Skip to content

ROX-30858: Consolidate operator image builds#19820

Open
janisz wants to merge 1 commit intomasterfrom
ROX-30858/unify-branding-builds
Open

ROX-30858: Consolidate operator image builds#19820
janisz wants to merge 1 commit intomasterfrom
ROX-30858/unify-branding-builds

Conversation

@janisz
Copy link
Copy Markdown
Contributor

@janisz janisz commented Apr 3, 2026

Problem: The build workflow was building operator images separately for RHACS_BRANDING and STACKROX_BRANDING (4 builds total: 2 brandings × 2 architectures), even though the Docker layers are identical. The only difference between builds was the target registry
(quay.io/rhacs-eng vs quay.io/stackrox-io).

Investigation showed:

  • operator/prebuilt.Dockerfile contains no ROX_PRODUCT_BRANDING
  • Operator Go code has no branding references
  • Binary builds are identical regardless of branding
  • Only the registry tag differs between variants

Solution: Build once per architecture, tag and push to both registries.

Changes:

  • Matrix definition: removed branding dimension from build_and_push_operator, added registry dimension to push_operator_multiarch_manifests
  • build-and-push-operator job: build with IMAGE_REPO=stackrox to create local tag, then push to both quay.io/rhacs-eng and quay.io/stackrox-io
  • Added push_operator_image_to_registry() function that accepts registry parameter instead of deriving it from branding
  • Added push_operator_image_manifest_lists() function for registry-based manifest push (follows scanner-build.yaml pattern)

Benefits:

  • Reduces operator builds from 4 to 2 (50% reduction)
  • Saves ~5-8 minutes per workflow run
  • Images remain available at same registry locations (no breaking changes)

Follows existing pattern from scanner-build.yaml which already uses registry-based matrix instead of branding matrix.

Description

change me!

User-facing documentation

Testing and quality

  • the change is production ready: the change is GA, or otherwise the functionality is gated by a feature flag
  • CI results are inspected

Automated testing

  • added unit tests
  • added e2e tests
  • added regression tests
  • added compatibility tests
  • modified existing tests

How I validated my change

change me!

…iants

Problem: The build workflow was building operator images separately for
RHACS_BRANDING and STACKROX_BRANDING (4 builds total: 2 brandings × 2
architectures), even though the Docker layers are identical. The only
difference between builds was the target registry
(quay.io/rhacs-eng vs quay.io/stackrox-io).

Investigation showed:
- operator/prebuilt.Dockerfile contains no ROX_PRODUCT_BRANDING
- Operator Go code has no branding references
- Binary builds are identical regardless of branding
- Only the registry tag differs between variants

Solution: Build once per architecture, tag and push to both registries.

Changes:
- Matrix definition: removed branding dimension from build_and_push_operator,
  added registry dimension to push_operator_multiarch_manifests
- build-and-push-operator job: build with IMAGE_REPO=stackrox to create
  local tag, then push to both quay.io/rhacs-eng and quay.io/stackrox-io
- Added push_operator_image_to_registry() function that accepts registry
  parameter instead of deriving it from branding
- Added push_operator_image_manifest_lists() function for registry-based
  manifest push (follows scanner-build.yaml pattern)

Benefits:
- Reduces operator builds from 4 to 2 (50% reduction)
- Saves ~5-8 minutes per workflow run
- Images remain available at same registry locations (no breaking changes)

Follows existing pattern from scanner-build.yaml which already uses
registry-based matrix instead of branding matrix.

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Both push_operator_image_to_registry and push_operator_image_manifest_lists re-implement tag/major-minor logic that already exists in other helpers (e.g., the older operator/scanner push functions); consider extracting a common helper to avoid duplication and keep the tagging behavior consistent across images.
  • The operator jobs now hardcode ROX_PRODUCT_BRANDING=RHACS_BRANDING; if any future operator build behavior diverges by branding, this may be a surprising coupling—consider adding a short comment in the workflow or wiring branding in a way that makes the assumption explicit or easier to change.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Both `push_operator_image_to_registry` and `push_operator_image_manifest_lists` re-implement tag/major-minor logic that already exists in other helpers (e.g., the older operator/scanner push functions); consider extracting a common helper to avoid duplication and keep the tagging behavior consistent across images.
- The operator jobs now hardcode `ROX_PRODUCT_BRANDING=RHACS_BRANDING`; if any future operator build behavior diverges by branding, this may be a surprising coupling—consider adding a short comment in the workflow or wiring branding in a way that makes the assumption explicit or easier to change.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 49.60%. Comparing base (118ca3c) to head (fbaa585).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #19820   +/-   ##
=======================================
  Coverage   49.60%   49.60%           
=======================================
  Files        2763     2763           
  Lines      208271   208271           
=======================================
+ Hits       103309   103312    +3     
+ Misses      97294    97292    -2     
+ Partials     7668     7667    -1     
Flag Coverage Δ
go-unit-tests 49.60% <ø> (+<0.01%) ⬆️

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:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • Chores
    • Refactored operator image build and deployment workflow to support publishing to multiple registry destinations.
    • Enhanced CI infrastructure with new helper functions for operator image publishing and manifest list management.

Walkthrough

The build workflow transitions from branding-based operator image pushing to registry-based pushing. Operator images are now built once with IMAGE_REPO=stackrox, then pushed to multiple registries (quay.io/rhacs-eng, quay.io/stackrox-io) using new helper functions that handle per-registry image pushing and manifest list generation.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
.github/workflows/build.yaml
Removed build_and_push_operator branding matrix dimension and added registry dimension to push_operator_multiarch_manifests job with two Quay targets. Updated build-and-push-operator job to build a single stackrox/stackrox-operator image without branding matrix variables. Refactored image push control flow to iterate over registries and call new push_operator_image_to_registry() function per registry. Updated manifest push job to use new push_operator_image_manifest_lists() function with registry parameter instead of branding-based logic.
CI Helper Functions
scripts/ci/lib.sh
Added push_operator_image_to_registry() function to handle operator image tagging, registry login, image retag, and multi-tag push (arch tags, conditional latest-<arch> and <major_minor>-<arch> for merge-to-master). Added push_operator_image_manifest_lists() function to handle registry login and manifest list publishing with conditional tags (latest, <major_minor>) for semver-like tags.

Sequence Diagram(s)

sequenceDiagram
    participant WF as GitHub Workflow
    participant Build as Build System
    participant Reg1 as quay.io/rhacs-eng
    participant Reg2 as quay.io/stackrox-io
    participant Manifest as Manifest Service

    WF->>Build: build_and_push_operator (IMAGE_REPO=stackrox)
    Build->>Build: Create stackrox/stackrox-operator:tag
    
    WF->>Reg1: push_operator_image_to_registry(registry=rhacs-eng, arch=amd64)
    Reg1->>Reg1: Login & retag to registry
    Reg1->>Reg1: Push with arch tag
    Reg1->>Reg1: Conditional: Push latest-amd64
    
    WF->>Reg2: push_operator_image_to_registry(registry=stackrox-io, arch=amd64)
    Reg2->>Reg2: Login & retag to registry
    Reg2->>Reg2: Push with arch tag
    Reg2->>Reg2: Conditional: Push latest-amd64
    
    WF->>Manifest: push_operator_image_manifest_lists(registry=rhacs-eng)
    Manifest->>Reg1: Generate & publish manifest list
    Manifest->>Reg1: Conditional: Publish latest, major.minor variants
    
    WF->>Manifest: push_operator_image_manifest_lists(registry=stackrox-io)
    Manifest->>Reg2: Generate & publish manifest list
    Manifest->>Reg2: Conditional: Publish latest, major.minor variants
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR provides a detailed explanation of the problem, investigation findings, solution, and benefits, but the template sections below remain unfilled with placeholder 'change me!' text. Complete the template sections: clarify testing approach (especially why tests may not be needed for CI workflow changes), confirm documentation and quality checkboxes, and remove placeholder text.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately describes the main change: consolidating operator image builds by eliminating redundant branding-based builds.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ROX-30858/unify-branding-builds

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/build.yaml (1)

75-76: ⚠️ Potential issue | 🔴 Critical

Remove the empty name axis from the operator matrices.

build_and_push_operator and push_operator_multiarch_manifests have name: []. In GitHub Actions, an empty array in strategy.matrix causes a validation error and prevents the job from expanding at all—operator images and manifests will not be built or published. Remove the unused name key.

Fix
-            "build_and_push_operator": { "name":[], "arch":[] },
-            "push_operator_multiarch_manifests": { "name":[] },
+            "build_and_push_operator": { "arch":[] },
+            "push_operator_multiarch_manifests": { "registry":[], "archs":[] },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/build.yaml around lines 75 - 76, The operator job matrices
include an empty name axis which breaks matrix expansion; remove the unused
name: [] entries under the "build_and_push_operator" and
"push_operator_multiarch_manifests" matrix definitions in
.github/workflows/build.yaml so the matrix no longer contains an empty array for
the name key (leave other axes like arch intact for build_and_push_operator);
ensure the YAML remains valid after deleting the name keys.
🧹 Nitpick comments (1)
scripts/ci/lib.sh (1)

371-431: Extract the shared operator tag-publish policy.

push_operator_image_to_registry and push_operator_image_manifest_lists now duplicate the same latest / major.minor publication rules already implemented by push_operator_image and push_operator_manifest_lists. Keeping four copies makes the next tagging-policy change easy to miss; please move that branching into a private helper and keep the public entrypoints thin.

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/ci/lib.sh` around lines 371 - 431, Both
push_operator_image_to_registry and push_operator_image_manifest_lists duplicate
the same "publish latest / major.minor" logic already used by
push_operator_image and push_operator_manifest_lists; extract that branching
into a single private helper (e.g., publish_operator_tag_policy or
_publish_operator_tags) that takes the push_context, registry, tag and a push
action (or parameters like arch/architectures) and performs the conditional
tagging/pushing for "merge-to-master" (latest) and semver major.minor; then
update push_operator_image_to_registry and push_operator_image_manifest_lists to
call this helper after logging and registry_rw_login, removing the duplicated if
[[ "$push_context" == "merge-to-master" ]] and semver-if blocks so the public
entrypoints remain thin and reuse the central policy used by push_operator_image
and push_operator_manifest_lists.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/build.yaml:
- Around line 75-76: The operator job matrices include an empty name axis which
breaks matrix expansion; remove the unused name: [] entries under the
"build_and_push_operator" and "push_operator_multiarch_manifests" matrix
definitions in .github/workflows/build.yaml so the matrix no longer contains an
empty array for the name key (leave other axes like arch intact for
build_and_push_operator); ensure the YAML remains valid after deleting the name
keys.

---

Nitpick comments:
In `@scripts/ci/lib.sh`:
- Around line 371-431: Both push_operator_image_to_registry and
push_operator_image_manifest_lists duplicate the same "publish latest /
major.minor" logic already used by push_operator_image and
push_operator_manifest_lists; extract that branching into a single private
helper (e.g., publish_operator_tag_policy or _publish_operator_tags) that takes
the push_context, registry, tag and a push action (or parameters like
arch/architectures) and performs the conditional tagging/pushing for
"merge-to-master" (latest) and semver major.minor; then update
push_operator_image_to_registry and push_operator_image_manifest_lists to call
this helper after logging and registry_rw_login, removing the duplicated if [[
"$push_context" == "merge-to-master" ]] and semver-if blocks so the public
entrypoints remain thin and reuse the central policy used by push_operator_image
and push_operator_manifest_lists.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 9463935b-785f-4628-b1d7-23096d045cd0

📥 Commits

Reviewing files that changed from the base of the PR and between b61d01e and fbaa585.

📒 Files selected for processing (2)
  • .github/workflows/build.yaml
  • scripts/ci/lib.sh

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

🚀 Build Images Ready

Images are ready for commit fbaa585. To use with deploy scripts:

export MAIN_IMAGE_TAG=4.11.x-557-gfbaa5858ff

@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Apr 3, 2026

@janisz: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/gke-operator-e2e-tests fbaa585 link false /test gke-operator-e2e-tests
ci/prow/gke-scanner-v4-install-tests fbaa585 link false /test gke-scanner-v4-install-tests
ci/prow/ocp-4-21-operator-e2e-tests fbaa585 link false /test ocp-4-21-operator-e2e-tests
ci/prow/ocp-4-12-scanner-v4-install-tests fbaa585 link false /test ocp-4-12-scanner-v4-install-tests
ci/prow/ocp-4-12-qa-e2e-tests fbaa585 link false /test ocp-4-12-qa-e2e-tests
ci/prow/ocp-4-12-nongroovy-e2e-tests fbaa585 link false /test ocp-4-12-nongroovy-e2e-tests
ci/prow/ocp-4-21-scanner-v4-install-tests fbaa585 link false /test ocp-4-21-scanner-v4-install-tests
ci/prow/ocp-4-21-qa-e2e-tests fbaa585 link false /test ocp-4-21-qa-e2e-tests
ci/prow/ocp-4-21-nongroovy-e2e-tests fbaa585 link false /test ocp-4-21-nongroovy-e2e-tests
ci/prow/ocp-4-12-operator-e2e-tests fbaa585 link false /test ocp-4-12-operator-e2e-tests

Full PR test history. Your PR dashboard.

Details

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. I understand the commands that are listed here.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant