feat: version aliasing#2049
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds mutable OCI-style aliases for component versions, centralizes component-version descriptor validation in a new validate package, removes store-side retag reconciliation (now relying on index.AddArtifact), and adds repository implementation and tests for alias management and resolution. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Repository
participant Store
participant Validator
Client->>Repository: AddComponentVersionAlias(component, versionOrAlias, alias)
Repository->>Repository: reject if alias matches semverRegex
Repository->>Store: getStore(versionOrAlias) / Resolve(ref)
Store-->>Repository: descriptor (or ErrNotFound)
Repository->>Validator: ComponentVersionDescriptor(ctx, Store, descriptor, component, ref)
Validator->>Store: Fetch(descriptor)
Store-->>Validator: payload reader
Validator->>Validator: decode manifest/index, extract annotation, validate component
Validator-->>Repository: parsed version (or ErrInvalidComponentVersion)
Repository->>Store: Tag(descriptor, alias)
Store-->>Repository: success
Repository-->>Client: success / error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
jakobmoellerdev
left a comment
There was a problem hiding this comment.
This looks very promising already. just smaller implementation related comments, great job in concept!
|
--- Changes with latest commit ---
|
| Test | What it covers |
|---|---|
ListComponentVersions_WithAliases |
Aliases don't produce duplicate entries in version listings |
OverwritesExistingVersion |
Documents that aliasing over a real version tag is destructive |
GetLocalResource via alias |
Resource retrieval works through aliases on plain manifest path |
OCIImageIndex |
Aliasing works when component versions are stored behind an OCI image index |
Additional index_test.go cases |
AddArtifact rework: retag-from-untagged, multiple untagged artifacts |
@jakobmoellerdev should we prevent the behavior document with the TestRepository_AddComponentVersionAlias_OverwritesExistingVersion test in repository_test.go?
## Summary This PR extracts and upstreams the CTF index changes from the broader version aliasing feature #2049. It's part of this feature request open-component-model/ocm-project#720. ### Changes - **CTF index (`bindings/go/ctf/index/v1`)**: Reworked `AddArtifact` to match OCI Image Layout semantics — multiple entries with the same digest but different tags can now coexist. Previously, adding a new tag to an existing digest would overwrite the old tag. - Exact duplicates (same repo + tag + digest) are skipped - Retagging (same tag, different digest) clears the old tag - Tagging an untagged entry updates it in place - Added comprehensive tests covering multi-tag, deduplication, cross-repo isolation, and encode/decode round-tripping ### Context This is the foundational change for **version aliasing** (see draft PR: #2049, which allows multiple OCI tags to reference the same component version. The remaining OCI repository, CTF store, and validation changes will follow in a separate PR once this lands and a new version of the CTF module is released. Signed-off-by: Christoph Bleyer <christoph.bleyer@sap.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
bindings/go/oci/repository_test.go (1)
1601-1614: Add one more not-found case for missing target version on an existing component.Right now only the missing-component path is covered; adding missing-version coverage would better pin expected
ErrNotFoundbehavior.➕ Suggested test extension
func TestRepository_AddComponentVersionAlias_NonExistent(t *testing.T) { r := require.New(t) ctx := t.Context() fs, err := filesystem.NewFS(t.TempDir(), os.O_RDWR) r.NoError(err) store := ocictf.NewFromCTF(ctf.NewFileSystemCTF(fs)) repo := Repository(t, ocictf.WithCTF(store)) // Must fail for non-existent component err = repo.AddComponentVersionAlias(ctx, "non-existent", "1.0.0", "latest") r.Error(err) r.ErrorIs(err, repository.ErrNotFound) + + // Must also fail for non-existent version in an existing component + componentName := "ocm.software/test-component" + r.NoError(repo.AddComponentVersion(ctx, &descriptor.Descriptor{ + Meta: descriptor.Meta{Version: "v2"}, + Component: descriptor.Component{ + Provider: descriptor.Provider{Name: "test-provider"}, + ComponentMeta: descriptor.ComponentMeta{ + ObjectMeta: descriptor.ObjectMeta{Name: componentName, Version: "1.0.0"}, + }, + }, + })) + err = repo.AddComponentVersionAlias(ctx, componentName, "9.9.9", "latest") + r.Error(err) + r.ErrorIs(err, repository.ErrNotFound) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bindings/go/oci/repository_test.go` around lines 1601 - 1614, Extend TestRepository_AddComponentVersionAlias_NonExistent to also assert ErrNotFound when the component exists but the target version does not: create the component first (e.g., via Repository helper plus repo.AddComponentVersion or the existing API used elsewhere in this test file to add a version), then call repo.AddComponentVersionAlias(ctx, "<existing-component>", "<non-existent-version>", "latest") and assert r.Error(err) and r.ErrorIs(err, repository.ErrNotFound); keep the original missing-component assertion intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@bindings/go/oci/interface.go`:
- Around line 19-23: The ComponentVersionRepository interface currently embeds
AliasComponentVersionRepository which forces all downstream implementations to
implement aliasing; remove AliasComponentVersionRepository from the embedded
list in the ComponentVersionRepository declaration so aliasing remains opt-in
(keep embedding of repository.ComponentVersionRepository,
repository.HealthCheckable and ResourceDigestProcessor intact), update any local
implementations/mocks in this package that assumed the wider shape, and if
callers need alias behavior they should type-assert to
AliasComponentVersionRepository where required; optionally add a short comment
above ComponentVersionRepository explaining aliasing is intentionally opt-in via
type assertion.
In `@bindings/go/oci/internal/lister/component/component_versions.go`:
- Around line 76-80: The tag-based lookup currently emits duplicate canonical
versions because alias tags resolve to the same canonical version (via
validate.ComponentVersionDescriptor in component_versions.go) but
ListComponentVersions (the resolver that iterates tags in lister.go) appends
every tag result without deduplication; update the ListComponentVersions flow to
track canonical version identifiers (use the canonical value returned by
validate.ComponentVersionDescriptor — e.g., the resolved version
string/descriptor) and skip adding a result if that canonical ID was already
emitted (apply this when LookupPolicyTagOnly or tag-fallback logic is used),
ensuring only unique canonical versions are returned.
In `@bindings/go/oci/internal/validate/validate.go`:
- Around line 90-93: The parse error from
annotations.ParseComponentVersionAnnotation should be wrapped with the sentinel
validate.ErrInvalidComponentVersion so ListComponentVersions can treat it as
non-fatal; replace the current return that wraps the original error with one
that wraps validate.ErrInvalidComponentVersion (e.g. using fmt.Errorf with %w)
while preserving the underlying parse error message, updating the error return
in the block where candidate, version, err :=
annotations.ParseComponentVersionAnnotation(annotation) is handled.
In `@bindings/go/oci/repository.go`:
- Around line 869-894: The current flow (involving versionRegex, repo.getStore,
store.Resolve, validate.ComponentVersionDescriptor, and store.Tag) allows
creating an alias that would overwrite an existing declared version name; fix
this by checking whether the requested alias already resolves to an existing
component version before calling store.Tag: call store.Resolve(ctx,
aliasReference) (or Resolve with alias as reference) and if it returns a valid
base (i.e., not errdef.ErrNotFound) compare that resolved base/reference to the
base you intend to tag; if they differ, return a descriptive error rejecting the
alias creation (do not call store.Tag); if Resolve returns not found, proceed to
validate.ComponentVersionDescriptor and then store.Tag as before. Ensure you use
the same error wrapping style as other errors.
---
Nitpick comments:
In `@bindings/go/oci/repository_test.go`:
- Around line 1601-1614: Extend
TestRepository_AddComponentVersionAlias_NonExistent to also assert ErrNotFound
when the component exists but the target version does not: create the component
first (e.g., via Repository helper plus repo.AddComponentVersion or the existing
API used elsewhere in this test file to add a version), then call
repo.AddComponentVersionAlias(ctx, "<existing-component>",
"<non-existent-version>", "latest") and assert r.Error(err) and r.ErrorIs(err,
repository.ErrNotFound); keep the original missing-component assertion intact.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c56a4c71-e411-4312-bb94-2aed6e59d830
⛔ Files ignored due to path filters (1)
bindings/go/oci/go.sumis excluded by!**/*.sum
📒 Files selected for processing (9)
bindings/go/oci/ctf/store.gobindings/go/oci/ctf/store_test.gobindings/go/oci/go.modbindings/go/oci/interface.gobindings/go/oci/internal/lister/component/component_versions.gobindings/go/oci/internal/validate/validate.gobindings/go/oci/internal/validate/validate_test.gobindings/go/oci/repository.gobindings/go/oci/repository_test.go
I think this requires some thinking. If we have a CTF with a component version I believe we need to drop the old manifest in case the tag moves from one digest to another. WDYT? |
<!-- markdownlint-disable MD041 --> #### What this PR does / why we need it e2b46f9 introduced a change in `ocm.software/open-component-model/bindings/go/ctf v0.4.0` that [breaks tests](https://github.com/open-component-model/open-component-model/actions/runs/24078003573/job/70231212198?pr=2152) in `bindings/go/oci/ctf`. A [fix](#2049) is already in progress but it includes a bigger implementation that is not ready to merge yet. This is why, this PR reverts the version bump for that module for now. #### Which issue(s) this PR fixes Fixes #2152 #### Testing Run `task test` and `task test/integration` --------- Signed-off-by: Frederic Wilhelm <frederic.wilhelm@sap.com> Co-authored-by: ocmbot[bot] <125909804+ocmbot[bot]@users.noreply.github.com>
…no ctf) (#2194) <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it #2192 wants to bump. `bindings/go/ctf` again. However, this bump breaks other modules until the respective PR (#2049) is merged. That is why this PR reverts the version bump for this module. We might need to do this until the other PR is merged. Fixes #2192 --------- Signed-off-by: Frederic Wilhelm <frederic.wilhelm@sap.com> Co-authored-by: ocmbot[bot] <125909804+ocmbot[bot]@users.noreply.github.com>
@jakobmoellerdev Completely valid point! That would create a lot of orphaned entries over time as tags move through different digests... Especially a latest tag being retagged frequently will create lots of untagged entries, causing index bloat... Since this needs to be fixed on the ctf layer I have adressed this in a seperate PR: #2230. Let me know what you think about this there. |
✅ Deploy Preview for ocm-website ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
bindings/go/oci/ctf/store.go (1)
296-342:⚠️ Potential issue | 🟠 MajorReject unparseable references before writing index metadata.
If
looseref.ParseReference(reference)fails,metastays zero-valued and this still appends it to the index viaidx.AddArtifact(meta). With the new alias API, malformed user input can now hit this path and silently persist an empty artifact record instead of returning an error.Suggested fix
- if ref, err := looseref.ParseReference(reference); err == nil { - if err := ref.ValidateReferenceAsTag(); err == nil { + ref, err := looseref.ParseReference(reference) + if err != nil { + return fmt.Errorf("invalid reference %q: %w", reference, err) + } + if err := ref.ValidateReferenceAsTag(); err == nil { meta = v1.ArtifactMetadata{ Repository: repo, Tag: ref.Tag, Digest: desc.Digest.String(), MediaType: desc.MediaType, } - } else if err := ref.ValidateReferenceAsDigest(); err == nil { + } else if err := ref.ValidateReferenceAsDigest(); err == nil { meta = v1.ArtifactMetadata{ Repository: repo, Digest: desc.Digest.String(), MediaType: desc.MediaType, } - } else { + } else { ref := registry.Reference{Reference: reference} if err := ref.ValidateReferenceAsTag(); err == nil { meta = v1.ArtifactMetadata{ Repository: repo, Tag: reference, Digest: desc.Digest.String(), MediaType: desc.MediaType, } } else if err := ref.ValidateReferenceAsDigest(); err == nil { meta = v1.ArtifactMetadata{ Repository: repo, Digest: desc.Digest.String(), MediaType: desc.MediaType, } } else { return fmt.Errorf("invalid raw reference %q: %w", reference, err) } - } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bindings/go/oci/ctf/store.go` around lines 296 - 342, The code currently lets an unparseable reference fall through and write a zero-valued meta via idx.AddArtifact(meta); change the control flow around looseref.ParseReference(reference) so that if ParseReference returns an error you reject the reference immediately (return an error) instead of continuing; keep the existing tag/digest checks (ref.ValidateReferenceAsTag/ValidateReferenceAsDigest) for the parsed ref and the fallback registry.Reference branch, but if both parsing and any validation attempts fail return a descriptive error (wrap the original parse/validation error with fmt.Errorf) before reaching idx.AddArtifact(meta).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@bindings/go/oci/internal/validate/validate.go`:
- Around line 81-84: The current branch in validate.go returns the lookup ref
(ref) for legacy manifests when annotations.OCMComponentVersion is missing,
which lets ReferenceTagVersionResolver treat that lookup ref as a canonical
version and causes ListComponentVersions to surface aliases; change this
behavior so that when oldOCMComponentVersion is true and the manifestAnnotations
lookup for annotations.OCMComponentVersion fails, do NOT return ref as the
canonical version—either reject the aliasing by returning an explicit error (so
ReferenceTagVersionResolver/ReferenceTagVersionResolver callers cannot record a
spurious version) or return a distinct sentinel (e.g., empty version) that
upstream logic will not treat as a real version; modify the branch handling
manifestAnnotations[annotations.OCMComponentVersion] (the block that currently
returns ref, nil) to implement that rejection/neutral result and update any
callers (ReferenceTagVersionResolver, ListComponentVersions) to handle the new
error/sentinel accordingly.
---
Outside diff comments:
In `@bindings/go/oci/ctf/store.go`:
- Around line 296-342: The code currently lets an unparseable reference fall
through and write a zero-valued meta via idx.AddArtifact(meta); change the
control flow around looseref.ParseReference(reference) so that if ParseReference
returns an error you reject the reference immediately (return an error) instead
of continuing; keep the existing tag/digest checks
(ref.ValidateReferenceAsTag/ValidateReferenceAsDigest) for the parsed ref and
the fallback registry.Reference branch, but if both parsing and any validation
attempts fail return a descriptive error (wrap the original parse/validation
error with fmt.Errorf) before reaching idx.AddArtifact(meta).
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f2fb051a-2d15-4631-80a4-d94f089e2d4b
⛔ Files ignored due to path filters (2)
bindings/go/oci/go.sumis excluded by!**/*.sumbindings/go/oci/integration/go.sumis excluded by!**/*.sum
📒 Files selected for processing (9)
bindings/go/ctf/index/v1/index.gobindings/go/oci/ctf/store.gobindings/go/oci/ctf/store_test.gobindings/go/oci/interface.gobindings/go/oci/internal/lister/component/component_versions.gobindings/go/oci/internal/validate/validate.gobindings/go/oci/internal/validate/validate_test.gobindings/go/oci/repository.gobindings/go/oci/repository_test.go
✅ Files skipped from review due to trivial changes (1)
- bindings/go/oci/ctf/store_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
- bindings/go/ctf/index/v1/index.go
a3b687a to
b826585
Compare
Signed-off-by: Christoph Bleyer <christoph.bleyer@sap.com>
## Summary This PR extracts and upstreams the CTF index changes from the broader version aliasing feature open-component-model#2049. It's part of this feature request open-component-model/ocm-project#720. ### Changes - **CTF index (`bindings/go/ctf/index/v1`)**: Reworked `AddArtifact` to match OCI Image Layout semantics — multiple entries with the same digest but different tags can now coexist. Previously, adding a new tag to an existing digest would overwrite the old tag. - Exact duplicates (same repo + tag + digest) are skipped - Retagging (same tag, different digest) clears the old tag - Tagging an untagged entry updates it in place - Added comprehensive tests covering multi-tag, deduplication, cross-repo isolation, and encode/decode round-tripping ### Context This is the foundational change for **version aliasing** (see draft PR: open-component-model#2049, which allows multiple OCI tags to reference the same component version. The remaining OCI repository, CTF store, and validation changes will follow in a separate PR once this lands and a new version of the CTF module is released. Signed-off-by: Christoph Bleyer <christoph.bleyer@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
…component-model#2174) <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it open-component-model@e2b46f9 introduced a change in `ocm.software/open-component-model/bindings/go/ctf v0.4.0` that [breaks tests](https://github.com/open-component-model/open-component-model/actions/runs/24078003573/job/70231212198?pr=2152) in `bindings/go/oci/ctf`. A [fix](open-component-model#2049) is already in progress but it includes a bigger implementation that is not ready to merge yet. This is why, this PR reverts the version bump for that module for now. #### Which issue(s) this PR fixes Fixes open-component-model#2152 #### Testing Run `task test` and `task test/integration` --------- Signed-off-by: Frederic Wilhelm <frederic.wilhelm@sap.com> Co-authored-by: ocmbot[bot] <125909804+ocmbot[bot]@users.noreply.github.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
…dule dependencies) (no ctf) (open-component-model#2194) <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it open-component-model#2192 wants to bump. `bindings/go/ctf` again. However, this bump breaks other modules until the respective PR (open-component-model#2049) is merged. That is why this PR reverts the version bump for this module. We might need to do this until the other PR is merged. Fixes open-component-model#2192 --------- Signed-off-by: Frederic Wilhelm <frederic.wilhelm@sap.com> Co-authored-by: ocmbot[bot] <125909804+ocmbot[bot]@users.noreply.github.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
### Summary Adds the ability to create aliases (additional tags) for existing component versions, similar to OCI tag behavior (e.g., tagging the same image as both v1.0.0 and latest). Also see open-component-model/ocm-project#720. ### Changes CTF Module (bindings/go/ctf) - index/v1/index.go: Modified AddArtifact to allow multiple entries with the same digest but different tags (OCI Image Layout-like behavior) - index/v1/index_test.go: Added tests for multi-tag scenarios, cross-repository isolation, and encode/decode roundtrip persistence OCI Module (bindings/go/oci) - interface.go: New AliasComponentVersionRepository interface with AddComponentVersionAlias method - repository.go: Implementation of AddComponentVersionAlias that tags existing manifests/indexes with new aliases - repository_test.go: tests covering aliasing, tag chaining, alias movement, and version immutability - ctf/store.go: Removed dead code (addOrUpdateArtifactMetadataInIndex was operating on a clone) - ctf/store_test.go: Updated test expectations for multi-tag behavior Compatibility Considerations CTF Index Format - Old CTF read by new code: Fully compatible - New CTF read by old code: Read operations work correctly - New CTF written by old code: Old AddArtifact would overwrite tags on the same digest (potential data loss if mixing library versions writing to the same CTF) Key Design Decisions - Aliases are stored only in CTF's artifact-index.json / OCI registry tags - Manifest/index blobs are never modified - AnnotationVersion always contains the semantic version from the component descriptor - The aliasing feature only calls store.Tag(), ensuring content-addressable integrity Merge Order 1. Merge CTF first: The multi-tag support is self-contained and backwards compatible for reads. The OCI module requires this change, but CTF works independently. 2. Merge OCI second: Depends on the new CTF behavior for the aliasing feature to work correctly. Signed-off-by: Christoph Bleyer <christoph.bleyer@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
## Summary This PR extracts and upstreams the CTF index changes from the broader version aliasing feature open-component-model#2049. It's part of this feature request open-component-model/ocm-project#720. ### Changes - **CTF index (`bindings/go/ctf/index/v1`)**: Reworked `AddArtifact` to match OCI Image Layout semantics — multiple entries with the same digest but different tags can now coexist. Previously, adding a new tag to an existing digest would overwrite the old tag. - Exact duplicates (same repo + tag + digest) are skipped - Retagging (same tag, different digest) clears the old tag - Tagging an untagged entry updates it in place - Added comprehensive tests covering multi-tag, deduplication, cross-repo isolation, and encode/decode round-tripping ### Context This is the foundational change for **version aliasing** (see draft PR: open-component-model#2049, which allows multiple OCI tags to reference the same component version. The remaining OCI repository, CTF store, and validation changes will follow in a separate PR once this lands and a new version of the CTF module is released. Signed-off-by: Christoph Bleyer <christoph.bleyer@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
…component-model#2174) <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it open-component-model@e2b46f9 introduced a change in `ocm.software/open-component-model/bindings/go/ctf v0.4.0` that [breaks tests](https://github.com/open-component-model/open-component-model/actions/runs/24078003573/job/70231212198?pr=2152) in `bindings/go/oci/ctf`. A [fix](open-component-model#2049) is already in progress but it includes a bigger implementation that is not ready to merge yet. This is why, this PR reverts the version bump for that module for now. #### Which issue(s) this PR fixes Fixes open-component-model#2152 #### Testing Run `task test` and `task test/integration` --------- Signed-off-by: Frederic Wilhelm <frederic.wilhelm@sap.com> Co-authored-by: ocmbot[bot] <125909804+ocmbot[bot]@users.noreply.github.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
…dule dependencies) (no ctf) (open-component-model#2194) <!-- markdownlint-disable MD041 --> #### What this PR does / why we need it open-component-model#2192 wants to bump. `bindings/go/ctf` again. However, this bump breaks other modules until the respective PR (open-component-model#2049) is merged. That is why this PR reverts the version bump for this module. We might need to do this until the other PR is merged. Fixes open-component-model#2192 --------- Signed-off-by: Frederic Wilhelm <frederic.wilhelm@sap.com> Co-authored-by: ocmbot[bot] <125909804+ocmbot[bot]@users.noreply.github.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
### Summary Adds the ability to create aliases (additional tags) for existing component versions, similar to OCI tag behavior (e.g., tagging the same image as both v1.0.0 and latest). Also see open-component-model/ocm-project#720. ### Changes CTF Module (bindings/go/ctf) - index/v1/index.go: Modified AddArtifact to allow multiple entries with the same digest but different tags (OCI Image Layout-like behavior) - index/v1/index_test.go: Added tests for multi-tag scenarios, cross-repository isolation, and encode/decode roundtrip persistence OCI Module (bindings/go/oci) - interface.go: New AliasComponentVersionRepository interface with AddComponentVersionAlias method - repository.go: Implementation of AddComponentVersionAlias that tags existing manifests/indexes with new aliases - repository_test.go: tests covering aliasing, tag chaining, alias movement, and version immutability - ctf/store.go: Removed dead code (addOrUpdateArtifactMetadataInIndex was operating on a clone) - ctf/store_test.go: Updated test expectations for multi-tag behavior Compatibility Considerations CTF Index Format - Old CTF read by new code: Fully compatible - New CTF read by old code: Read operations work correctly - New CTF written by old code: Old AddArtifact would overwrite tags on the same digest (potential data loss if mixing library versions writing to the same CTF) Key Design Decisions - Aliases are stored only in CTF's artifact-index.json / OCI registry tags - Manifest/index blobs are never modified - AnnotationVersion always contains the semantic version from the component descriptor - The aliasing feature only calls store.Tag(), ensuring content-addressable integrity Merge Order 1. Merge CTF first: The multi-tag support is self-contained and backwards compatible for reads. The OCI module requires this change, but CTF works independently. 2. Merge OCI second: Depends on the new CTF behavior for the aliasing feature to work correctly. Signed-off-by: Christoph Bleyer <christoph.bleyer@sap.com> Signed-off-by: Gerald Morrison (SAP) <gerald.morrison@sap.com>
Summary
Adds the ability to create aliases (additional tags) for existing component versions, similar to OCI tag behavior (e.g., tagging the same image as both v1.0.0 and latest).
Also see open-component-model/ocm-project#720.
Changes
CTF Module (bindings/go/ctf)
OCI Module (bindings/go/oci)
Compatibility Considerations
CTF Index Format
Key Design Decisions
Merge Order