Is there an existing issue for this?
Current Behavior
A Fleet HelmOp pointing at an OCI Helm chart whose only published tags use
the Helm build-metadata convention (semver X.Y.Z+upA.B.C, stored in the
registry as the OCI-safe tag X.Y.Z_upA.B.C) never becomes Accepted. Fleet's
OCI version resolver treats spec.helm.version as a semver constraint and
fails to resolve a chart for every value of version — a specific
build-metadata version, the underscore tag, the plain X.Y.Z, and empty.
The same chart installs fine with the Helm CLI, which requests the tag directly
instead of listing + semver-matching.
Expected Behavior
Fleet should resolve and install the chart. In particular, a constraint of
109.0.1 (or the exact 109.0.1+up1.0.2) should match the published chart
version 109.0.1+up1.0.2, since semver comparison ignores build metadata.
Contrast: the Helm CLI works
Helm requests the tag directly (converting + -> _) instead of
listing + semver-matching, so it succeeds:
helm show chart oci://registry.suse.com/rancher/charts/rancher-ai-agent --version 109.0.1+up1.0.2
# Pulled: registry.suse.com/rancher/charts/rancher-ai-agent:109.0.1_up1.0.2
# ... version: 109.0.1+up1.0.2
helm pull oci://registry.suse.com/rancher/charts/rancher-ai-agent --version 109.0.1+up1.0.2
# downloads rancher-ai-agent-109.0.1_up1.0.2.tgz
### Steps To Reproduce
```bash
kubectl apply -f helmop.yaml
# Read the Accepted condition:
kubectl get helmop liz-agent-repro -n fleet-local \
-o jsonpath='{.status.conditions[?(@.type=="Accepted")].status} {.status.conditions[?(@.type=="Accepted")].message}{"\n"}'
To test the other version values, edit spec.helm.version in helmop.yaml,
re-apply, and re-read the condition.
Cleanup:
kubectl delete -f helmop.yaml
The helmop file:
# Minimal Fleet HelmOp that reproduces the OCI "+up"/"_up" tag resolution
# failure. No Rancher AI Factory operator involved — this is pure Fleet.
#
# The chart's only published OCI tags use Rancher's build-metadata convention
# (e.g. 109.0.1_up1.0.2, which is the OCI-safe encoding of the semver
# 109.0.1+up1.0.2). Fleet's HelmOp OCI resolver treats spec.helm.version as a
# semver constraint and lists/filters the registry tags; it never resolves a
# chart for any value of version (see README.md for the matrix).
#
# Apply, then read the Accepted condition:
# kubectl apply -f helmop.yaml
# kubectl get helmop liz-agent-repro -n fleet-local \
# -o jsonpath='{.status.conditions[?(@.type=="Accepted")].status} {.status.conditions[?(@.type=="Accepted")].message}{"\n"}'
# kubectl delete -f helmop.yaml # cleanup
apiVersion: fleet.cattle.io/v1alpha1
kind: HelmOp
metadata:
name: liz-agent-repro
namespace: fleet-local
spec:
defaultNamespace: default
helm:
releaseName: liz-agent-repro
repo: oci://registry.suse.com/rancher/charts/rancher-ai-agent
# Try each of these values (one at a time) — all fail; see README.md:
# version: "109.0.1+up1.0.2" # -> could not find tag matching constraint
# version: "109.0.1_up1.0.2" # -> improper constraint (invalid semver)
# version: "109.0.1" # -> could not find tag matching constraint
# version: "" # -> improper constraint (empty)
version: "109.0.1+up1.0.2"
takeOwnership: true
targets:
- clusterName: local
Environment
- Architecture: arm64
- Fleet Version: 0.15.2
- Cluster:
- Provider:
- Options:
- Kubernetes Version: v1.35.6+k3s1
- Fleet version: registry.rancher.com/rancher/fleet:v0.15.2
- Rancher version: 2.14.2
- Kubernetes: rancher-desktop (but irrelevant I guess)
- Registry: `registry.suse.com/rancher/charts/rancher-ai-agent`
(any OCI chart whose tags all carry `+up`/`_up` build metadata reproduces this)
Logs
Anything else?
Likely root cause
Fleet's OCI resolver enumerates the repository tags and parses each as semver to
build the candidate set for constraint matching. Tags encoded the OCI-safe way
(_up, because + is not allowed in OCI tags) fail semver parsing and are
dropped, leaving an empty candidate set — so no constraint can match. The
resolver does not apply Helm's _ -> + reverse conversion before parsing, nor
does it fall back to a direct tag pull the way the Helm CLI does.
Suggested fixes
- When listing OCI tags, reverse Helm's encoding (
_ -> +) before semver
parsing, so 109.0.1_up1.0.2 is considered as 109.0.1+up1.0.2.
- And/or, when
spec.helm.version is an exact version, request that tag directly
(Helm-CLI behavior) instead of list + constraint-match.
Observed results (all fail)
spec.helm.version |
Accepted |
message |
109.0.1+up1.0.2 |
False |
could not get a chart version: could not find tag matching constraint "109.0.1+up1.0.2" in registry oci://registry.suse.com/rancher/charts/rancher-ai-agent: %!w(<nil>) |
109.0.1_up1.0.2 |
False |
... failed to compute version constraint from version "109.0.1_up1.0.2": improper constraint: 109.0.1_up1.0.2 |
109.0.1 |
False |
could not get a chart version: could not find tag matching constraint "109.0.1" in registry oci://registry.suse.com/rancher/charts/rancher-ai-agent: %!w(<nil>) |
| `` (empty) |
False |
... failed to compute version constraint from version "": improper constraint: |
Notes:
%!w(<nil>) is a Go fmt artifact of wrapping a nil error — i.e. the tag
listing returned no usable candidates and no underlying error, so the
constraint matched nothing.
- The available registry tags (via
crane ls registry.suse.com/rancher/charts/rancher-ai-agent)
are all of the form 10x.y.z_upA.B.C — there is no plain-semver tag and no
latest tag.
Is there an existing issue for this?
Current Behavior
A Fleet
HelmOppointing at an OCI Helm chart whose only published tags usethe Helm build-metadata convention (semver
X.Y.Z+upA.B.C, stored in theregistry as the OCI-safe tag
X.Y.Z_upA.B.C) never becomesAccepted. Fleet'sOCI version resolver treats
spec.helm.versionas a semver constraint andfails to resolve a chart for every value of
version— a specificbuild-metadata version, the underscore tag, the plain
X.Y.Z, and empty.The same chart installs fine with the Helm CLI, which requests the tag directly
instead of listing + semver-matching.
Expected Behavior
Fleet should resolve and install the chart. In particular, a constraint of
109.0.1(or the exact109.0.1+up1.0.2) should match the published chartversion
109.0.1+up1.0.2, since semver comparison ignores build metadata.Contrast: the Helm CLI works
Helm requests the tag directly (converting
+->_) instead oflisting + semver-matching, so it succeeds:
To test the other
versionvalues, editspec.helm.versioninhelmop.yaml,re-apply, and re-read the condition.
Cleanup:
The helmop file:
Environment
Logs
Anything else?
Likely root cause
Fleet's OCI resolver enumerates the repository tags and parses each as semver to
build the candidate set for constraint matching. Tags encoded the OCI-safe way
(
_up, because+is not allowed in OCI tags) fail semver parsing and aredropped, leaving an empty candidate set — so no constraint can match. The
resolver does not apply Helm's
_->+reverse conversion before parsing, nordoes it fall back to a direct tag pull the way the Helm CLI does.
Suggested fixes
_->+) before semverparsing, so
109.0.1_up1.0.2is considered as109.0.1+up1.0.2.spec.helm.versionis an exact version, request that tag directly(Helm-CLI behavior) instead of list + constraint-match.
Observed results (all fail)
spec.helm.version109.0.1+up1.0.2could not get a chart version: could not find tag matching constraint "109.0.1+up1.0.2" in registry oci://registry.suse.com/rancher/charts/rancher-ai-agent: %!w(<nil>)109.0.1_up1.0.2... failed to compute version constraint from version "109.0.1_up1.0.2": improper constraint: 109.0.1_up1.0.2109.0.1could not get a chart version: could not find tag matching constraint "109.0.1" in registry oci://registry.suse.com/rancher/charts/rancher-ai-agent: %!w(<nil>)... failed to compute version constraint from version "": improper constraint:Notes:
%!w(<nil>)is a Gofmtartifact of wrapping anilerror — i.e. the taglisting returned no usable candidates and no underlying error, so the
constraint matched nothing.
crane ls registry.suse.com/rancher/charts/rancher-ai-agent)are all of the form
10x.y.z_upA.B.C— there is no plain-semver tag and nolatesttag.