Skip to content

Helm OCI build-info resolution fails for charts stored under non-root subpaths #424

Description

@vjda

Describe the bug

When the Helm build-info flow works with OCI charts stored under a non-root path inside an Artifactory OCI repository, it can resolve the wrong Artifactory path and miss artifacts that do exist.

This showed up in two concrete places:

  • jf helm push post-push build-info collection
  • OCI dependency layer resolution in addOCILayersForDependency

In both cases, the root problem is the same: the follow-up lookup assumes the OCI storage path inside Artifactory is always:

<chart-name>/<chart-version>

That assumption is only valid when the chart was pushed at the repository root. For valid OCI repository URLs that include additional path segments, the real storage path is:

<resolved-subpath>/<chart-name>/<chart-version>

As a result, the CLI searches the wrong path and misses manifests/layers that were actually uploaded and do exist in Artifactory.

Current behavior

Two broken behaviors can be observed today when the OCI URL contains a non-root path:

  1. jf helm push can succeed, but the follow-up build-info collection step can fail because it looks under chart/version instead of the real subpath/chart/version.
  2. OCI dependency layer resolution can silently miss dependency artifacts for the same reason: dep.Id only contains chart:version, while the missing subpath lives in dep.Repository.

Examples of valid OCI repository layouts:

  • repo in host, no path
    • oci://helm-repo.artifactory.acme.example.com
  • repo in host, with subpath
    • oci://helm-repo.artifactory.acme.example.com/team-a/charts
  • repo in path, no extra subpath
    • oci://artifactory.acme.example.com/helm-repo
  • repo in path, with extra subpath
    • oci://artifactory.acme.example.com/helm-repo/team-a/charts

Before the fix, the root-only cases work, but the non-root cases can fail because the lookup path ignores the resolved subpath.

This is especially confusing because the OCI artifacts are already present in Artifactory. The failure happens later, during build-info/layer resolution.

Reproduction steps

One concrete push reproduction path is:

  1. Push a Helm chart to a valid OCI URL with a non-root path, for example:
    • oci://helm-repo.artifactory.acme.example.com/team-a/charts
    • or oci://artifactory.acme.example.com/helm-repo/team-a/charts
  2. Run the push through the JFrog CLI build-info flow (jf helm push ...).
  3. Observe that the native Helm push succeeds.
  4. Observe that the follow-up build-info collection looks for OCI artifacts under chart-name/chart-version instead of under team-a/charts/chart-name/chart-version.
  5. Build-info collection fails to find the uploaded manifest/layers even though the artifact exists in Artifactory.

One concrete OCI dependency reproduction path is:

  1. Define a dependency with an OCI repository URL that contains a non-root path, for example:
    • oci://helm-repo.artifactory.acme.example.com/team-a/charts
    • or oci://artifactory.acme.example.com/helm-repo/team-a/charts
  2. Ensure the dependency is stored in Artifactory under the real path: team-a/charts/chart-name/chart-version
  3. Run the build-info flow that resolves OCI dependency layers.
  4. Observe that the dependency lookup searches chart-name/chart-version instead of team-a/charts/chart-name/chart-version.
  5. The dependency is skipped or left unresolved even though its OCI artifacts exist.

Expected behavior

The Helm OCI build-info flow should resolve artifacts correctly both at the repository root and under non-root subpaths.

Expected behavior:

  • host-only root pushes still work as before
  • path-based root pushes still work as before
  • host-based pushes with subpath resolve the correct repo key and subpath
  • path-based pushes with subpath resolve the correct repo key and subpath
  • OCI dependency resolution uses the same real Artifactory storage semantics for subpath cases
  • once repo key and subpath are resolved, the CLI searches Artifactory using the real storage path:
    • subpath/chart-name/chart-version
  • build properties / manifest-folder annotation use the same resolved Artifactory location instead of assuming a root-only chart layout
  • OCI dependency layer resolution uses the same resolved storage path instead of assuming the dependency chart is at repo root

JFrog CLI-Core version

github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260414083544-243b4d55328b

JFrog CLI-Artifactory version

source checkout (commit e9db596)

JFrog CLI version (if applicable)

jf version 2.100.0

Operating system type and version

macOS darwin arm64

JFrog Artifactory version

N.A

Additional context

  • This report is limited to OCI behavior.
  • It covers both jf helm push post-push build-info for non-root subpaths and jf helm dependency OCI dependency layer resolution for non-root subpaths.
  • Classic Helm remains out of scope and unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions