Skip to content

fix(ci): align hermetic build with must-gather improvements - #3668

Merged
openshift-merge-bot[bot] merged 5 commits into
redhat-developer:mainfrom
Fortune-Ndlovu:improve-hermetic-build-cache-and-non-root
Oct 2, 2026
Merged

openshift-merge-bot[bot] merged 5 commits into
redhat-developer:mainfrom
Fortune-Ndlovu:improve-hermetic-build-cache-and-non-root

Conversation

@Fortune-Ndlovu

@Fortune-Ndlovu Fortune-Ndlovu commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Summary

Follow-up to rhdh-must-gather#218: apply the same hermetic CI hygiene to the operator.

  • Single Hermeto pin in the Makefile (Renovate + shared by CI and make hermetic-build)
  • Cache key includes the Hermeto image tag
  • chmod on the prefetched cache after inject (local script + CI) so the go-builder can stay non-root
  • Remove USER 0 from the builder stage; set GOCACHE=/tmp/go-build-cache

Test plan

  • make hermetic-build IMG=localhost/rhdh-operator:hermetic-test
  • podman run --rm localhost/rhdh-operator:hermetic-test --help
  • PR Build (hermetic) green on GitHub Actions

@Fortune-Ndlovu
Fortune-Ndlovu requested a review from a team as a code owner September 30, 2026 14:09
@openshift-ci
openshift-ci Bot requested review from gazarenkov and rm3l September 30, 2026 14:09
@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

Align hermetic CI and local builds around a shared Hermeto pin

🐞 Bug fix ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Share one Renovate-managed Hermeto image pin across CI and local builds.
• Invalidate CI dependency caches when the Hermeto tag changes.
• Make prefetched caches writable so the Go builder can run as non-root.
Diagram

graph TD
  R["Renovate"] --> M["Makefile pin"] --> C["CI build action"] --> H[("Hermeto cache")] --> B["Non-root builder"] --> I["Operator image"]
  M --> L["Local build script"] --> H
Loading
High-Level Assessment

Keep the shared Makefile pin: it avoids separate CI and script versions while remaining Renovate-managed. Duplicating pins would reintroduce drift, and a separate configuration file would add another layer for a single value.

Files changed (6) +50 / -9

Bug fix (3) +33 / -7
action.yamlUse the shared pin and prepare a writable CI cache +14/-4

Use the shared pin and prepare a writable CI cache

• Reads the Hermeto image from the Makefile and includes its tag in the dependency-cache key. Makes the cache writable after injection so the non-root builder can use it.

.github/actions/docker-build/action.yaml

DockerfileRun the Go builder as the default non-root user +3/-2

Run the Go builder as the default non-root user

• Removes the builder's root-user override and places the Go build cache under /tmp.

Dockerfile

local-hermeto-build.shRead the shared pin and open cache permissions locally +16/-1

Read the shared pin and open cache permissions locally

• Accepts an image override or reads the component Makefile, failing if neither supplies a value. Makes the prefetched cache writable after injection for non-root image builds.

scripts/local-hermeto-build.sh

Documentation (1) +2 / -0
developer.mdDocument the shared Hermeto image pin +2/-0

Document the shared Hermeto image pin

• Explains that CI and local hermetic builds use the image value defined in the Makefile.

docs/developer.md

Other (2) +15 / -2
renovate.jsonTrack the Makefile Hermeto pin with Renovate +12/-1

Track the Makefile Hermeto pin with Renovate

• Adds a regex manager that discovers the Hermeto Docker image version in the Makefile.

.github/renovate.json

MakefileDefine and pass the shared Hermeto image pin +3/-1

Define and pass the shared Hermeto image pin

• Defines the Renovate-managed image value and passes it to the local hermetic-build script.

Makefile

@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Some local cache builds stop at chmod ✓ Resolved
Description
build_cache runs an unguarded host-side chmod -R on files populated by Podman containers,
without first ensuring the invoking user owns them. If those files are owned by another host UID,
chmod fails under set -e and the image build never starts; the CI path explicitly repairs
ownership before its equivalent chmod.
Code

scripts/local-hermeto-build.sh[174]

+  chmod -R a+rwX "${local_cache_dir}"
Relevance

●●● Strong

Prior reviewers accepted deterministic local-script reliability fixes; missing ownership repair can
terminate builds under set -e.

PR-#3359

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Podman commands populate the mounted cache before the new host-side chmod, and set -e makes a
permission failure fatal. Unlike the local script, CI performs a privileged recursive chown before
chmod.

scripts/local-hermeto-build.sh[16-16]
scripts/local-hermeto-build.sh[136-175]
scripts/local-hermeto-build.sh[301-310]
.github/actions/docker-build/action.yaml[139-145]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A host-side chmod terminates local builds when Podman-created cache files belong to a different host UID.
## Fix Focus Areas
- scripts/local-hermeto-build.sh[136-175]
- .github/actions/docker-build/action.yaml[139-145]
## Recommended Fix
Normalize cache ownership using an appropriate Podman user-namespace operation before changing permissions, or perform the permission change as a user that owns the files. Verify the script works with rootless Podman cache files owned by subordinate UIDs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Local users can poison build dependencies ✓ Resolved
Description
build_cache applies chmod -R a+rwX to the entire prefetched cache, allowing other local users to
alter its contents. When the cache path is accessible to another user, their changes to the
generated environment file or cached dependencies are consumed by the subsequent offline image
build.
Code

scripts/local-hermeto-build.sh[174]

+  chmod -R a+rwX "${local_cache_dir}"
Relevance

●● Moderate

Intent explicitly matches CI hygiene, but broad writable permissions create a credible local
cache-integrity risk.

PR-#3359

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new chmod grants write access to all users; the script then mounts that same directory at
/cachi2, and its Dockerfile transformation sources the environment file from that mount during
build commands.

scripts/local-hermeto-build.sh[169-174]
scripts/local-hermeto-build.sh[118-124]
scripts/local-hermeto-build.sh[198-214]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Recursive all-user write permission lets other local users alter dependencies used by the offline image build.
## Fix Focus Areas
- scripts/local-hermeto-build.sh[169-175]
- scripts/local-hermeto-build.sh[198-214]
## Recommended Fix
Give the build container access through a restricted group or an appropriate user-namespace ownership mapping instead of making the entire cache writable by everyone.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 18 rules
✅ Cross-repo context — repo relationships
  Explored: repo: redhat-developer/rhdh-must-gather (sha: ad4beb40) — View relationship
Review mode: ⚖️ Balanced: This changes hermetic CI/build behavior across Makefile, shell, Dockerfile, caching, permissions, and Renovate configuration, creating meaningful cross-path correctness and security implications without being dense enough to require extended review.

Grey Divider

Tip of the day
💡 Did you know, you can show, collapse, or hide each part of a finding: code, evidence, and all

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Pin Hermeto once in the Makefile for CI and local builds, include the
Hermeto tag in the deps cache key, chmod the prefetch cache for non-root
go-builder, and drop USER 0 from the builder stage.

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@rhdh-qodo-merge rhdh-qodo-merge Bot added documentation Improvements or additions to documentation enhancement New feature or request Bug fix labels Sep 30, 2026
@rhdh-qodo-merge

Copy link
Copy Markdown

Important

The /generate_labels command by Qodo is sunsetting on the 1st of October 2026 and will no longer be available. We recommend switching to the latest Qodo review capabilities. Learn more

@Fortune-Ndlovu
Fortune-Ndlovu force-pushed the improve-hermetic-build-cache-and-non-root branch from 3a8a3ae to c83d33b Compare September 30, 2026 14:12
Chown the Podman-populated cache before chmod (podman unshare, like CI),
use /tmp/hermeto-cache/operator for local builds, and restrict the cache
parent directory to the invoking user.

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ PR images built and pushed successfully!

Images are available for testing (expires in 7 days):

Image Full tag PR tag
Operator quay.io/rhdh-community/operator:2.1.0-pr-3668-c83d33b quay.io/rhdh-community/operator:2.1.0-pr-3668
Bundle quay.io/rhdh-community/operator-bundle:2.1.0-pr-3668-c83d33b quay.io/rhdh-community/operator-bundle:2.1.0-pr-3668
Catalog quay.io/rhdh-community/operator-catalog:2.1.0-pr-3668-c83d33b quay.io/rhdh-community/operator-catalog:2.1.0-pr-3668

