Skip to content

feat: add OCIVolumes feature gate with ORAS OCI volume support - #342

Merged
bennyz merged 1 commit into
centos-automotive-suite:mainfrom
bennyz:worktree-oci-volumes-clean
Jul 9, 2026
Merged

feat: add OCIVolumes feature gate with ORAS OCI volume support#342
bennyz merged 1 commit into
centos-automotive-suite:mainfrom
bennyz:worktree-oci-volumes-clean

Conversation

@bennyz

@bennyz bennyz commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Gate OCI image volumes behind a new Alpha feature gate (OCIVolumes). When enabled, mount the ORAS CLI container image as a read-only volume in build pods, eliminating the runtime download+verify of the ORAS binary.

Enable via OperatorConfig:
spec.featureGates.OCIVolumes: true

Summary

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • CI/CD improvement
  • Refactoring

Testing

  • Unit tests pass (make test)
  • Linter passes (make lint)
  • Manifests are up to date (make manifests generate)
  • Tested on OpenShift cluster (if applicable)

Summary by CodeRabbit

  • New Features
    • Added optional OCI volume support for build and push workflows behind the OCIVolumes feature gate.
    • Added configurable ORAS CLI image selection with a default fallback.
  • Bug Fixes
    • Improved ORAS CLI installation flow by sharing the install logic and using the resolved ORAS executable consistently.
    • When enabled, OCI volume mounts are applied to generated pod templates; added a Secure Build drift warning noting bundle task behavior.
  • Tests
    • Expanded coverage for OCI volume creation, mount behavior (read-only, pull policy), and feature-gate/config handling.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@bennyz, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 144d40cb-977a-44b9-b08c-606298e48599

📥 Commits

Reviewing files that changed from the base of the PR and between a3ed10a and 15aa241.

⛔ Files ignored due to path filters (1)
  • config/crd/bases/automotive.sdv.cloud.redhat.com_operatorconfigs.yaml is excluded by !config/crd/bases/**
📒 Files selected for processing (13)
  • api/v1alpha1/operatorconfig_types.go
  • internal/common/tasks/oci_volumes_test.go
  • internal/common/tasks/scripts/build_image.sh
  • internal/common/tasks/scripts/common.sh
  • internal/common/tasks/scripts/push_artifact.sh
  • internal/common/tasks/scripts/sealed_operation.sh
  • internal/common/tasks/tasks.go
  • internal/controller/controllerutils/oci_volumes.go
  • internal/controller/controllerutils/oci_volumes_test.go
  • internal/controller/imagebuild/controller.go
  • internal/controller/operatorconfig/controller.go
  • internal/featuregates/features.go
  • internal/featuregates/gates_test.go
📝 Walkthrough

Walkthrough

This PR adds ORAS OCI volume support: a new Oras image config field with getter, an OCIVolumes feature gate, Tekton task volume/mount injection helpers, controller wiring to enable and configure OCI volumes in build/push pod templates, and shell script updates to resolve or download oras conditionally.

Changes

ORAS OCI Volumes Support

Layer / File(s) Summary
ORAS image config
api/v1alpha1/operatorconfig_types.go
Adds DefaultOrasImage, ImagesConfig.Oras, and GetOrasImage() with fallback behavior.
Feature gate registration
internal/featuregates/features.go, internal/featuregates/gates_test.go
Registers OCIVolumes at Alpha stage and adds tests for registration and override behavior.
Task volume/mount generation
internal/common/tasks/tasks.go, internal/common/tasks/oci_volumes_test.go
Adds UseOCIVolumes/OrasImage to BuildConfig, introduces OCI tooling volume helpers, wires mounts into task generation, and validates the generated mounts and volumes.
Controller feature-gate wiring
internal/controller/controllerutils/oci_volumes.go, internal/controller/controllerutils/oci_volumes_test.go, internal/controller/imagebuild/controller.go, internal/controller/operatorconfig/controller.go
Applies OCI-volume config from OperatorConfig, propagates it into build config and pod templates, and covers enabled/disabled gate cases with tests.
Shell script oras resolution
internal/common/tasks/scripts/build_image.sh, internal/common/tasks/scripts/common.sh, internal/common/tasks/scripts/push_artifact.sh, internal/common/tasks/scripts/sealed_operation.sh
Moves ORAS installation into a shared helper, updates PATH handling, switches push/attach calls to ORAS_BIN, and removes the in-file install_oras definition from sealed operations.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: bkhizgiy

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding the OCIVolumes feature gate and ORAS OCI volume support.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@bennyz
bennyz force-pushed the worktree-oci-volumes-clean branch from 6a426f0 to 188f07f Compare July 6, 2026 06:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
internal/common/tasks/tasks.go (2)

906-946: 🧹 Nitpick | 🔵 Trivial

Cluster prerequisite: ImageVolume feature gate must be enabled.

OCIVolumes() relies on corev1.ImageVolumeSource, which is gated by Kubernetes' own ImageVolume feature (alpha in 1.31, beta since 1.33) and is still disabled by default, because not all container runtimes have full support for it. It also requires a compatible container runtime version (CRI-O ≥1.31, or containerd ≥2.1.0 for alpha support). If the target OpenShift cluster's ImageVolume gate isn't enabled, pods requesting this volume type will fail to schedule/validate even though OCIVolumes is Alpha-gated at the operator level.

Since the PR objectives mention OpenShift cluster testing, worth confirming this cluster-side prerequisite is documented (e.g., install docs/README) so operators enabling OCIVolumes: true know the underlying k8s feature gate dependency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/common/tasks/tasks.go` around lines 906 - 946, Document the
cluster-side prerequisite for the ImageVolume dependency used by OCIVolumes(),
since applyOCIVolumeMounts() and OCIVolumes() rely on corev1.ImageVolumeSource.
Add a note in the install/docs/README explaining that enabling
BuildConfig.UseOCIVolumes requires the Kubernetes ImageVolume feature gate and a
compatible runtime, so operators know not to turn on the feature unless the
OpenShift cluster supports it.

911-924: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Mount applied to all steps regardless of need.

applyOCIVolumeMounts unconditionally appends the oras-tools mount to every step of every task it's applied to (e.g. find-manifest-file/build-image steps in GenerateBuildAutomotiveImageTask never invoke oras). Restricting the mount to steps that actually need it would reduce unnecessary volume exposure across containers (least privilege), though the risk is low since the mount is read-only.

♻️ Example: scope mounts to specific step names
-func applyOCIVolumeMounts(task *tektonv1.Task, buildConfig *BuildConfig) {
+func applyOCIVolumeMounts(task *tektonv1.Task, buildConfig *BuildConfig, stepNames ...string) {
 	if buildConfig == nil || !buildConfig.UseOCIVolumes || buildConfig.OrasImage == "" {
 		return
 	}
 
+	allowed := map[string]bool{}
+	for _, n := range stepNames {
+		allowed[n] = true
+	}
+
 	for i := range task.Spec.Steps {
 		step := &task.Spec.Steps[i]
+		if len(allowed) > 0 && !allowed[step.Name] {
+			continue
+		}
 		step.VolumeMounts = append(step.VolumeMounts, corev1.VolumeMount{
 			Name:      ociVolumeNameOras,
 			MountPath: ociMountPathOras,
 			ReadOnly:  true,
 		})
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/common/tasks/tasks.go` around lines 911 - 924,
`applyOCIVolumeMounts` currently adds the `ociVolumeNameOras` mount to every
step in a task, even for steps like `find-manifest-file` and `build-image` that
do not use `oras`. Update the logic in `applyOCIVolumeMounts` to scope the mount
only to the specific step names that actually need it, using `task.Spec.Steps`
and the step `Name` field to identify them, so the mount is not appended to
unrelated steps.
internal/controller/imagebuild/controller.go (1)

905-911: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate OCI-volumes feature-gate wiring (3 sites).

This exact block — construct featuregates.NewFromConfig(&spec), check OCIVolumes, set UseOCIVolumes/OrasImage — is repeated verbatim here, again at Line 2598-2604 in this file, and a third time in internal/controller/operatorconfig/controller.go (Lines 709-713). The codebase already has a precedent for factoring this kind of shared BuildConfig population out (see controllerutils.ApplyTrustedCABundleFromOSBuilds). Consider a similar helper, e.g. controllerutils.ApplyOCIVolumesConfig(bc *tasks.BuildConfig, spec *automotivev1alpha1.OperatorConfigSpec), to avoid the three copies drifting.

♻️ Proposed helper
func ApplyOCIVolumesConfig(bc *tasks.BuildConfig, spec *automotivev1alpha1.OperatorConfigSpec) {
	gates := featuregates.NewFromConfig(spec)
	if gates.Enabled(featuregates.OCIVolumes) {
		bc.UseOCIVolumes = true
		bc.OrasImage = spec.GetImages().GetOrasImage()
	}
}

Also applies to: 2598-2604

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/controller/imagebuild/controller.go` around lines 905 - 911, The
OCI-volumes feature-gate wiring is duplicated in multiple places, so factor the
repeated feature-gate check and BuildConfig mutation out of the image build
controller into a shared helper. Add a helper such as
controllerutils.ApplyOCIVolumesConfig that takes the BuildConfig and
OperatorConfigSpec, performs the featuregates.NewFromConfig check for
featuregates.OCIVolumes, and sets UseOCIVolumes and OrasImage; then replace the
repeated inline blocks in imagebuild controller code and the operatorconfig
controller with calls to that helper.
internal/common/tasks/scripts/build_image.sh (1)

95-121: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

ORAS fallback-download logic has diverged in robustness from push_artifact.sh.

Both scripts implement essentially the same "download + verify checksum + install oras" logic, but push_artifact.sh was hardened in this PR (curl failure checks, missing-checksum check, extraction failure check, $HOME edge-case guard for //bin//bin, cleanup trap) while this block keeps the older, unchecked version: curl -sLO failures are silent, tar -zxf isn't checked, and mkdir -p "$HOME/bin" has no guard against $HOME being unset/root. Since this logic is now duplicated in two places, further changes to one (as already happened here) risk leaving the other behind. Consider extracting a single install_oras() function into common.sh that both scripts call.

♻️ Sketch of a shared helper in common.sh
+install_oras() {
+  ORAS_VERSION="1.2.0"
+  case "$(uname -m)" in
+    x86_64) ORAS_ARCH="amd64" ;;
+    aarch64|arm64) ORAS_ARCH="arm64" ;;
+    *) echo "ERROR: Unsupported architecture: $(uname -m)" >&2; return 1 ;;
+  esac
+  # ... same hardened download/verify/install logic currently in push_artifact.sh ...
+}

Then both build_image.sh and push_artifact.sh call install_oras when oras isn't already resolvable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/common/tasks/scripts/build_image.sh` around lines 95 - 121, The ORAS
download/install fallback in build_image.sh is still using the older, less safe
flow compared with push_artifact.sh. Refactor the duplicated inline block into a
shared install_oras helper in common.sh and have both scripts call it when
command -v oras fails. Make sure the shared helper includes the same hardened
checks as push_artifact.sh: fail on curl/download errors, verify the checksum
file and tar extraction, and guard the $HOME/bin install path edge case.
internal/common/tasks/scripts/push_artifact.sh (1)

4-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded mount path duplicates the Go-side constant.

/oci-tools/oras/bin/oras is hardcoded here, mirroring OCIToolsMountBase + "/oras" (/oci-tools/oras) from internal/common/tasks/tasks.go, plus an assumed /bin/oras layout inside the ORAS image. If that Go constant ever changes, this script silently falls through to command -v oras / the download fallback instead of failing loudly — a correctness regression that would go unnoticed until someone inspects logs. A brief comment noting this must stay in sync with ociMountPathOras in tasks.go would help.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/common/tasks/scripts/push_artifact.sh` around lines 4 - 11, The ORAS
mount path check in push_artifact.sh hardcodes the OCI volume location and can
drift from the Go-side constant used by tasks.go. Update the logic around
ORAS_BIN to keep it explicitly in sync with ociMountPathOras/OCIToolsMountBase,
and add a brief comment near the /oci-tools/oras/bin/oras check documenting that
this path must match the Go constant. Make the mismatch obvious so changes to
the mount path do not silently fall back to command -v oras or the download
path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/controller/imagebuild/controller.go`:
- Line 1466: The OCI volume and task mount sources are being read from different
config snapshots, which can let `taskRef`/`pipelineRef` and
`podTemplate.Volumes` drift apart. Update the ImageBuild reconciliation flow
around `podTemplate.Volumes = append(... tasks.OCIVolumes(buildConfig)...)` and
the `taskRef`/`pipelineRef` selection so both come from the same reconciled
`OperatorConfig` snapshot, or defer creating the `PipelineRun` until the
regenerated Task/Pipeline has been applied.

---

Nitpick comments:
In `@internal/common/tasks/scripts/build_image.sh`:
- Around line 95-121: The ORAS download/install fallback in build_image.sh is
still using the older, less safe flow compared with push_artifact.sh. Refactor
the duplicated inline block into a shared install_oras helper in common.sh and
have both scripts call it when command -v oras fails. Make sure the shared
helper includes the same hardened checks as push_artifact.sh: fail on
curl/download errors, verify the checksum file and tar extraction, and guard the
$HOME/bin install path edge case.

In `@internal/common/tasks/scripts/push_artifact.sh`:
- Around line 4-11: The ORAS mount path check in push_artifact.sh hardcodes the
OCI volume location and can drift from the Go-side constant used by tasks.go.
Update the logic around ORAS_BIN to keep it explicitly in sync with
ociMountPathOras/OCIToolsMountBase, and add a brief comment near the
/oci-tools/oras/bin/oras check documenting that this path must match the Go
constant. Make the mismatch obvious so changes to the mount path do not silently
fall back to command -v oras or the download path.

In `@internal/common/tasks/tasks.go`:
- Around line 906-946: Document the cluster-side prerequisite for the
ImageVolume dependency used by OCIVolumes(), since applyOCIVolumeMounts() and
OCIVolumes() rely on corev1.ImageVolumeSource. Add a note in the
install/docs/README explaining that enabling BuildConfig.UseOCIVolumes requires
the Kubernetes ImageVolume feature gate and a compatible runtime, so operators
know not to turn on the feature unless the OpenShift cluster supports it.
- Around line 911-924: `applyOCIVolumeMounts` currently adds the
`ociVolumeNameOras` mount to every step in a task, even for steps like
`find-manifest-file` and `build-image` that do not use `oras`. Update the logic
in `applyOCIVolumeMounts` to scope the mount only to the specific step names
that actually need it, using `task.Spec.Steps` and the step `Name` field to
identify them, so the mount is not appended to unrelated steps.

In `@internal/controller/imagebuild/controller.go`:
- Around line 905-911: The OCI-volumes feature-gate wiring is duplicated in
multiple places, so factor the repeated feature-gate check and BuildConfig
mutation out of the image build controller into a shared helper. Add a helper
such as controllerutils.ApplyOCIVolumesConfig that takes the BuildConfig and
OperatorConfigSpec, performs the featuregates.NewFromConfig check for
featuregates.OCIVolumes, and sets UseOCIVolumes and OrasImage; then replace the
repeated inline blocks in imagebuild controller code and the operatorconfig
controller with calls to that helper.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d0561b2b-1adb-4377-b395-8645ba1b992d

📥 Commits

Reviewing files that changed from the base of the PR and between 395d9c7 and 6a426f0.

⛔ Files ignored due to path filters (1)
  • config/crd/bases/automotive.sdv.cloud.redhat.com_operatorconfigs.yaml is excluded by !config/crd/bases/**
📒 Files selected for processing (10)
  • api/v1alpha1/operatorconfig_types.go
  • internal/common/tasks/oci_volumes_test.go
  • internal/common/tasks/scripts/build_image.sh
  • internal/common/tasks/scripts/common.sh
  • internal/common/tasks/scripts/push_artifact.sh
  • internal/common/tasks/tasks.go
  • internal/controller/imagebuild/controller.go
  • internal/controller/operatorconfig/controller.go
  • internal/featuregates/features.go
  • internal/featuregates/gates_test.go

Comment thread internal/controller/imagebuild/controller.go
@bennyz
bennyz force-pushed the worktree-oci-volumes-clean branch from 188f07f to f8467e2 Compare July 6, 2026 08:26
@bennyz

bennyz commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@bennyz

bennyz commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@ambient-code please review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/common/tasks/scripts/push_artifact.sh (1)

10-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the ORAS download/verify/install logic into a shared helper.

This ~80-line download+checksum-verify+install flow appears to duplicate similar logic already present in build_image.sh per the PR summary. Centralizing it in common.sh (which already gains an "OCI tools path hook" in this PR) would avoid version-pin drift (ORAS_VERSION="1.2.0") between the two call sites and reduce maintenance surface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/common/tasks/scripts/push_artifact.sh` around lines 10 - 91, The
ORAS download, checksum verification, and install flow in push_artifact.sh is
duplicated and should be centralized. Extract the logic used in the ORAS_BIN
bootstrap block into a shared helper in common.sh, then have push_artifact.sh
call that helper instead of embedding the full flow. Keep the version-pinned
setup in one place so build_image.sh and the push_artifact.sh path both use the
same helper and cannot drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/common/tasks/scripts/push_artifact.sh`:
- Around line 10-91: The ORAS download, checksum verification, and install flow
in push_artifact.sh is duplicated and should be centralized. Extract the logic
used in the ORAS_BIN bootstrap block into a shared helper in common.sh, then
have push_artifact.sh call that helper instead of embedding the full flow. Keep
the version-pinned setup in one place so build_image.sh and the push_artifact.sh
path both use the same helper and cannot drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e22a4b68-402d-45f4-af02-c5ac06824bd5

📥 Commits

Reviewing files that changed from the base of the PR and between 6a426f0 and f8467e2.

⛔ Files ignored due to path filters (1)
  • config/crd/bases/automotive.sdv.cloud.redhat.com_operatorconfigs.yaml is excluded by !config/crd/bases/**
📒 Files selected for processing (12)
  • api/v1alpha1/operatorconfig_types.go
  • internal/common/tasks/oci_volumes_test.go
  • internal/common/tasks/scripts/build_image.sh
  • internal/common/tasks/scripts/common.sh
  • internal/common/tasks/scripts/push_artifact.sh
  • internal/common/tasks/tasks.go
  • internal/controller/controllerutils/oci_volumes.go
  • internal/controller/controllerutils/oci_volumes_test.go
  • internal/controller/imagebuild/controller.go
  • internal/controller/operatorconfig/controller.go
  • internal/featuregates/features.go
  • internal/featuregates/gates_test.go
✅ Files skipped from review due to trivial changes (1)
  • internal/common/tasks/scripts/common.sh
🚧 Files skipped from review as they are similar to previous changes (6)
  • internal/common/tasks/scripts/build_image.sh
  • internal/featuregates/gates_test.go
  • internal/featuregates/features.go
  • api/v1alpha1/operatorconfig_types.go
  • internal/common/tasks/oci_volumes_test.go
  • internal/common/tasks/tasks.go

@ambient-code ambient-code Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Overall this is a well-structured feature addition that follows the established patterns (feature gates, controllerutils helpers, BuildConfig extension). The approach of using image volumes via podTemplate to avoid Tekton's Task CRD pruning is sound. Good test coverage across the feature gate, volume mounting, and controller integration paths.

A few items worth considering below — nothing blocking, mostly around edge-case robustness.

Comment thread internal/controller/imagebuild/controller.go
Comment thread internal/common/tasks/scripts/common.sh
Comment thread internal/common/tasks/scripts/push_artifact.sh Outdated
Comment thread internal/featuregates/features.go
Comment thread internal/controller/controllerutils/oci_volumes.go
Comment thread internal/common/tasks/tasks.go
@bennyz
bennyz force-pushed the worktree-oci-volumes-clean branch from f8467e2 to 257485b Compare July 7, 2026 08:21
@bennyz

bennyz commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@ambient-code please review

@ambient-code ambient-code Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Re-review after force-push

Both items from the previous review have been addressed:

  1. pushPodTemplate guard — now correctly only creates the PodTemplate when OCI volumes are present, avoiding a behavioral change for non-OCIVolumes push TaskRuns.
  2. Feature registration patternOCIVolumes is registered directly in the defaultFeatures map literal, consistent with the intended pattern documented in the comment.

The overall implementation is clean and well-tested. The ORAS install consolidation into common.sh eliminates duplication between build_image.sh and push_artifact.sh, and the install_oras() function correctly short-circuits when oras is already on PATH (via OCI volume mount).

One minor observation (not blocking): the trap _cleanup_oras_files EXIT inside install_oras() replaces any existing EXIT trap. Currently this is fine since no other EXIT traps exist at that point, but it could be fragile if other cleanup traps are added in the future. A stacking approach (trap '...; _cleanup_oras_files' EXIT) or using a trap wrapper would be more robust — but that's a general shell scripting concern, not specific to this PR.

LGTM — good feature addition with solid test coverage.

@bennyz
bennyz requested review from bkhizgiy and maboras-rh July 7, 2026 09:03
Comment on lines +41 to +45
if command -v oras >/dev/null 2>&1; then
ORAS_BIN="$(command -v oras)"
echo "ORAS already available at $ORAS_BIN"
return 0
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If the oras binary location change, then command -v oras fails silently, install_oras falls back to downloading, and the feature appears to work but the OCI volume goes unused with no warning emitted.
I think adding a log line is much helpful when the PATH directory doesn't exist
echo "WARN: OCI volume mounted but ORAS binary not found at expected path, falling back to download" >&2

return 0
fi

ORAS_VERSION="1.2.0"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oras version is hardcoded in the fallback. If the operator configure spec.images.oras: ghcr.io/oras-project/oras:v1.3.0 then OCI volume has v1.3.0 but the fallback download still installs v1.2.0.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we can introduce a variable to the task, but the plan is that over time (not too long hopefully) only ImageVolume will be used and the fallback will be removed entirely

@bennyz
bennyz force-pushed the worktree-oci-volumes-clean branch from 257485b to a3ed10a Compare July 8, 2026 05:29
Gate OCI image volumes behind a new Alpha feature gate (OCIVolumes).
When enabled, mount the ORAS CLI container image as a read-only volume
in build pods, eliminating the runtime download+verify of the ORAS
binary.

Enable via OperatorConfig:
  spec.featureGates.OCIVolumes: true

Signed-off-by: Benny Zlotnik <bzlotnik@redhat.com>
Assisted-by: claude-opus-4.6
@bennyz
bennyz force-pushed the worktree-oci-volumes-clean branch from a3ed10a to 15aa241 Compare July 8, 2026 05:46
@bennyz
bennyz merged commit 37a08a0 into centos-automotive-suite:main Jul 9, 2026
4 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 21, 2026
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants