Skip to content

OCPBUGS-88461: fix(helm): tolerate v-prefix version mismatch in disk-to-mirror#1430

Merged
openshift-merge-bot[bot] merged 3 commits into
openshift:mainfrom
Sourav21jain:fix/helm-v-prefix-version-mismatch
Jun 16, 2026
Merged

OCPBUGS-88461: fix(helm): tolerate v-prefix version mismatch in disk-to-mirror#1430
openshift-merge-bot[bot] merged 3 commits into
openshift:mainfrom
Sourav21jain:fix/helm-v-prefix-version-mismatch

Conversation

@Sourav21jain

@Sourav21jain Sourav21jain commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Description

During the disk-to-mirror (d2m) phase, oc-mirror constructs chart tarball
paths as {name}-{version}.tgz. However, the Helm downloader saves files
using the URL basename from the repository's index.yaml, which may include
a v prefix (e.g. csi-driver-nfs-v4.9.0.tgz). This causes d2m to fail
with file not found even though mirror-to-disk succeeded.

Root cause

Phase Who decides filename
m2d / m2m (download) Helm library — filepath.Base(url) from index
d2m (lookup) oc-mirror — fmt.Sprintf("%s-%s.tgz", name, version)

When the index URL contained a v prefix but the config did not (or
vice-versa), the reconstructed path never matched the file on disk.

Github / Jira issue: https://redhat.atlassian.net/browse/RFE-8530

Type of change

  • Code Improvements (Refactoring, Performance, CI upgrades, etc)

How Has This Been Tested?

  • TestResolveChartPath — unit tests for the helper (exact match,
    config omits v / disk has v, config has v / disk has no v, both missing)
  • TestHelmImageCollectorVPrefixDiskToMirror — end-to-end d2m collector
    test exercising both mismatch directions with a real chart tarball
  • Verified with the oc-mirror binary using --dry-run with a
    pre-seeded working-dir containing podinfo-v5.0.0.tgz and config
    specifying version: "5.0.0"

Summary by CodeRabbit

  • Bug Fixes

    • Improved local Helm chart archive resolution to reliably find on-disk chart packages when version strings include or omit a leading "v". Added safer path validation to prevent path traversal, treats missing files as non-fatal, and ensures processing continues when a chart path lookup fails.
  • Tests

    • Added tests covering v-prefix/version variations and end-to-end disk-to-mirror collection to prevent regressions.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Walkthrough

This PR adds resolveChartPath to locate local Helm chart tarballs with optional leading "v" in versions, integrates it into the disk-to-mirror flow (errors are aggregated and processing continues), and adds tests covering matching, mismatching, missing, and an end-to-end DiskToMirror case.

Changes

Chart Version Prefix Resolution

Layer / File(s) Summary
Chart path resolution helper and integration
internal/pkg/helm/local_stored_collector.go
New resolveChartPath and helpers build {name}-{version}.tgz and a toggled v-prefixed variant, check existence with os.Stat, validate candidate paths against the base directory using filepath.Rel, and return descriptive errors. IsDiskToMirror (disk-to-mirror loop) now calls this helper and appends resolution errors to the collector's error list when resolution fails.
Version prefix mismatch test coverage
internal/pkg/helm/local_stored_collector_test.go
Added TestResolveChartPath validating matching, mismatching, and missing tarball cases and TestHelmImageCollectorVPrefixDiskToMirror validating end-to-end DiskToMirror behavior when config and on-disk versions differ only by a v prefix. Also added strings import used by tests.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
Stable And Deterministic Test Names ✅ Passed PASS: Added tests use static string literals for subtest names (t.Run(tc.name/...)); no timestamps/UUIDs/random pod/namespace names are constructed in test titles (only in setup/assertions).
Test Structure And Quality ✅ Passed Repo has no Ginkgo tests (no BeforeEach/AfterEach/Eventually/Consistently/Expect/NotTo). Added tests are table-driven with t.TempDir and local file setup; no cluster interactions or missing timeouts.
Microshift Test Compatibility ✅ Passed Only standard Go unit tests added in internal/pkg/helm (testing.T); no Ginkgo e2e tests or MicroShift-incompatible OpenShift APIs/resources referenced.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PR adds Go unit tests (testing.T) for Helm path resolution; no new Ginkgo e2e tests or multi-node/SNO topology assumptions found.
Topology-Aware Scheduling Compatibility ✅ Passed PR changes are limited to Helm chart path resolution (local_stored_collector.go/test); scanning those files found no affinity/anti-affinity/topologySpread/PDB/nodeSelector or control-plane scheduli...
Ote Binary Stdout Contract ✅ Passed PR only touches helm collector/test files; verified tests/e2e/cmd/main.go and modified files have no fmt.Print/os.Stdout or klog.LogToStderr/SetOutput calls in process-level setup.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Inspected PR’s touched files (local_stored_collector*.go): no Ginkgo e2e tests (no Describe/It) and no IPv4/external-connectivity assumptions; HTTP is mocked via local files.
No-Weak-Crypto ✅ Passed Checked the PR-changed files (local_stored_collector.go and _test.go) for MD5/SHA1/DES/RC4/3DES/Blowfish/ECB (incl. cipher.NewECB) and secret/token compare patterns; none found.
Container-Privileges ✅ Passed Repo scan for privileged:true/hostPID/hostNetwork/hostIPC/SYS_ADMIN/allowPrivilegeEscalation:true/runAsUser:0 in YAML/JSON/Go found 0 matches; PR only touches helm collector logic/tests.
No-Sensitive-Data-In-Logs ✅ Passed Checked local_stored_collector.go logging: resolveChartPath debug logs only chart name/basenames; scans found no token/password/secret/Authorization or embedded credential patterns in the code touc...
Title check ✅ Passed The title clearly identifies the specific fix: tolerating v-prefix version mismatches in the disk-to-mirror flow for Helm charts, which directly aligns with the main change in the changeset.

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

✨ 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 and usage tips.

@openshift-ci openshift-ci Bot requested review from adolfo-ab and r4f4 June 4, 2026 10:43

@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: 2

🧹 Nitpick comments (1)
internal/pkg/helm/local_stored_collector_test.go (1)

771-777: ⚡ Quick win

Assert the descriptive error contract in the not-found case.

Line 772 only checks that an error exists. Since this helper is expected to report both attempted candidates, assert those path fragments to prevent silent regressions in error quality.

✅ Suggested test addition
 			got, err := resolveChartPath(dir, tc.chartName, tc.version)
 			if tc.wantErr {
 				assert.Error(t, err)
+				assert.Contains(t, err.Error(), fmt.Sprintf("%s-%s.tgz", tc.chartName, tc.version))
+				altVersion := "v" + tc.version
+				if strings.HasPrefix(tc.version, "v") {
+					altVersion = strings.TrimPrefix(tc.version, "v")
+				}
+				assert.Contains(t, err.Error(), fmt.Sprintf("%s-%s.tgz", tc.chartName, altVersion))
 				return
 			}
🤖 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/pkg/helm/local_stored_collector_test.go` around lines 771 - 777,
When tc.wantErr is true, instead of only checking that err is non-nil, also
assert the error string includes the two attempted path fragments so the
descriptive "not found" contract doesn't regress; update the block inside the if
tc.wantErr branch in local_stored_collector_test.go to call assert.Error(t, err)
followed by assert.Contains(t, err.Error(), tc.candidateA) and
assert.Contains(t, err.Error(), tc.candidateB) (use the actual test-case fields
that hold the two candidate paths) so both attempted candidates are verified in
the error message.
🤖 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/pkg/helm/local_stored_collector.go`:
- Around line 363-381: The code builds primary and alt paths from untrusted
name/version (primary, alt) and can escape dir via path traversal; sanitize and
canonicalize: first reject or normalize name and version (remove path separators
or enforce a regex), then construct candidate paths and call filepath.Clean +
filepath.Abs on both the candidate and dir, and verify the candidate is inside
dir (e.g., use filepath.Rel or check that candidateAbs has dirAbs as a prefix)
before using them; apply these checks for both primary and alt before calling
os.Stat and before returning or logging (referencing variables primary, alt,
dir, name, version and the local_stored_collector logic).
- Around line 364-379: The code treats any os.Stat error as "file missing" for
primary and alt chart paths (variables primary and alt), which hides real
permission/I/O failures; update both os.Stat checks so that if err != nil and
!os.IsNotExist(err) you immediately return the wrapped error (include context
like the path and the original err) instead of falling through — keep the
existing not-found logic when os.IsNotExist(err) is true and retain the
lsc.Log.Debug call only when switching to the v-prefixed alt variant.

---

Nitpick comments:
In `@internal/pkg/helm/local_stored_collector_test.go`:
- Around line 771-777: When tc.wantErr is true, instead of only checking that
err is non-nil, also assert the error string includes the two attempted path
fragments so the descriptive "not found" contract doesn't regress; update the
block inside the if tc.wantErr branch in local_stored_collector_test.go to call
assert.Error(t, err) followed by assert.Contains(t, err.Error(), tc.candidateA)
and assert.Contains(t, err.Error(), tc.candidateB) (use the actual test-case
fields that hold the two candidate paths) so both attempted candidates are
verified in the error message.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 35417b06-f3d1-49a0-9673-a498abbe2d25

📥 Commits

Reviewing files that changed from the base of the PR and between cd8e7ec and a539ead.

📒 Files selected for processing (2)
  • internal/pkg/helm/local_stored_collector.go
  • internal/pkg/helm/local_stored_collector_test.go

Comment thread internal/pkg/helm/local_stored_collector.go Outdated
Comment thread internal/pkg/helm/local_stored_collector.go Outdated
During the disk-to-mirror phase oc-mirror reconstructed chart tarball
paths as {name}-{version}.tgz, but the Helm downloader saves files
using the URL basename from the repository index.yaml, which may embed
a "v" prefix (e.g. csi-driver-nfs-v4.9.0.tgz). This caused d2m to
fail with "file not found" even though the m2d download succeeded.

Introduce resolveChartPath which tries the primary path first and falls
back to toggling the "v" prefix on the version component:
- Path traversal is prevented by confining both candidates to the
  charts directory via filepath.Rel.
- Non-ENOENT os.Stat errors (permission/I/O) are surfaced immediately
  rather than being silently treated as "file missing".
- A descriptive error naming both attempted paths is returned when
  neither candidate exists.

Add two new test functions:
- TestResolveChartPath: unit tests for the helper covering all four
  cases (exact match, config omits v / disk has v, config has v / disk
  has no v, both missing). The not-found case asserts both candidate
  path fragments appear in the error message.
- TestHelmImageCollectorVPrefixDiskToMirror: end-to-end d2m collector
  test that places a v-prefixed chart on disk while the config specifies
  the bare version, and the reverse.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Sourav21jain Sourav21jain force-pushed the fix/helm-v-prefix-version-mismatch branch from a539ead to 54ced19 Compare June 4, 2026 10:58
@Sourav21jain

Copy link
Copy Markdown
Contributor Author

/test lint

@aguidirh

Copy link
Copy Markdown
Contributor

Hi @Sourav21jain,

Could you please have a look on the lint job failing and also provide the image set config you used to test the scenario with and without v ?

Thanks.

@Sourav21jain

Copy link
Copy Markdown
Contributor Author
  1. Create a file named isc-non-consistent-charts-filenames.yaml with the following contents:
    kind: ImageSetConfiguration
    apiVersion: mirror.openshift.io/v2alpha1
    mirror:
    helm:
    repositories:
  2. Create the mirror:
    oc-mirror -c ./isc-non-consistent-charts-filenames.yaml file:///opt/oc-mirror --v2
  3. Attempt to upload the mirror:
    oc-mirror -c ./isc-non-consistent-charts-filenames.yaml --from file:///opt/oc-mirror docker://[mirror-regstry] --v2

Extract chartPathExists helper to handle os.Stat + error classification
logic, dropping resolveChartPath's cyclomatic complexity from 11 to 6
to satisfy the cyclop linter's max-complexity limit of 10.