@github-actions

Copy link
Copy Markdown
Contributor

✅ PR images built and pushed successfully!

Images are available for testing (expires in 7 days):

Image Full tag PR tag
Operator quay.io/rhdh-community/operator:2.1.0-pr-3668-fe4df57 quay.io/rhdh-community/operator:2.1.0-pr-3668
Bundle quay.io/rhdh-community/operator-bundle:2.1.0-pr-3668-fe4df57 quay.io/rhdh-community/operator-bundle:2.1.0-pr-3668
Catalog quay.io/rhdh-community/operator-catalog:2.1.0-pr-3668-fe4df57 quay.io/rhdh-community/operator-catalog:2.1.0-pr-3668

Map go-builder and rpm-builder Podman UIDs with setfacl (subuid math plus
a root probe) so local offline builds work without world-writable cache files.

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ PR images built and pushed successfully!

Images are available for testing (expires in 7 days):

Image Full tag PR tag
Operator quay.io/rhdh-community/operator:2.1.0-pr-3668-f441c05 quay.io/rhdh-community/operator:2.1.0-pr-3668
Bundle quay.io/rhdh-community/operator-bundle:2.1.0-pr-3668-f441c05 quay.io/rhdh-community/operator-bundle:2.1.0-pr-3668
Catalog quay.io/rhdh-community/operator-catalog:2.1.0-pr-3668-f441c05 quay.io/rhdh-community/operator-catalog:2.1.0-pr-3668

Relocate local Hermeto helper to hack/local-hermeto-build.sh, add
CONTAINERFILE and per-image cache dirs under /tmp/hermeto-cache/, and
parse multi-stage Dockerfiles for ACL UID mapping. Add
dp-installer-hermetic-build for plugin-installer.

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

✅ PR images built and pushed successfully!

Images are available for testing (expires in 7 days):

Image Full tag PR tag
Operator quay.io/rhdh-community/operator:2.2.0-pr-3668-f235d26 quay.io/rhdh-community/operator:2.2.0-pr-3668
Bundle quay.io/rhdh-community/operator-bundle:2.2.0-pr-3668-f235d26 quay.io/rhdh-community/operator-bundle:2.2.0-pr-3668
Catalog quay.io/rhdh-community/operator-catalog:2.2.0-pr-3668-f235d26 quay.io/rhdh-community/operator-catalog:2.2.0-pr-3668

Comment thread hack/local-hermeto-build.sh Outdated
Use podman unshare chown plus chmod -R a+rwX on the local Hermeto cache,
same as rhdh-must-gather redhat-developer#218 and CI. Removes the acl package requirement.

Signed-off-by: Fortune-Ndlovu <fndlovu@redhat.com>
@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

✅ PR images built and pushed successfully!

Images are available for testing (expires in 7 days):

Image Full tag PR tag
Operator quay.io/rhdh-community/operator:2.2.0-pr-3668-3a91f09 quay.io/rhdh-community/operator:2.2.0-pr-3668
Bundle quay.io/rhdh-community/operator-bundle:2.2.0-pr-3668-3a91f09 quay.io/rhdh-community/operator-bundle:2.2.0-pr-3668
Catalog quay.io/rhdh-community/operator-catalog:2.2.0-pr-3668-3a91f09 quay.io/rhdh-community/operator-catalog:2.2.0-pr-3668

@codecov

codecov Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.43%. Comparing base (0379ecd) to head (3a91f09).
⚠️ Report is 12 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3668      +/-   ##
==========================================
+ Coverage   60.09%   60.43%   +0.33%     
==========================================
  Files          51       52       +1     
  Lines        3614     3672      +58     
==========================================
+ Hits         2172     2219      +47     
- Misses       1247     1257      +10     
- Partials      195      196       +1     
Flag Coverage Δ
nightly ?
unittests 60.43% <ø> (+0.33%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 7 files with indirect coverage changes

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

@openshift-ci openshift-ci Bot added the lgtm label Oct 2, 2026
@openshift-merge-bot
openshift-merge-bot Bot merged commit 088febb into redhat-developer:main Oct 2, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug fix documentation Improvements or additions to documentation enhancement New feature or request lgtm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants