From 314c1039abfb0b72ad0150d42b0e1da416b8e6d6 Mon Sep 17 00:00:00 2001 From: Evan Anderson Date: Mon, 16 Jun 2025 14:53:37 -0700 Subject: [PATCH] Support Helm semver encoding in OCI repositories Signed-off-by: Evan Anderson --- internal/controller/ocirepository_controller.go | 9 +++++++-- .../controller/ocirepository_controller_test.go | 5 +++-- .../podinfo/podinfo-6.1.7_ref.1234567.tar | Bin 0 -> 14848 bytes 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 internal/controller/testdata/podinfo/podinfo-6.1.7_ref.1234567.tar diff --git a/internal/controller/ocirepository_controller.go b/internal/controller/ocirepository_controller.go index 5056d66f5..24ca7ca4b 100644 --- a/internal/controller/ocirepository_controller.go +++ b/internal/controller/ocirepository_controller.go @@ -898,7 +898,11 @@ func (r *OCIRepositoryReconciler) getTagBySemver(repo name.Repository, exp strin var matchingVersions []*semver.Version for _, t := range validTags { - v, err := version.ParseVersion(t) + // Helm translates `+` to `_` in OCI tags, because `+` is not a valid tag character. + versionStr := strings.Replace(t, "_", "+", 1) + // It would be even better to use `org.opencontainers.image.version` annotation + // if present, but that adds a fetch for each tag. + v, err := version.ParseVersion(versionStr) if err != nil { continue } @@ -913,7 +917,8 @@ func (r *OCIRepositoryReconciler) getTagBySemver(repo name.Repository, exp strin } sort.Sort(sort.Reverse(semver.Collection(matchingVersions))) - return repo.Tag(matchingVersions[0].Original()), nil + asTag := strings.Replace(matchingVersions[0].Original(), "+", "_", 1) + return repo.Tag(asTag), nil } // keychain generates the credential keychain based on the resource diff --git a/internal/controller/ocirepository_controller_test.go b/internal/controller/ocirepository_controller_test.go index aa024082f..ff723c85e 100644 --- a/internal/controller/ocirepository_controller_test.go +++ b/internal/controller/ocirepository_controller_test.go @@ -2866,6 +2866,7 @@ func TestOCIRepository_getArtifactRef(t *testing.T) { "6.1.5", "6.1.6-rc.1", "6.1.6", + "6.1.7_ref.1234567", // Version 6.1.7+ref.1234567, encoded as a tag ) g.Expect(err).ToNot(HaveOccurred()) @@ -2898,12 +2899,12 @@ func TestOCIRepository_getArtifactRef(t *testing.T) { want: "ghcr.io/stefanprodan/charts@" + imgs["6.1.6"].digest.String(), }, { - name: "valid url with semver reference", + name: "valid url with semver reference and build identifier", url: fmt.Sprintf("oci://%s/podinfo", server.registryHost), reference: &sourcev1.OCIRepositoryRef{ SemVer: ">= 6.1.6", }, - want: server.registryHost + "/podinfo:6.1.6", + want: server.registryHost + "/podinfo:6.1.7_ref.1234567", }, { name: "invalid url without oci prefix", diff --git a/internal/controller/testdata/podinfo/podinfo-6.1.7_ref.1234567.tar b/internal/controller/testdata/podinfo/podinfo-6.1.7_ref.1234567.tar new file mode 100644 index 0000000000000000000000000000000000000000..09616c2dfabc3ca74b251763d2de655d892e2629 GIT binary patch literal 14848 zcmeHNZExE)5YFfP3PQzz4XADE{RPN}E$Pr;SskQF2dpRpTB2;OlBiL%Q8&nc-%)Ro zT_;XzHz-yK0U{soj>kLR@gYSo@;vIhB-F9%IuUkE98Mw&`_#r5$2z7_>>8o1o4V&< z2UFK`V$U>VOfBM?=ICJigRzBO+dcq=>RJEarB&~`YwN}VvbU?=onu}|BEY0wH7U#C zX$QBfzGss6c8&kLR~K(j$8R1o7wZ^1mesnZ@>J_8_-Qt6l?x4Q+xP(O9FvEPYTADA z`0K-G@p9ws{{MI8ft~aJpMqyw#b;D?DLzDj&hWh_3GxG<}{~L`(TA=MZ4YZe9 zC@7IsDT5&DgYxeZQU-2J{PsHj?g zm6C+Bw=!ax7Q`ee=u54o@wxnxNCk-2oR@OhzK?U7t?DU%jk6GpsQF)I3oXdzN%B%V zPGLmV>uE}+wW05LGEZsIwEV@zN0v=bSZ(dAOp0aBSq64hvg7QxIZIkqXJkT?TKu;3 zOz)4@AGce|N#DFj5A2%wql7G}7%B{X@AGi|*Bz)AYxqw$%^v^V>(6~Q3`ZYf1>`CF zO!ujFMVDICpSJ&l-KO2||5lv%jefMzA4N1z_%fxL94<+k?6E%;{|EMers3$T`LA0h zhWPjRZ;wH^M-|E0J1PpsvjCAiFGdUf5U@-Xpp$k!9Hvx~h)5C~BBan+fN~BY191N|6 z6o4eBOQjgJ@B~<cWN*zsT2nJNLDUso< z!e5Ot828CTcro3b+PnItxWC?};B%g^a2cS}_zjom5HctaEteWX+dD!{|1&A`mZxLrc{yU=^Sw?h zm?3${lK@>FpSSd`ssT7nu&`(wzf=i6?6f|taw_t$!`!;Dw$AtcPU~h>Ax~2RDbg|y z(6Di2hc*}}2OX^pcz`NuGpHjK{}mZ!UoF_RMG2Nouq9fskPcKH9yMvGCWLwvS3(yw zIV!WWB35Jp7V~rvQ2=a5 z(eUFMZEX%JwuFZynZbTDP!So;C`sh(b4QM4Ofr(3C=ay-NmZ-nku0UK*WAzsTVJS$ z-^C=wKpit8kN7$oKOsTw}akY-D^jTw0Rb#)vor<`M zH*2Js11ceaG7YFT00l1qs#XL`5h}c(`WiHlkXBW!EKPu7%92(Y)ARuKt84}QS6bV& zHmLGSvV?sufnUvs&jjn951jvCOLy1u-?W|n{Aa&GxJO$z|J$RVx78l=5zBjZ;&Plo zO`zgbZQxf=Th@*+IwuC*Eq=WMs#aL>?hXhxZNID4x!SF_yF9fsEM@Pu%w4|Do_~|d z3SyK@_jsu%_a5jy(0kzj=K<=5wxMG`_NWQBE?tLso)<^9t4ATGcw)f?P>*;x@=dH8 z*t1-V7{tfU1QR0)!{P4tf3RtEF&xA`CXY93*iL=;{s-LtUC)1AcX5CIx81RO;D8K1u5aUMdsz!0o8dT)Uy^B= z%^N>DHj}PszM55^A2p~IXX-jpDY?I!Nl*$t^hXVwCyRhs6%4+PGg@rs*qyp9{~_Dg y_W!zL_xZoO;~$~nMtfX_s#UwZBLK_xu9>Ob-uCJEh}iTjy$5;^^d9(@9{3LiHH=>X literal 0 HcmV?d00001