Support for alias in registries.conf by jonesbusy · Pull Request #540 · oras-project/oras-java

@jonesbusy

Description

Support for alias in registries.conf

Testing done

Implemented tests.

Will check coverage on this PR

Submitter checklist

  • I have read and understood the CONTRIBUTING guide
  • I have run mvn license:update-file-header, mvn spotless:apply, pre-commit run -a, mvn clean install before opening the PR

@jonesbusy

Signed-off-by: Valentin Delaye <jonesbusy@users.noreply.github.com>

@codecov

Codecov Report

❌ Patch coverage is 82.60870% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.34%. Comparing base (b774e08) to head (01eb53f).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/main/java/land/oras/ContainerRef.java 73.33% 1 Missing and 3 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #540      +/-   ##
============================================
+ Coverage     87.62%   88.34%   +0.72%     
- Complexity      707      713       +6     
============================================
  Files            42       42              
  Lines          2117     2137      +20     
  Branches        242      245       +3     
============================================
+ Hits           1855     1888      +33     
+ Misses          166      150      -16     
- Partials         96       99       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for [aliases] in registries.conf so unqualified container references can be resolved via configured alias mappings.

Changes:

  • Extend RegistriesConf to parse and expose an aliases map from TOML.
  • Update ContainerRef to consult configured aliases when resolving unqualified references.
  • Add unit/integration tests covering alias parsing and alias-based pulls.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/main/java/land/oras/auth/RegistriesConf.java Adds [aliases] model + accessors and loads aliases from TOML.
src/main/java/land/oras/ContainerRef.java Introduces alias key calculation and alias-aware resolution paths.
src/test/java/land/oras/auth/RegistriesConfTest.java Adds test coverage for reading aliases from registries.conf.
src/test/java/land/oras/ContainerRefTest.java Adds test coverage for resolving an unqualified ref via alias config.
src/test/java/land/oras/GitHubContainerRegistryITCase.java Adds an IT that pulls using an alias-based unqualified ref.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 393 to 402

public String getEffectiveRegistry(Registry target) {
if (isUnqualified()) {
String key = getAliasKey();
if (target.getRegistry() == null && target.getRegistriesConf().hasAlias(key)) {
return target.getRegistriesConf().getAliases().get(key);
}
return target.getRegistry() != null
? target.getRegistry()
: determineFirstUnqualifiedSearchRegistry(target);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getEffectiveRegistry now returns the alias target value (e.g., ghcr.io/org/repo) when an alias exists. That breaks the method’s contract/javadoc of returning a registry (host) and can also lead to callers treating a repo path as a host. Consider keeping getEffectiveRegistry returning only the resolved registry host (possibly extracted from the alias target), and/or introducing a separate API that resolves an alias into a full ContainerRef.

Copilot uses AI. Check for mistakes.

Comment on lines +424 to +426

String newRefString = "%s:%s".formatted(newLocation, tag);
LOG.info("Using {} as an alias to {}", key, newRefString);
return ContainerRef.parse(newRefString);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alias resolution in forRegistry(Registry) builds a new reference string with "%s:%s".formatted(newLocation, tag) and then reparses it. This drops any existing digest on the original ref and can also produce malformed refs if the alias target already contains a tag or digest. It would be safer to parse the alias target as a base ref and then carry over the original tag/digest (or construct the new ContainerRef directly) so aliasing works for digest-pinned references too.

String newRefString = "%s:%s".formatted(newLocation, tag);
LOG.info("Using {} as an alias to {}", key, newRefString);
return ContainerRef.parse(newRefString);
// Parse the alias target as a base reference and carry over tag/digest from this reference
ContainerRef baseRef = ContainerRef.parse(newLocation);
String effectiveTag = this.tag != null ? this.tag : baseRef.tag;
String effectiveDigest = this.digest != null ? this.digest : baseRef.digest;
LOG.info(
"Using {} as an alias to {} (tag={}, digest={})",
key,
newLocation,
effectiveTag,
effectiveDigest);
return new ContainerRef(
baseRef.registry,
baseRef.isUnqualified(),
baseRef.namespace,
baseRef.repository,
effectiveTag,
effectiveDigest);

Copilot uses AI. Check for mistakes.

public ContainerRef forRegistry(Registry registry) {
if (isUnqualified() && registry.getRegistry() == null) {
String key = getAliasKey();
if (registry.getRegistry() == null && registry.getRegistriesConf().hasAlias(key)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inner condition if (registry.getRegistry() == null && ...) is redundant because the outer if (isUnqualified() && registry.getRegistry() == null) already guarantees registry.getRegistry() == null. Removing the duplicate check would simplify the control flow slightly.

if (registry.getRegistry() == null && registry.getRegistriesConf().hasAlias(key)) {
if (registry.getRegistriesConf().hasAlias(key)) {

Copilot uses AI. Check for mistakes.