Also promote buildChartCandidatePath and toggleVersionPrefix from
inline closures to package-level functions for clarity.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Sourav21jain

Copy link
Copy Markdown
Contributor Author

@aguidirh I have updated the code as well as the file for testing. If you need anything else please let me know.

@aguidirh aguidirh left a comment

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.

Thanks for fixing it! I noticed we can simplify this implementation using the semver.NewVersion() function that we already use elsewhere in the codebase (e.g., internal/pkg/config/validate.go).

The semver.NewVersion() function from github.com/Masterminds/semver/v3 automatically handles the "v" prefix - it accepts both "v5.0.0" and "5.0.0" and normalizes them to "5.0.0".

I've tested this approach and it seems it works fine.


1. Add semver import:

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io/fs"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/Masterminds/semver/v3"  // Add this line
	helmchart "helm.sh/helm/v3/pkg/chart"
	// ... rest of imports

2. Simplication of the resolveChartPath() function:

func resolveChartPath(dir, name, version string) (string, error) {
	// Normalize version using semver (handles v-prefix automatically)
	ver, err := semver.NewVersion(version)
	if err != nil {
		return "", fmt.Errorf("invalid chart version %q: %w", version, err)
	}
	canonical := ver.String() // always without "v"

	baseDir := filepath.Clean(dir)

	// Try both candidates: with and without v-prefix in filename
	candidateVersions := []string{canonical, "v" + canonical}
	var candidatePaths []string

	for _, candidateVer := range candidateVersions {
		path, err := buildChartCandidatePath(baseDir, name, candidateVer)
		if err != nil {
			return "", err
		}
		candidatePaths = append(candidatePaths, path)

		exists, err := chartPathExists(path)
		if err != nil {
			return "", err
		}
		if exists {
			return path, nil
		}
	}

	return "", fmt.Errorf("chart file not found for %s version %s: tried %s and %s", 
		name, version, filepath.Base(candidatePaths[0]), filepath.Base(candidatePaths[1]))
}

3. Removal the toggleVersionPrefix() function

@aguidirh

Copy link
Copy Markdown
Contributor

Also, please create a bug on OCPBUGS and add it to the beginning of the PR title like OCPBUGS-NUMBER: , otherwise we won't be able to backport it.

Replace manual v-prefix toggling with semver.NewVersion() which already
exists in the codebase. semver.String() always returns the canonical
form without a "v" prefix, so we can deterministically probe both
"{name}-{canonical}.tgz" and "{name}-v{canonical}.tgz" in a loop,
removing the need for the toggleVersionPrefix() helper.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Sourav21jain Sourav21jain changed the title fix(helm): tolerate v-prefix version mismatch in disk-to-mirror OCPBUGS-88461: fix(helm): tolerate v-prefix version mismatch in disk-to-mirror Jun 12, 2026
@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jun 12, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@Sourav21jain: This pull request references Jira Issue OCPBUGS-88461, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Description

During the disk-to-mirror (d2m) phase, oc-mirror constructs chart tarball
paths as {name}-{version}.tgz. However, the Helm downloader saves files
using the URL basename from the repository's index.yaml, which may include
a v prefix (e.g. csi-driver-nfs-v4.9.0.tgz). This causes d2m to fail
with file not found even though mirror-to-disk succeeded.

Root cause

Phase Who decides filename
m2d / m2m (download) Helm library — filepath.Base(url) from index
d2m (lookup) oc-mirror — fmt.Sprintf("%s-%s.tgz", name, version)

When the index URL contained a v prefix but the config did not (or
vice-versa), the reconstructed path never matched the file on disk.

Github / Jira issue: https://redhat.atlassian.net/browse/RFE-8530

Type of change

  • Code Improvements (Refactoring, Performance, CI upgrades, etc)

How Has This Been Tested?

  • TestResolveChartPath — unit tests for the helper (exact match,
    config omits v / disk has v, config has v / disk has no v, both missing)
  • TestHelmImageCollectorVPrefixDiskToMirror — end-to-end d2m collector
    test exercising both mismatch directions with a real chart tarball
  • Verified with the oc-mirror binary using --dry-run with a
    pre-seeded working-dir containing podinfo-v5.0.0.tgz and config
    specifying version: "5.0.0"

Summary by CodeRabbit

  • Bug Fixes

  • Improved local Helm chart archive resolution to reliably find on-disk chart packages when version strings include or omit a leading "v". Added safer path validation to prevent path traversal, treats missing files as non-fatal, and ensures processing continues when a chart path lookup fails.

  • Tests

  • Added tests covering v-prefix/version variations and end-to-end disk-to-mirror collection to prevent regressions.

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 openshift-eng/jira-lifecycle-plugin repository.

@Sourav21jain Sourav21jain requested a review from aguidirh June 12, 2026 09:00
@Sourav21jain

Copy link
Copy Markdown
Contributor Author

@aguidirh I have updated both the things, Can you please do a validation?

@Sourav21jain

Copy link
Copy Markdown
Contributor Author

/test unit

@Sourav21jain

Sourav21jain commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

@aguidirh

The ci/prow/unit failure is a pre-existing regression in main unrelated to this PR.

The failing test is:

--- FAIL: TestGetReleaseReferenceImages/TestGetReleaseReferenceImages_should_pass_(no_channels)
cincinnati_test.go:155: should return a related images
Root cause: In internal/pkg/release/client.go, NewOCPClient respects the UPDATE_URL_OVERRIDE environment variable (to redirect to a mock server in tests), but NewOKDClient does not. So the "no channels" test — which uses an OKD-only config — hits the real OKD server and gets empty results for the outdated stable-4.0 channel.

This can be confirmed by checking out main directly (without this PR's changes) and running:

go test -tags "json1 libdm_no_deferred_remove exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" ./internal/pkg/release/... -run TestGetReleaseReferenceImages -v
The test fails identically — our PR touches only internal/pkg/helm/, which has zero overlap with internal/pkg/release/.

The regression was introduced by PR #1373 ("CLID-547: v2: add list releases command"), commit 3e0ec76, which moved OKD URL to cincinnati.OkdUpdateURL but omitted the UPDATE_URL_OVERRIDE support that exists for the OCP client.

@Sourav21jain

Copy link
Copy Markdown
Contributor Author

/test unit

@aguidirh

Copy link
Copy Markdown
Contributor

/retest

@aguidirh

Copy link
Copy Markdown
Contributor

/jira refresh

@openshift-ci-robot openshift-ci-robot added the jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. label Jun 12, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@aguidirh: This pull request references Jira Issue OCPBUGS-88461, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state New, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

/jira refresh

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot removed the jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. label Jun 12, 2026
@aguidirh

Copy link
Copy Markdown
Contributor

@aguidirh

The ci/prow/unit failure is a pre-existing regression in main unrelated to this PR.

The failing test is:

--- FAIL: TestGetReleaseReferenceImages/TestGetReleaseReferenceImages_should_pass_(no_channels) cincinnati_test.go:155: should return a related images Root cause: In internal/pkg/release/client.go, NewOCPClient respects the UPDATE_URL_OVERRIDE environment variable (to redirect to a mock server in tests), but NewOKDClient does not. So the "no channels" test — which uses an OKD-only config — hits the real OKD server and gets empty results for the outdated stable-4.0 channel.

This can be confirmed by checking out main directly (without this PR's changes) and running:

go test -tags "json1 libdm_no_deferred_remove exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" ./internal/pkg/release/... -run TestGetReleaseReferenceImages -v The test fails identically — our PR touches only internal/pkg/helm/, which has zero overlap with internal/pkg/release/.

The regression was introduced by PR #1373 ("CLID-547: v2: add list releases command"), commit 3e0ec76, which moved OKD URL to cincinnati.OkdUpdateURL but omitted the UPDATE_URL_OVERRIDE support that exists for the OCP client.

@r4f4 could you please have a look ?

@Sourav21jain

Copy link
Copy Markdown
Contributor Author

/retest

@Sourav21jain

Copy link
Copy Markdown
Contributor Author

/retest

1 similar comment
@Sourav21jain

Copy link
Copy Markdown
Contributor Author

/retest

@Sourav21jain

Copy link
Copy Markdown
Contributor Author

@aguidirh All the checks are done can you review?

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 12, 2026

@r4f4 r4f4 left a comment

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.

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jun 15, 2026

@adolfo-ab adolfo-ab left a comment

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.

/lgtm

@Sourav21jain

Copy link
Copy Markdown
Contributor Author

Hello @aguidirh I believe only your approval is remaining for the merge. Thank you in advance.

@r4f4

r4f4 commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Hello @aguidirh I believe only your approval is remaining for the merge. Thank you in advance.

@Sourav21jain No, the PR is awaiting QE verification now.

/cc @nidangavali

@openshift-ci openshift-ci Bot requested a review from nidangavali June 16, 2026 07:28
@nidangavali

Copy link
Copy Markdown
Contributor

/verified by @nidangavali

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Jun 16, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@nidangavali: This PR has been marked as verified by @nidangavali.

Details

In response to this:

/verified by @nidangavali

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci

openshift-ci Bot commented Jun 16, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: adolfo-ab, aguidirh, nidangavali, Sourav21jain

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 commented Jun 16, 2026

Copy link
Copy Markdown

@Sourav21jain: all tests passed!

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.

@openshift-merge-bot openshift-merge-bot Bot merged commit f36d52d into openshift:main Jun 16, 2026
12 checks passed
@openshift-ci-robot

Copy link
Copy Markdown

@Sourav21jain: Jira Issue Verification Checks: Jira Issue OCPBUGS-88461
✔️ This pull request was pre-merge verified.
✔️ All associated pull requests have merged.
✔️ All associated, merged pull requests were pre-merge verified.

Jira Issue OCPBUGS-88461 has been moved to the MODIFIED state and will move to the VERIFIED state when the change is available in an accepted nightly payload. 🕓

Details

In response to this:

Description

During the disk-to-mirror (d2m) phase, oc-mirror constructs chart tarball
paths as {name}-{version}.tgz. However, the Helm downloader saves files
using the URL basename from the repository's index.yaml, which may include
a v prefix (e.g. csi-driver-nfs-v4.9.0.tgz). This causes d2m to fail
with file not found even though mirror-to-disk succeeded.

Root cause

Phase Who decides filename
m2d / m2m (download) Helm library — filepath.Base(url) from index
d2m (lookup) oc-mirror — fmt.Sprintf("%s-%s.tgz", name, version)

When the index URL contained a v prefix but the config did not (or
vice-versa), the reconstructed path never matched the file on disk.

Github / Jira issue: https://redhat.atlassian.net/browse/RFE-8530

Type of change

  • Code Improvements (Refactoring, Performance, CI upgrades, etc)

How Has This Been Tested?

  • TestResolveChartPath — unit tests for the helper (exact match,
    config omits v / disk has v, config has v / disk has no v, both missing)
  • TestHelmImageCollectorVPrefixDiskToMirror — end-to-end d2m collector
    test exercising both mismatch directions with a real chart tarball
  • Verified with the oc-mirror binary using --dry-run with a
    pre-seeded working-dir containing podinfo-v5.0.0.tgz and config
    specifying version: "5.0.0"

Summary by CodeRabbit

  • Bug Fixes

  • Improved local Helm chart archive resolution to reliably find on-disk chart packages when version strings include or omit a leading "v". Added safer path validation to prevent path traversal, treats missing files as non-fatal, and ensures processing continues when a chart path lookup fails.

  • Tests

  • Added tests covering v-prefix/version variations and end-to-end disk-to-mirror collection to prevent regressions.

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 openshift-eng/jira-lifecycle-plugin repository.

@aguidirh

Copy link
Copy Markdown
Contributor

/cherry-pick release-4.22

@openshift-cherrypick-robot

Copy link
Copy Markdown

@aguidirh: new pull request created: #1448

Details

In response to this:

/cherry-pick release-4.22

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. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants