Skip to content

Conversation

@BYK
Copy link
Member

@BYK BYK commented Dec 10, 2025

Summary

Extend the Docker target to support publishing to multiple container registries (Docker Hub, GHCR, GCR, etc.) with per-registry credentials, including cross-registry publishing from private sources.

Key Changes

Multi-Registry Support

  • Auto-detect registry from image paths (e.g., ghcr.io/user/imageghcr.io)
  • Per-registry credentials via DOCKER_<REGISTRY>_USERNAME/PASSWORD env vars
  • Built-in GHCR defaults using GITHUB_ACTOR/GITHUB_TOKEN for zero-config in GitHub Actions
  • Registry override to share credentials across regional registries
  • Treat docker.io, index.docker.io, registry-1.docker.io as Docker Hub aliases

Cross-Registry Publishing

  • Source registry authentication for pulling from private registries
  • Login to both source and target registries when credentials are available
  • If no source credentials found, assumes source is public

New Nested Object Config Format

Both source and target now support string or object format:

# String shorthand
source: ghcr.io/org/image
target: getsentry/craft

# Object format with options
source:
  image: ghcr.io/org/image
  registry: ghcr.io
  format: "{{{source}}}:sha-{{{revision}}}"
  usernameVar: MY_SOURCE_USER
  passwordVar: MY_SOURCE_PASS
target:
  image: us.gcr.io/project/image
  registry: gcr.io  # Share creds across regions

Security Improvements

  • Secure password handling using --password-stdin

Example Configurations

Cross-registry publishing:

targets:
  - name: docker
    source:
      image: ghcr.io/myorg/private-image
      usernameVar: GHCR_USER
      passwordVar: GHCR_PASS
    target: getsentry/craft

Multi-registry publishing:

targets:
  # Docker Hub
  - name: docker
    source: ghcr.io/getsentry/craft
    target: getsentry/craft

  # GHCR (zero-config in GitHub Actions)
  - name: docker
    source: ghcr.io/getsentry/craft
    target: ghcr.io/getsentry/craft

  # GCR with shared regional credentials  
  - name: docker
    source: ghcr.io/getsentry/craft
    target:
      image: us.gcr.io/project/image
      registry: gcr.io

Closes #591

Extend the Docker target to support publishing to multiple container registries
(Docker Hub, GHCR, GCR, etc.) with per-registry credentials.

Key changes:
- Auto-detect registry from target image path (e.g., ghcr.io/user/image)
- Per-registry credentials via DOCKER_<REGISTRY>_USERNAME/PASSWORD env vars
- Built-in GHCR defaults using GITHUB_ACTOR/GITHUB_TOKEN for zero-config in
  GitHub Actions
- Optional registry config override to share credentials across regions
- Optional usernameVar/passwordVar for explicit env var names (no fallback)
- Use --password-stdin for secure password handling

Closes #591
BYK added 3 commits December 11, 2025 11:11
Recognize docker.io, index.docker.io, and registry-1.docker.io as Docker Hub
aliases that should use default DOCKER_USERNAME/PASSWORD credentials instead of
looking for DOCKER_DOCKER_IO_* env vars.
…ublishing

When source and target registries differ, credentials can now be resolved
independently for each registry. This enables cross-registry publishing
(e.g., pulling from private GHCR and pushing to Docker Hub).

- Source credentials use registry-specific env vars (no default fallback)
- Add sourceRegistry, sourceUsernameVar, sourcePasswordVar config options
- Login to both registries when source credentials are available
- If source credentials are not found, assume source is public
@BYK BYK force-pushed the byk/feat/docker-multi-registry branch 3 times, most recently from fe9004d to 56969b7 Compare December 12, 2025 00:01
@BYK BYK marked this pull request as ready for review December 12, 2025 00:02
@BYK BYK requested review from aldy505 and hubertdeng123 and removed request for aldy505 December 12, 2025 00:02
@BYK BYK force-pushed the byk/feat/docker-multi-registry branch from 56969b7 to 0b62470 Compare December 12, 2025 10:10
Comment on lines +140 to +223
// Object form - prefer object properties over legacy, but allow legacy as fallback
return {
image: ref.image,
format: ref.format ?? legacyFormat,
registry: ref.registry ?? legacyRegistry,
usernameVar: ref.usernameVar ?? legacyUsernameVar,
passwordVar: ref.passwordVar ?? legacyPasswordVar,
skipLogin: ref.skipLogin ?? legacySkipLogin,
};
}

This comment was marked as outdated.

Allow source and target to be specified as either a string (image path) or
an object with additional options (image, registry, format, usernameVar,
passwordVar). This provides a cleaner API that groups related configuration.

- Add ImageRefConfig and ImageRef types
- Add normalizeImageRef() for backwards compatibility with legacy flat config
- Update getDockerConfig() to use normalized config
- Support both new nested format and legacy flat format
- Add comprehensive tests for new format (12 new tests)
- Update README with new configuration documentation
@BYK BYK force-pushed the byk/feat/docker-multi-registry branch from 0b62470 to 0faa5a4 Compare December 12, 2025 10:28
@BYK BYK requested review from aldy505 and hubertdeng123 December 12, 2025 10:36
Throws a clear ConfigurationError if source or target is missing from
the Docker target configuration, instead of crashing with an unhelpful
TypeError: Cannot read property 'image' of undefined.
Copy link
Member

@hubertdeng123 hubertdeng123 left a comment

Choose a reason for hiding this comment

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

one more comment, hope this doesn't break anything 🤞

…t-ins

- Use node:fs, node:os, node:path instead of fs, os, path
- Use specific named imports (existsSync, homedir, join) instead of namespace imports
@BYK BYK enabled auto-merge (squash) December 12, 2025 19:27
Comment on lines +27 to +32
const GCR_REGISTRY_PATTERNS = [
/^gcr\.io$/,
/^[a-z]+-gcr\.io$/, // us-gcr.io, eu-gcr.io, asia-gcr.io, etc.
/^[a-z]+\.gcr\.io$/, // us.gcr.io, eu.gcr.io, asia.gcr.io, etc.
/^[a-z]+-docker\.pkg\.dev$/, // us-docker.pkg.dev, europe-docker.pkg.dev, etc.
];
Copy link

Choose a reason for hiding this comment

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

Bug: The regex for Google Artifact Registry hostnames is too strict and doesn't account for numbers in region names, causing authentication failures for valid regional endpoints.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

The regular expression used to identify Google Cloud Registry (GCR) hosts is incorrect. The pattern /^[a-z]+-docker\.pkg\.dev$/ in isGoogleCloudRegistry only matches lowercase letters for the region, but valid Google Artifact Registry regions can contain numbers (e.g., us-west1). As a result, when a user specifies a valid regional endpoint like us-west1-docker.pkg.dev, the function returns false. This causes the application to incorrectly demand explicit DOCKER_..._USERNAME/PASSWORD credentials instead of using the available gcloud authentication, breaking the expected zero-configuration workflow.

💡 Suggested Fix

Update the regular expression on line 32 of src/targets/docker.ts to allow for numeric digits in the region part of the hostname. Change /^[a-z]+-docker\.pkg\.dev$/ to /^[a-z0-9-]+-docker\.pkg\.dev$/ to correctly match regional endpoints like us-west1-docker.pkg.dev.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/targets/docker.ts#L27-L32

Potential issue: The regular expression used to identify Google Cloud Registry (GCR)
hosts is incorrect. The pattern `/^[a-z]+-docker\.pkg\.dev$/` in `isGoogleCloudRegistry`
only matches lowercase letters for the region, but valid Google Artifact Registry
regions can contain numbers (e.g., `us-west1`). As a result, when a user specifies a
valid regional endpoint like `us-west1-docker.pkg.dev`, the function returns `false`.
This causes the application to incorrectly demand explicit
`DOCKER_..._USERNAME`/`PASSWORD` credentials instead of using the available `gcloud`
authentication, breaking the expected zero-configuration workflow.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 7465936

@BYK BYK merged commit f60aba9 into master Dec 12, 2025
14 checks passed
@BYK BYK deleted the byk/feat/docker-multi-registry branch December 12, 2025 19:30
@aldy505
Copy link

aldy505 commented Dec 15, 2025

@BYK do you have any plans to cut a release for this one?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support multiple docker registries

4 participants