Skip to content

🌱 Migrate operator upgrade e2e tests to Godog/Cucumber BDD framework#2538

Open
pedjak wants to merge 1 commit intooperator-framework:mainfrom
pedjak:migrate-upgrade-tests
Open

🌱 Migrate operator upgrade e2e tests to Godog/Cucumber BDD framework#2538
pedjak wants to merge 1 commit intooperator-framework:mainfrom
pedjak:migrate-upgrade-tests

Conversation

@pedjak
Copy link
Contributor

@pedjak pedjak commented Mar 4, 2026

Description

Replace testify-based upgrade tests with a Godog test runner and Gherkin
feature file. Add step definitions for OLM install/upgrade, component
readiness via leader election leases, and reconciliation verification.

Simplify Makefile upgrade targets using a reusable install script macro
and fix template path resolution so tests work from any directory.

Reviewer Checklist

  • API Go Documentation
  • Tests: Unit Tests (and E2E Tests, if appropriate)
  • Comprehensive Commit Messages
  • Links to related GitHub Issue(s)

Copilot AI review requested due to automatic review settings March 4, 2026 21:43
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 4, 2026
@netlify
Copy link

netlify bot commented Mar 4, 2026

Deploy Preview for olmv1 ready!

Name Link
🔨 Latest commit 56dddb8
🔍 Latest deploy log https://app.netlify.com/projects/olmv1/deploys/69b33da76eb5de000881b069
😎 Deploy Preview https://deploy-preview-2538--olmv1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the operator upgrade E2E validation from Go testing-based post-upgrade checks to Godog/Cucumber feature scenarios, integrating upgrade workflows into the existing Godog step framework used elsewhere in the repo.

Changes:

  • Replaces test/upgrade-e2e Go upgrade tests with a Godog TestMain runner plus a new operator-upgrade.feature.
  • Adds upgrade-focused Godog step implementations (install latest release, upgrade, reconcile/lease/log checks).
  • Updates shared Godog step utilities/templates and Makefile targets to support the new upgrade test flow.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/upgrade-e2e/upgrade_test.go New Godog test runner for upgrade scenarios
test/upgrade-e2e/upgrade_e2e_suite_test.go Removes old TestMain env/client bootstrap
test/upgrade-e2e/post_upgrade_test.go Removes prior Go testing upgrade assertions
test/upgrade-e2e/features/operator-upgrade.feature Adds cucumber scenarios for upgrade validation
test/e2e/steps/upgrade_steps.go Implements upgrade-specific Godog steps
test/e2e/steps/steps.go Registers upgrade steps and adjusts template path handling / catalog setup
test/e2e/steps/hooks.go Adds scenario context fields and OLM deployment detection helper
test/e2e/steps/testdata/rbac-template.yaml Updates RBAC template for upgrade scenario needs
Makefile Adds install script generation + new upgrade-e2e make targets

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- apiGroups: [olm.operatorframework.io]
resources: [clusterextensions, clusterextensions/finalizers]
resourceNames: ["${CLUSTEREXTENSION_NAME}"]
resourceNames: ["${CLUSTEREXTENSION_NAME}", "upgrade-ce"]
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This RBAC template now hard-codes upgrade-ce in resourceNames, coupling a shared template to one specific test resource and broadening permissions unintentionally for other scenarios. Keep the template parameterized (only ${CLUSTEREXTENSION_NAME}) and instead ensure the scenario context sets clusterExtensionName to the intended name for upgrade scenarios (e.g., via the step that applies the ClusterExtension or by passing the name into the SA/RBAC step).

Suggested change
resourceNames: ["${CLUSTEREXTENSION_NAME}", "upgrade-ce"]
resourceNames: ["${CLUSTEREXTENSION_NAME}"]

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +63
var cmd *exec.Cmd
if u, err := url.Parse(scriptPath); err == nil && u.Scheme != "" {
cmd = exec.Command("bash", "-c", fmt.Sprintf("curl -L -s %s | bash -s", scriptPath))
} else {
cmd = exec.Command("bash", scriptPath)
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runInstallScript builds a bash -c command with the env-provided script path interpolated into the shell string. This is brittle (URLs containing shell-special characters can break) and introduces avoidable shell-injection risk even in test code. Prefer executing curl with arguments (no shell) and then running bash on the downloaded content, or require a local path and run bash <path> directly.

Copilot uses AI. Check for mistakes.
define install-sh
.PHONY: $(1)/install.sh
$(1)/install.sh: manifests
@echo -e "\n\U1F4D8 Using $(1).yaml as source manifest\n"
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This recipe uses echo -e with \U... escapes. echo -e and Unicode escape handling vary across /bin/sh implementations, so this can break in some environments. Prefer printf for portable escape/newline handling.

Suggested change
@echo -e "\n\U1F4D8 Using $(1).yaml as source manifest\n"
@printf '\n\U1F4D8 Using %s.yaml as source manifest\n\n' "$(1)"

Copilot uses AI. Check for mistakes.
@pedjak pedjak force-pushed the migrate-upgrade-tests branch from 102561e to 6ec1572 Compare March 4, 2026 22:03
@codecov
Copy link

codecov bot commented Mar 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.63%. Comparing base (f19c8c9) to head (56dddb8).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2538      +/-   ##
==========================================
+ Coverage   68.61%   68.63%   +0.02%     
==========================================
  Files         131      131              
  Lines        9333     9333              
==========================================
+ Hits         6404     6406       +2     
+ Misses       2438     2437       -1     
+ Partials      491      490       -1     
Flag Coverage Δ
e2e 42.26% <ø> (+0.02%) ⬆️
experimental-e2e 51.62% <ø> (+0.02%) ⬆️
unit 53.84% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pedjak pedjak force-pushed the migrate-upgrade-tests branch from 6ec1572 to 5d17dc0 Compare March 4, 2026 22:33
@pedjak pedjak changed the title 🌱 Migrate operator upgrade tests to Godog/cucumber 🌱 Migrate operator upgrade e2e tests to Godog/Cucumber BDD framework Mar 4, 2026
@pedjak pedjak marked this pull request as ready for review March 4, 2026 22:36
Copilot AI review requested due to automatic review settings March 4, 2026 22:36
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 4, 2026
@pedjak pedjak requested review from dtfranz and perdasilva March 4, 2026 22:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 102 to 105
for _, d := range dl {
if d.Name == olmDeploymentName {
olm = &d
olmNamespace = d.Namespace
break
return &d, nil
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning &d here takes the address of the range loop variable. It’s safe today because you return immediately, but it’s a common footgun and easy to break if the code is refactored (e.g., storing pointers). Prefer iterating by index and returning &dl[i].

Copilot uses AI. Check for mistakes.
}
var cmd *exec.Cmd
if u, err := url.Parse(scriptPath); err == nil && u.Scheme != "" {
cmd = exec.Command("bash", "-c", fmt.Sprintf("curl -L -s %s | bash -s", scriptPath)) //nolint:gosec // scriptPath is from a trusted env variable
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL install path uses a shell pipeline (curl ... | bash) without pipefail / -f, so a failed download can still result in an empty script being executed and the command succeeding. Consider executing curl directly (no shell), or at least use curl -f and set -o pipefail, and quote/escape the URL so special characters don’t break the command.

Suggested change
cmd = exec.Command("bash", "-c", fmt.Sprintf("curl -L -s %s | bash -s", scriptPath)) //nolint:gosec // scriptPath is from a trusted env variable
cmd = exec.Command("bash", "-c", fmt.Sprintf("set -o pipefail; curl -fsSL %q | bash -s", scriptPath)) //nolint:gosec // scriptPath is from a trusted env variable

Copilot uses AI. Check for mistakes.
Comment on lines +242 to +246
.PHONY: $(1)/install.sh
$(1)/install.sh: manifests
@echo -e "\n\U1F4D8 Using $(1).yaml as source manifest\n"
sed "s/cert-git-version/cert-$$(VERSION)/g" manifests/$(1).yaml > $(2)
MANIFEST=$(2) INSTALL_DEFAULT_CATALOGS=false DEFAULT_CATALOG=$$(RELEASE_CATALOGS) envsubst '$$$$DEFAULT_CATALOG,$$$$CERT_MGR_VERSION,$$$$INSTALL_DEFAULT_CATALOGS,$$$$MANIFEST' < scripts/install.tpl.sh > $(1)-install.sh
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

install-sh defines a phony target named $(1)/install.sh, but the recipe actually writes $(1)-install.sh (and also writes the manifest to $(2) in the repo root). This mismatch makes the target name misleading and can leave generated artifacts around unintentionally. Consider aligning target/output names (or making the generated files the actual targets) and placing generated artifacts under a dedicated build/output dir or ensuring they’re cleaned up.

Suggested change
.PHONY: $(1)/install.sh
$(1)/install.sh: manifests
@echo -e "\n\U1F4D8 Using $(1).yaml as source manifest\n"
sed "s/cert-git-version/cert-$$(VERSION)/g" manifests/$(1).yaml > $(2)
MANIFEST=$(2) INSTALL_DEFAULT_CATALOGS=false DEFAULT_CATALOG=$$(RELEASE_CATALOGS) envsubst '$$$$DEFAULT_CATALOG,$$$$CERT_MGR_VERSION,$$$$INSTALL_DEFAULT_CATALOGS,$$$$MANIFEST' < scripts/install.tpl.sh > $(1)-install.sh
.PHONY: $(1)-install.sh
$(1)-install.sh: manifests
@echo -e "\n\U1F4D8 Using $(1).yaml as source manifest\n"
sed "s/cert-git-version/cert-$$(VERSION)/g" manifests/$(1).yaml > $(2)
MANIFEST=$(2) INSTALL_DEFAULT_CATALOGS=false DEFAULT_CATALOG=$$(RELEASE_CATALOGS) envsubst '$$$$DEFAULT_CATALOG,$$$$CERT_MGR_VERSION,$$$$INSTALL_DEFAULT_CATALOGS,$$$$MANIFEST' < scripts/install.tpl.sh > $@

Copilot uses AI. Check for mistakes.
@pedjak pedjak force-pushed the migrate-upgrade-tests branch from 5d17dc0 to d2239a3 Compare March 5, 2026 07:19
Copilot AI review requested due to automatic review settings March 5, 2026 09:15
@pedjak pedjak force-pushed the migrate-upgrade-tests branch from d2239a3 to c053f87 Compare March 5, 2026 09:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +845 to +849
// ServiceAccountWithNeededPermissionsIsAvailableInNamespace creates a ServiceAccount and applies standard RBAC permissions.
func ServiceAccountWithNeededPermissionsIsAvailableInGivenNamespace(ctx context.Context, serviceAccount string, ns string) error {
sc := scenarioCtx(ctx)
sc.namespace = ns
return applyPermissionsToServiceAccount(ctx, serviceAccount, "rbac-template.yaml")
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServiceAccountWithNeededPermissionsIsAvailableInGivenNamespace mutates sc.namespace to the caller-provided value. In suites that register ScenarioCleanup, this will cause cleanup to attempt to delete that namespace (e.g., if someone passes default, the test will try to delete the default namespace). Consider passing the namespace through to applyServiceAccount / applyPermissionsToServiceAccount (or introducing a dedicated field like serviceAccountNamespace) instead of reassigning the scenario’s primary namespace.

Copilot uses AI. Check for mistakes.
sc.Step(`^(?i)ServiceAccount "([^"]*)" with needed permissions is available in \${TEST_NAMESPACE}$`, ServiceAccountWithNeededPermissionsIsAvailableInNamespace)
sc.Step(`^(?i)ServiceAccount "([^"]*)" with permissions to install extensions is available in "([^"]*)" namespace$`, ServiceAccountWithNeededPermissionsIsAvailableInGivenNamespace)
sc.Step(`^(?i)ServiceAccount "([^"]*)" with needed permissions is available in test namespace$`, ServiceAccountWithNeededPermissionsIsAvailableInTestNamespace)
sc.Step(`^(?i)ServiceAccount "([^"]*)" with needed permissions is available in \${TEST_NAMESPACE}$`, ServiceAccountWithNeededPermissionsIsAvailableInTestNamespace)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we may need to rebase as there's been a recent change affecting ServiceAccountWithNeededPermissionsIsAvailableInNamespace

olmNamespace = "olmv1-system"
kubeconfigPath string
k8sCli string
deployImageRegistry = sync.OnceValue(func() error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to make this just part of BeforeSuite?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to make this just part of BeforeSuite?

Currently, image-registry depends on the installation of OLM - it uses a CA certificate to create its own. It is a bit of unfortunate, but in these sort of tests, we would like to install and upgrade OLM as a part of test scenario. Thus, we cannot put this logic in BeforeSuite, because OLM is not installed at that point. Perhaps we could relax OLM installation a bit so that it could use already installed certificate, but that requires moving us to Helm installation method. Anyhow, that would make this PR a way larger.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense! thank you =D

Replace testify-based upgrade tests with a Godog test runner and Gherkin
feature file. Add step definitions for OLM install/upgrade, component
readiness via leader election leases, and reconciliation verification.

Simplify Makefile upgrade targets using a reusable install script macro
and fix template path resolution so tests work from any directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 12, 2026 22:26
@pedjak pedjak force-pushed the migrate-upgrade-tests branch from 36ad16e to 56dddb8 Compare March 12, 2026 22:26
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +875 to +877
if err := applyServiceAccount(ctx, serviceAccount, "TEST_NAMESPACE", ns); err != nil {
return err
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServiceAccountWithNeededPermissionsIsAvailableInGivenNamespace applies the ServiceAccount in the provided ns, but then calls applyPermissionsToServiceAccount, which (currently) also calls applyServiceAccount using the scenario’s default sc.namespace. This creates an extra ServiceAccount/Namespace unrelated to the provided namespace. Consider adjusting applyPermissionsToServiceAccount to pass the same TEST_NAMESPACE override through to applyServiceAccount (or skipping the duplicate call here) so the ServiceAccount is only created in the intended namespace.

Suggested change
if err := applyServiceAccount(ctx, serviceAccount, "TEST_NAMESPACE", ns); err != nil {
return err
}

Copilot uses AI. Check for mistakes.
Comment on lines 390 to 392
test-st2ex-e2e: export MANIFEST := $(STANDARD_RELEASE_MANIFEST)
test-st2ex-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog
test-st2ex-e2e: export TEST_CLUSTER_EXTENSION_NAME := test-package
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test-st2ex-e2e still exports MANIFEST, TEST_CLUSTER_CATALOG_NAME, and TEST_CLUSTER_EXTENSION_NAME, but the upgrade test flow no longer consumes these variables (the old pre/post upgrade scripts were removed and the new Godog feature hard-codes the resource names). These exports are now dead configuration and can be removed to avoid confusion about what the upgrade tests actually use.

Suggested change
test-st2ex-e2e: export MANIFEST := $(STANDARD_RELEASE_MANIFEST)
test-st2ex-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog
test-st2ex-e2e: export TEST_CLUSTER_EXTENSION_NAME := test-package

Copilot uses AI. Check for mistakes.
test-st2ex-e2e: export TEST_CLUSTER_CATALOG_NAME := test-catalog
test-st2ex-e2e: export TEST_CLUSTER_EXTENSION_NAME := test-package
test-st2ex-e2e: run-internal image-registry pre-upgrade-setup kind-deploy-experimental post-upgrade-checks kind-clean #HELP Run swichover (standard -> experimental) e2e tests on a local kind cluster
test-st2ex-e2e: experimental/install.sh standard/install.sh $(TEST_UPGRADE_E2E_TASKS) #HELP Run swichover (standard -> experimental) e2e tests on a local kind cluster
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in help text: swichover should be switchover.

Suggested change
test-st2ex-e2e: experimental/install.sh standard/install.sh $(TEST_UPGRADE_E2E_TASKS) #HELP Run swichover (standard -> experimental) e2e tests on a local kind cluster
test-st2ex-e2e: experimental/install.sh standard/install.sh $(TEST_UPGRADE_E2E_TASKS) #HELP Run switchover (standard -> experimental) e2e tests on a local kind cluster

Copilot uses AI. Check for mistakes.
@pedjak
Copy link
Contributor Author

pedjak commented Mar 13, 2026

/override go-apidiff

this PR does not touch any of API

@openshift-ci
Copy link

openshift-ci bot commented Mar 13, 2026

@pedjak: Overrode contexts on behalf of pedjak: go-apidiff

Details

In response to this:

/override go-apidiff

this PR does not touch any of API

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Copy link
Member

@rashmigottipati rashmigottipati left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Mar 13, 2026
@tmshort
Copy link
Contributor

tmshort commented Mar 13, 2026

/approve

@openshift-ci
Copy link

openshift-ci bot commented Mar 13, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: rashmigottipati, tmshort

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 13, 2026
@tmshort
Copy link
Contributor

tmshort commented Mar 13, 2026

/override go-apidiff

@openshift-ci
Copy link

openshift-ci bot commented Mar 13, 2026

@tmshort: Overrode contexts on behalf of tmshort: go-apidiff

Details

In response to this:

/override go-apidiff

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants