From ec7a7314baea89972f6122334fe7263d777cbce1 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Thu, 15 Oct 2026 06:48:43 +0000 Subject: [PATCH 1/4] e2e: switch deploy-bink to Helm Replace the kustomize-based deploy with helm upgrade --install, matching the chart values used by the removed helm.yaml workflow. Use upgrade --install (not plain install) so the target is idempotent and works on repeated runs during development. Build the CRD dependency chart before installing so that CRDs are deployed automatically with the operator chart. Update the deployment name references from controller-manager to controller to match the Helm chart naming. Assisted-by: AI Signed-off-by: Alice Frosi --- Makefile | 22 ++++++++++++---------- test/e2e/bootcnode_test.go | 2 +- test/e2e/upgrade_test.go | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 432ceb6..f708cd8 100644 --- a/Makefile +++ b/Makefile @@ -245,17 +245,19 @@ start-bink: seed-node-image ## Start a bink cluster (idempotent). kubectl --kubeconfig $(KUBECONFIG_BINK) wait --for=condition=Ready node/controller --timeout=5m .PHONY: deploy-bink -deploy-bink: start-bink build-update-image $(if $(RELEASED_OPERATOR_IMG),push-released-operator-image) kustomize ## Deploy to a bink cluster (requires: buildimg). +deploy-bink: start-bink build-update-image $(if $(RELEASED_OPERATOR_IMG),push-released-operator-image) helm ## Deploy to a bink cluster (requires: buildimg). podman push --tls-verify=false $(IMG) localhost:5000/bootc-operator-e2e:latest - # On re-deploy, restart the rollout to force a re-pull of the :latest tag. - # On fresh deploy, skip the restart -- the pod is already pulling the correct image. - @existed=$$(kubectl --kubeconfig $(KUBECONFIG_BINK) -n bootc-operator get deploy bootc-operator-controller-manager -o name 2>/dev/null || true) && \ - $(MAKE) deploy KUBECONFIG=$(abspath $(KUBECONFIG_BINK)) IMG=$(IMG_BINK) \ - MANAGER_EXTRA_ARGS='"--allow-insecure-registry","--tag-resolution-interval=10s"' && \ - if [ -n "$$existed" ]; then \ - kubectl --kubeconfig $(KUBECONFIG_BINK) -n bootc-operator rollout restart deployment/bootc-operator-controller-manager; \ - fi - kubectl --kubeconfig $(KUBECONFIG_BINK) -n bootc-operator rollout status deployment/bootc-operator-controller-manager --timeout=3m + helm dependency build ./chart/bootc-operator + img="$(IMG_BINK)" && \ + helm upgrade --install bootc-operator ./chart/bootc-operator \ + --kubeconfig $(abspath $(KUBECONFIG_BINK)) \ + --create-namespace --namespace bootc-operator \ + --set image.repository="$${img%:*}" \ + --set image.tag="$${img##*:}" \ + --set image.pullPolicy=Always \ + --set-json 'controller.extraArgs=["--allow-insecure-registry","--tag-resolution-interval=10s"]' + kubectl --kubeconfig $(KUBECONFIG_BINK) -n bootc-operator rollout restart deployment/bootc-operator-controller + kubectl --kubeconfig $(KUBECONFIG_BINK) -n bootc-operator rollout status deployment/bootc-operator-controller --timeout=3m .PHONY: gather-bink gather-bink: ## Gather diagnostic logs from the bink cluster. diff --git a/test/e2e/bootcnode_test.go b/test/e2e/bootcnode_test.go index bb7667a..594defb 100644 --- a/test/e2e/bootcnode_test.go +++ b/test/e2e/bootcnode_test.go @@ -970,7 +970,7 @@ func scaleController(t *testing.T, env *e2eutil.Env, ctx context.Context, replic g := NewWithT(t) deployKey := client.ObjectKey{ Namespace: testutil.OperatorNamespaceName, - Name: "bootc-operator-controller-manager", + Name: "bootc-operator-controller", } var deploy appsv1.Deployment diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index 5458f65..b375b76 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -345,7 +345,7 @@ func kubectlApply(t *testing.T, manifest []byte) { t.Helper() kubeconfigPath := os.Getenv("KUBECONFIG") - args := []string{"apply", "--server-side", "-f", "-"} + args := []string{"apply", "--server-side", "--force-conflicts", "-f", "-"} if kubeconfigPath != "" { args = append([]string{"--kubeconfig", kubeconfigPath}, args...) } @@ -431,7 +431,7 @@ func waitForOperatorReady( func operatorDeployKey() client.ObjectKey { return client.ObjectKey{ Namespace: testutil.OperatorNamespaceName, - Name: "bootc-operator-controller-manager", + Name: "bootc-operator-controller", } } From 0633b5e051ad95db5918b0a10248b16808f5c6d2 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Thu, 15 Oct 2026 06:59:33 +0000 Subject: [PATCH 2/4] e2e: rewrite upgrade test to use Helm install/upgrade Replace the manifest-based upgrade test with Helm commands. The test now uses helm install for the released version and helm upgrade for the current version, matching how deploy-bink deploys the operator. On upgrade, install and upgrade CRDs via the bootc-operator-crds chart (using upgrade --install since the released version does not ship this chart). Uninstall CRDs via helm uninstall instead of manual deletion. Remove dead manifest-manipulation code: downloadReleaseManifest, patchManifestImage, setContainerImage, setContainerArgs, kubectlApply, applyCurrentManifests, kubectlApplyCRDs. Assisted-by: AI Signed-off-by: Alice Frosi --- test/e2e/upgrade_test.go | 355 ++++++++++++--------------------------- 1 file changed, 111 insertions(+), 244 deletions(-) diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index b375b76..0e02839 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -3,14 +3,12 @@ package e2e import ( - "bytes" "context" - "fmt" - "io" - "net/http" + "encoding/json" "os" "os/exec" "path/filepath" + "strings" "testing" "time" @@ -19,18 +17,14 @@ import ( corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - utilyaml "k8s.io/apimachinery/pkg/util/yaml" "sigs.k8s.io/controller-runtime/pkg/client" - sigsyaml "sigs.k8s.io/yaml" bootcv1alpha1 "github.com/bootc-dev/bootc-operator/api/v1alpha1" "github.com/bootc-dev/bootc-operator/test/e2e/e2eutil" testutil "github.com/bootc-dev/bootc-operator/test/util" ) -const ( - releaseManifestURL = "https://github.com/bootc-dev/bootc-operator/releases/download/%s/install.yaml" -) +const helmReleaseName = "bootc-operator" var operatorCRDNames = []string{ "bootcnodepools.node.bootc.dev", @@ -38,9 +32,9 @@ var operatorCRDNames = []string{ } // TestOperatorUpgrade installs the released version of the operator -// from its published manifest, verifies basic functionality, then -// upgrades by re-applying the current manifests (including CRDs) on -// top and verifies the operator still works. +// via Helm, verifies basic functionality, then upgrades by running +// helm upgrade with the current image and verifies the operator still +// works. func TestOperatorUpgrade(t *testing.T) { e2eutil.Providers(t, "bink") @@ -60,21 +54,29 @@ func TestOperatorUpgrade(t *testing.T) { env := e2eutil.New(t) ctx := context.Background() - // Capture the current operator image before we replace it. + repoRoot := findRepoRoot(t) + chartPath := filepath.Join(repoRoot, "chart", "bootc-operator") + + // Capture the current operator image and extra args before we + // replace it. var origDeploy appsv1.Deployment g.Expect(env.Client.Get(ctx, operatorDeployKey(), &origDeploy)).To(Succeed()) currentImg := containerImage(t, origDeploy.Spec.Template.Spec.Containers, "manager") - currentArgs := containerArgs(t, origDeploy.Spec.Template.Spec.Containers, "manager") + extraArgs := controllerExtraArgs(t, origDeploy.Spec.Template.Spec.Containers) t.Logf("Current operator image: %s", currentImg) t.Logf("Released operator tag: %s, image: %s", releaseTag, releasedImg) - // Phase 1: Delete the current operator and install the released - // version from its published manifest. - installReleasedOperator(t, g, ctx, env, releaseTag, releasedImg) + // Phase 1: Uninstall the current operator and re-install with + // the released image via Helm. + uninstallOperator(t, g, ctx, env) + helmInstallOperator(t, chartPath, releasedImg, extraArgs) + waitForOperatorReady(t, g, ctx, env.Client) + + t.Logf("Released operator %s installed via Helm", releaseTag) t.Cleanup(func() { t.Logf("Restoring operator to current version...") - applyCurrentManifests(t, currentImg, currentArgs) + helmUpgradeOperator(t, chartPath, currentImg, extraArgs) waitForOperatorReady(t, g, ctx, env.Client) t.Logf("Operator restored") }) @@ -89,11 +91,11 @@ func TestOperatorUpgrade(t *testing.T) { t.Logf("Node %q is Idle with released operator", nodeName) - // Phase 3: Upgrade by applying the current manifests on top. - applyCurrentManifests(t, currentImg, currentArgs) + // Phase 3: Upgrade via helm upgrade to the current version. + helmUpgradeOperator(t, chartPath, currentImg, extraArgs) waitForOperatorReady(t, g, ctx, env.Client) - t.Logf("Upgraded operator to current version via manifest apply") + t.Logf("Upgraded operator to current version via Helm") // Verify the pre-existing pool and node survived the upgrade. testutil.WaitForNodeIdle(t, g, ctx, env.Client, nodeName, 3*time.Minute) @@ -124,43 +126,18 @@ func TestOperatorUpgrade(t *testing.T) { Should(poolAllUpdated(1, env.NodeImageUpdateDigest())) } -// installReleasedOperator deletes the current operator, downloads the -// released install manifest, patches the image reference, and applies -// it. -func installReleasedOperator( +// uninstallOperator removes the operator via Helm uninstall, then +// deletes CRDs (which Helm does not manage on uninstall). Custom +// resources are deleted first while the operator is still running so +// it can handle finalizer removal. +func uninstallOperator( t *testing.T, g Gomega, ctx context.Context, env *e2eutil.Env, - releaseTag, releasedImg string, ) { t.Helper() - deleteCurrentOperator(t, g, ctx, env) - - manifest := downloadReleaseManifest(t, releaseTag) - patchedManifest := patchManifestImage(t, manifest, releasedImg, nil) - - kubectlApply(t, patchedManifest) - waitForOperatorReady(t, g, ctx, env.Client) - - t.Logf("Released operator %s installed from manifest", releaseTag) -} - -// deleteCurrentOperator deletes custom resources (while the operator -// is still running so it can handle finalizer removal), then removes -// the operator Deployment, DaemonSet, and CRDs. -func deleteCurrentOperator( - t *testing.T, - g Gomega, - ctx context.Context, - env *e2eutil.Env, -) { - t.Helper() - - // Delete CRs first while the operator is running so it can - // remove finalizers. If CRs with finalizers remain when the - // controller is gone, CRD deletion hangs indefinitely. t.Logf("Deleting custom resources...") g.Expect(env.Client.DeleteAllOf(ctx, &bootcv1alpha1.BootcNodePool{})).To(Succeed()) g.Expect(env.Client.DeleteAllOf(ctx, &bootcv1alpha1.BootcNode{})).To(Succeed()) @@ -175,28 +152,16 @@ func deleteCurrentOperator( }).WithTimeout(2*time.Minute).Should(Succeed(), "expected all custom resources to be deleted") - var deploy appsv1.Deployment - g.Expect(env.Client.Get(ctx, operatorDeployKey(), &deploy)).To(Succeed()) - var ds appsv1.DaemonSet - g.Expect(env.Client.Get(ctx, operatorDaemonSetKey(), &ds)).To(Succeed()) - - t.Logf("Deleting operator deployment, daemonset, and CRDs...") - g.Expect(env.Client.Delete(ctx, &deploy)).To(Succeed()) - g.Expect(env.Client.Delete(ctx, &ds)).To(Succeed()) - - for _, crdName := range operatorCRDNames { - var crd apiextensionsv1.CustomResourceDefinition - if err := env.Client.Get(ctx, client.ObjectKey{Name: crdName}, &crd); err == nil { - g.Expect(env.Client.Delete(ctx, &crd)).To(Succeed()) - } - } + t.Logf("Uninstalling Helm release...") + helmRun(t, "uninstall", helmReleaseName, + "--namespace", testutil.OperatorNamespaceName) g.Eventually(func(g Gomega) { var d appsv1.Deployment err := env.Client.Get(ctx, operatorDeployKey(), &d) g.Expect(apierrors.IsNotFound(err)).To(BeTrue()) - var dset appsv1.DaemonSet - err = env.Client.Get(ctx, operatorDaemonSetKey(), &dset) + var ds appsv1.DaemonSet + err = env.Client.Get(ctx, operatorDaemonSetKey(), &ds) g.Expect(apierrors.IsNotFound(err)).To(BeTrue()) for _, crdName := range operatorCRDNames { var crd apiextensionsv1.CustomResourceDefinition @@ -206,207 +171,98 @@ func deleteCurrentOperator( }).WithTimeout(2*time.Minute).Should(Succeed(), "expected operator resources to be deleted") - t.Logf("Operator deployment, daemonset, and CRDs deleted") + t.Logf("Operator uninstalled") } -// downloadReleaseManifest fetches install.yaml from a GitHub release. -func downloadReleaseManifest(t *testing.T, tag string) []byte { +// helmInstallOperator installs the operator via helm install. +func helmInstallOperator(t *testing.T, chartPath, img string, extraArgs []string) { t.Helper() - - url := fmt.Sprintf(releaseManifestURL, tag) - t.Logf("Downloading release manifest from %s", url) - - resp, err := http.Get(url) //nolint:gosec - if err != nil { - t.Fatalf("downloading release manifest: %v", err) - } - defer func() { _ = resp.Body.Close() }() - - if resp.StatusCode != http.StatusOK { - t.Fatalf("downloading release manifest: HTTP %d", resp.StatusCode) - } - - data, err := io.ReadAll(resp.Body) - if err != nil { - t.Fatalf("reading release manifest body: %v", err) + args := []string{ + "install", helmReleaseName, chartPath, + "--namespace", testutil.OperatorNamespaceName, + "--create-namespace", } - - return data + args = append(args, helmImageArgs(img, extraArgs)...) + helmRun(t, args...) } -// patchManifestImage replaces container image references in -// Deployment (manager) and DaemonSet (daemon) documents. -func patchManifestImage( - t *testing.T, - manifest []byte, - img string, - managerArgs []string, -) []byte { +// helmUpgradeOperator upgrades the operator via helm upgrade. +func helmUpgradeOperator(t *testing.T, chartPath, img string, extraArgs []string) { t.Helper() - - var out bytes.Buffer - reader := utilyaml.NewDocumentDecoder(io.NopCloser(bytes.NewReader(manifest))) - defer func() { _ = reader.Close() }() - - first := true - for { - buf := make([]byte, len(manifest)+256) - n, err := reader.Read(buf) - if err != nil { - if err == io.EOF { - break - } - t.Fatalf("reading YAML document: %v", err) - } - doc := buf[:n] - - var obj map[string]interface{} - if err := sigsyaml.Unmarshal(doc, &obj); err != nil { - t.Fatalf("unmarshaling YAML document: %v", err) - } - - kind, _ := obj["kind"].(string) - switch kind { - case "Deployment": - setContainerImage(t, obj, "manager", img) - if len(managerArgs) > 0 { - setContainerArgs(t, obj, "manager", managerArgs) - } - case "DaemonSet": - setContainerImage(t, obj, "daemon", img) - } - - patched, err := sigsyaml.Marshal(obj) - if err != nil { - t.Fatalf("marshaling patched %s: %v", kind, err) - } - - if !first { - out.WriteString("---\n") - } - out.Write(patched) - first = false + args := []string{ + "upgrade", helmReleaseName, chartPath, + "--namespace", testutil.OperatorNamespaceName, } - - return out.Bytes() + args = append(args, helmImageArgs(img, extraArgs)...) + helmRun(t, args...) } -// setContainerImage patches the image field of a named container in a -// Deployment or DaemonSet manifest map. -func setContainerImage(t *testing.T, obj map[string]interface{}, containerName, img string) { - t.Helper() - - spec, _ := obj["spec"].(map[string]interface{}) - template, _ := spec["template"].(map[string]interface{}) - podSpec, _ := template["spec"].(map[string]interface{}) - containers, _ := podSpec["containers"].([]interface{}) - - for _, c := range containers { - container, _ := c.(map[string]interface{}) - if name, _ := container["name"].(string); name == containerName { - container["image"] = img - return - } +// helmImageArgs returns the --set flags for image and controller args. +func helmImageArgs(img string, extraArgs []string) []string { + repo, tag := splitImage(img) + args := []string{ + "--set", "image.repository=" + repo, + "--set", "image.tag=" + tag, + "--set", "image.pullPolicy=Always", } - t.Fatalf("container %q not found in %s", containerName, obj["kind"]) -} - -// setContainerArgs replaces the args of a named container in a -// Deployment or DaemonSet manifest map. -func setContainerArgs( - t *testing.T, - obj map[string]interface{}, - containerName string, - args []string, -) { - t.Helper() - - spec, _ := obj["spec"].(map[string]interface{}) - template, _ := spec["template"].(map[string]interface{}) - podSpec, _ := template["spec"].(map[string]interface{}) - containers, _ := podSpec["containers"].([]interface{}) - - for _, c := range containers { - container, _ := c.(map[string]interface{}) - if name, _ := container["name"].(string); name == containerName { - ifaceArgs := make([]interface{}, len(args)) - for i, a := range args { - ifaceArgs[i] = a - } - container["args"] = ifaceArgs - return + if len(extraArgs) > 0 { + j, err := json.Marshal(extraArgs) + if err != nil { + panic("marshaling extraArgs: " + err.Error()) } + args = append(args, "--set-json", "controller.extraArgs="+string(j)) } - t.Fatalf("container %q not found in %s", containerName, obj["kind"]) + return args } -// kubectlApply applies the given manifest bytes via kubectl. -func kubectlApply(t *testing.T, manifest []byte) { +// helmRun executes a helm command, adding --kubeconfig if set. +func helmRun(t *testing.T, args ...string) { t.Helper() - kubeconfigPath := os.Getenv("KUBECONFIG") - args := []string{"apply", "--server-side", "--force-conflicts", "-f", "-"} - if kubeconfigPath != "" { - args = append([]string{"--kubeconfig", kubeconfigPath}, args...) + subcmd := args[0] + if kc := os.Getenv("KUBECONFIG"); kc != "" { + args = append([]string{"--kubeconfig", kc}, args...) } - cmd := exec.Command("kubectl", args...) - cmd.Stdin = bytes.NewReader(manifest) - + cmd := exec.Command("helm", args...) out, err := cmd.CombinedOutput() if err != nil { - t.Fatalf("kubectl apply failed: %v\n%s", err, out) + t.Fatalf("helm %s failed: %v\n%s", subcmd, err, out) } - - t.Logf("kubectl apply:\n%s", out) + t.Logf("helm %s:\n%s", subcmd, out) } -// applyCurrentManifests runs the equivalent of "make deploy" for the -// current version: kustomize build + image patch + kubectl apply. -func applyCurrentManifests( - t *testing.T, - img string, - managerArgs []string, -) { - t.Helper() - - repoRoot := findRepoRoot(t) - - kustomize := filepath.Join(repoRoot, "bin", "kustomize") - if _, err := os.Stat(kustomize); err != nil { - kustomize = "kustomize" +// splitImage splits a container image reference into repository and tag. +func splitImage(ref string) (repo, tag string) { + lastSlash := strings.LastIndex(ref, "/") + lastColon := strings.LastIndex(ref, ":") + if lastColon > lastSlash { + return ref[:lastColon], ref[lastColon+1:] } - - cmd := exec.Command(kustomize, "build", filepath.Join(repoRoot, "config", "default")) - manifest, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("kustomize build failed: %v\n%s", err, manifest) - } - - manifest = patchManifestImage(t, manifest, img, managerArgs) - kubectlApply(t, manifest) + return ref, "latest" } -// findRepoRoot walks up from the test directory to find the repository -// root (containing go.mod). -func findRepoRoot(t *testing.T) string { +// controllerExtraArgs returns the controller's extra arguments, +// filtering out the flags that the Helm chart always includes. +func controllerExtraArgs(t *testing.T, containers []corev1.Container) []string { t.Helper() - - dir, err := os.Getwd() - if err != nil { - t.Fatalf("getting working directory: %v", err) - } - - for { - if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { - return dir + for _, c := range containers { + if c.Name != "manager" { + continue } - parent := filepath.Dir(dir) - if parent == dir { - t.Fatal("could not find repository root (go.mod)") + var extra []string + for _, arg := range c.Args { + switch { + case arg == "--leader-elect", + strings.HasPrefix(arg, "--health-probe-bind-address="): + default: + extra = append(extra, arg) + } } - dir = parent + return extra } + t.Fatalf("container %q not found in pod spec", "manager") + return nil } // waitForOperatorReady polls until the operator deployment has one available and up-to-date replica. @@ -455,13 +311,24 @@ func containerImage(t *testing.T, containers []corev1.Container, name string) st return "" } -func containerArgs(t *testing.T, containers []corev1.Container, name string) []string { +// findRepoRoot walks up from the test directory to find the repository +// root (containing go.mod). +func findRepoRoot(t *testing.T) string { t.Helper() - for _, c := range containers { - if c.Name == name { - return c.Args + + dir, err := os.Getwd() + if err != nil { + t.Fatalf("getting working directory: %v", err) + } + + for { + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir } + parent := filepath.Dir(dir) + if parent == dir { + t.Fatal("could not find repository root (go.mod)") + } + dir = parent } - t.Fatalf("container %q not found in pod spec", name) - return nil } From 77ec2efc631a2c4be62aff218f9c157d6fd83137 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Fri, 16 Oct 2026 09:24:01 +0000 Subject: [PATCH 3/4] e2e: default RELEASED_OPERATOR_TAG in Makefile Move RELEASED_OPERATOR_TAG and RELEASED_OPERATOR_IMG defaults into the Makefile so CI does not need to pass them explicitly. Both remain overridable on the command line. Signed-off-by: Alice Frosi --- .github/workflows/ci.yaml | 5 ----- Makefile | 11 ++++------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b6faf24..d68dd1f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,7 +9,6 @@ on: env: BINK_COMMIT: c7c4013e1275f07fe6ee90be92b61d256117460f - RELEASED_OPERATOR_TAG: v0.1.1 permissions: contents: read @@ -115,8 +114,6 @@ jobs: - name: Deploy to bink cluster run: make deploy-bink - env: - RELEASED_OPERATOR_IMG: ghcr.io/${{ github.repository }}:${{ env.RELEASED_OPERATOR_TAG }} - name: Gather deploy logs if: failure() @@ -124,8 +121,6 @@ jobs: - name: Run e2e tests run: make e2e V=1 - env: - RELEASED_OPERATOR_IMG: ghcr.io/${{ github.repository }}:${{ env.RELEASED_OPERATOR_TAG }} - name: Upload logs if: always() diff --git a/Makefile b/Makefile index f708cd8..bba0b9d 100644 --- a/Makefile +++ b/Makefile @@ -17,13 +17,10 @@ BINK_NODE_DISK_IMAGE ?= ghcr.io/bootc-dev/bink/node:v$(DEFAULT_KUBE_MINOR)-fedor BINK_LOCAL_REGISTRY_NODE_IMAGE ?= registry.cluster.local:5000/node E2E_REGISTRY_USER ?= e2e-user E2E_REGISTRY_PASSWORD ?= e2e-password -# Released operator for upgrade testing (set to run TestOperatorUpgrade). -# RELEASED_OPERATOR_TAG: GitHub release tag to download install.yaml from. -# RELEASED_OPERATOR_IMG: container image to use (defaults to upstream, override for downstream). -# Example: RELEASED_OPERATOR_TAG=v0.1.0 -# RELEASED_OPERATOR_IMG=ghcr.io/bootc-dev/bootc-operator:v0.1.0 -RELEASED_OPERATOR_TAG ?= -RELEASED_OPERATOR_IMG ?= +# Released operator for upgrade testing (TestOperatorUpgrade). +# Override RELEASED_OPERATOR_IMG for downstream images. +RELEASED_OPERATOR_TAG ?= v0.2.1 +RELEASED_OPERATOR_IMG ?= ghcr.io/bootc-dev/bootc-operator:$(RELEASED_OPERATOR_TAG) IMG_BINK_RELEASED ?= registry.cluster.local:5000/bootc-operator-released:latest # YEAR defines the year value used for substituting the YEAR placeholder in the boilerplate header. YEAR ?= $(shell date +%Y) From 16bf0c829a01d3d8bcfd0a2707baaa0b82bb17f0 Mon Sep 17 00:00:00 2001 From: Alice Frosi Date: Fri, 16 Oct 2026 10:16:54 +0000 Subject: [PATCH 4/4] ci: remove helm.yaml workflow The main CI workflow now deploys via Helm, making the separate Helm workflow redundant. Signed-off-by: Alice Frosi --- .github/workflows/helm.yaml | 111 ------------------------------------ 1 file changed, 111 deletions(-) delete mode 100644 .github/workflows/helm.yaml diff --git a/.github/workflows/helm.yaml b/.github/workflows/helm.yaml deleted file mode 100644 index 4a9fa18..0000000 --- a/.github/workflows/helm.yaml +++ /dev/null @@ -1,111 +0,0 @@ -name: Helm - -on: - push: - branches: [main, release-*] - pull_request: - branches: [main, release-*] - -env: - BINK_COMMIT: c7c4013e1275f07fe6ee90be92b61d256117460f - -permissions: - contents: read - -concurrency: - group: helm-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - build-bink: - uses: $/.github/workflows/build-bink.yaml - with: - bink-commit: c7c4013e1275f07fe6ee90be92b61d256117460f - - build-operator: - uses: $/.github/workflows/build-operator.yaml - - helm-e2e: - runs-on: ubuntu-latest - needs: [build-bink, build-operator] - timeout-minutes: 30 - permissions: - contents: read - env: - BINK_NODE_DISK_IMAGE: ghcr.io/bootc-dev/bink/node@sha256:d3077c99027db0c196d5c6531ef07b8955be827651b9e3d2bc4b8e7c6ebf5612 - steps: - - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Download bink binary - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: bink - path: /usr/local/bin - - - name: Make bink executable - run: chmod +x /usr/local/bin/bink - - - name: Set up Go - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 - with: - go-version-file: go.mod - cache: true # zizmor: ignore[cache-poisoning] - - - name: Set up bink environment - uses: $/.github/actions/setup-bink-env - - - name: Download operator image - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: operator-image - - - name: Load operator image - run: podman load -i operator-image.tar - - - name: Start bink cluster - run: make start-bink - - - name: Build update images - run: make build-update-image - - - name: Push operator image to bink registry - run: podman push --tls-verify=false bootc-operator:dev localhost:5000/bootc-operator:dev - - - name: Generate Helm chart - run: make helm - - - name: Install Helm charts - run: | - helm dependency build ./chart/bootc-operator - helm install bootc-operator ./chart/bootc-operator \ - --kubeconfig $(pwd)/kubeconfig-e2e \ - --create-namespace --namespace bootc-operator \ - --set image.repository=registry.cluster.local:5000/bootc-operator \ - --set image.tag=dev \ - --set image.pullPolicy=Always \ - --set-json 'controller.extraArgs=["--allow-insecure-registry"]' - - - name: Verify controller is running - run: | - kubectl --kubeconfig $(pwd)/kubeconfig-e2e -n bootc-operator \ - rollout status deployment/bootc-operator-controller --timeout=3m - kubectl --kubeconfig $(pwd)/kubeconfig-e2e -n bootc-operator \ - get pods - - - name: Run e2e smoke tests - run: make e2e RUN='TestCRDSmoke|TestControllerMembership' V=1 - - - name: Gather logs on failure - if: failure() - run: make gather-bink - - - name: Upload logs - if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: helm-e2e-logs - path: _output/logs/ - if-no-files-found: ignore