Skip to content

fix(image-link): parse image refs explicitly and add GHCR/Quay support#191

Open
coding-shalabh wants to merge 1 commit into
microsoft:mainfrom
coding-shalabh:fix/private-registry-image-links
Open

fix(image-link): parse image refs explicitly and add GHCR/Quay support#191
coding-shalabh wants to merge 1 commit into
microsoft:mainfrom
coding-shalabh:fix/private-registry-image-links

Conversation

@coding-shalabh
Copy link
Copy Markdown

Fixes #179.

What the issue was

The previous implementation matched image references with three positional regexes:

const dockerHubImageRegex            = /^(?<imageName>[.\w-]+)(?<tag>:[.\w-]+)?$/i;
const dockerHubNamespacedImageRegex  = /^(?<namespace>[a-z0-9]+)\/(?<imageName>[.\w-]+)(?<tag>:[.\w-]+)?$/i;
const mcrImageRegex                  = /^mcr.microsoft.com\/(?<namespace>([a-z0-9]+\/)+)(?<imageName>[.\w-]+)(?<tag>:[.\w-]+)?$/i;

These worked for Docker Hub / namespaced / MCR cases but for any other registry — ghcr.io, quay.io, localhost:5000, nrt.vultrcr.com/... — they all silently fell through to "no link." The user filing the issue saw what looked like a wrong link because they expected some clickable hint and got none. The underlying gap is real even though the symptom they described isn't exactly what happens.

What this PR does

1. Refactors the regex jungle into an explicit image-reference parser. A new parseImageRef() helper follows the rules documented at github.com/distribution/reference: a path component before the first / is treated as a registry hostname if it contains ., contains :, or is exactly localhost. Otherwise the reference is resolved against Docker Hub.

2. Preserves every existing link target. All 119 prior tests pass unchanged — Docker Hub official (alpine), namespaced (library/alpine), MCR (mcr.microsoft.com/dotnet/sdk), the "other hosts" negative case, multi-namespaced negative case, build-section negative case, etc.

3. Adds support for two more public registries. Both are common enough in compose.yaml files that linking to their UI is high-value:

Reference New link target
ghcr.io/<owner>/<repo>[:tag] https://github.com/<owner>/<repo>/pkgs/container/<repo>
quay.io/<owner>/<repo>[:tag] https://quay.io/repository/<owner>/<repo>

Tags are stripped from the link target (matching the existing behavior for Docker Hub).

4. Adds three new test cases:

  • Should provide links for GitHub Container Registry images — covers ghcr.io/microsoft/playwright-mcp and a tagged form.
  • Should provide links for Quay.io images — covers quay.io/prometheus/node-exporter and a tagged form.
  • Should NOT provide links for unrecognized private registries — includes the exact image from Hover link on image: field in compose.yaml always points to Docker Hub, even for private registries #179 (nrt.vultrcr.com/wulicoco/code-sync) plus localhost:5000/myimg and registry.gitlab.com/group/project/image. Locks in the negative behavior so it can't regress.

Total test count: 122 passing (was 119).

Things I deliberately did not change

  • Link range computation. The clickable link still covers everything before the optional :tag suffix, matching the existing Docker Hub / MCR behavior.
  • Telemetry shape. The imageTypes set still records what was matched; dockerHub, dockerHubNamespaced, mcr keep their existing values and ghcr / quay are added.
  • No new dependencies.
  • GitLab / AWS ECR / GCR. I considered adding these but the URL mapping is non-trivial (GitLab projects can be nested arbitrarily; AWS ECR URLs need an account ID; GCR is being deprecated in favor of Artifact Registry). Happy to follow up in a separate PR if you'd like.

Verification

  • npm run lint — clean
  • npm run build — clean (esm + cjs)
  • npm test — 122 passing, 1 pending (no changes to pending list)

Comment thread src/service/providers/ImageLinkProvider.ts
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the image link provider to replace three positional regexes with an explicit parseImageRef() helper that follows Docker's reference resolution rules (a first path component is a registry hostname iff it contains ., :, or equals localhost). This fixes #179, where references like nrt.vultrcr.com/wulicoco/code-sync previously fell through silently, and adds explicit link targets for GHCR and Quay.io.

Changes:

  • New parseImageRef() parser plus buildLinkUri() dispatcher; existing Docker Hub / MCR link targets and ranges are preserved.
  • Adds GHCR (ghcr.io/<owner>/<repo> → GitHub package page) and Quay (quay.io/<owner>/<repo> → quay.io repository page) link generation, plus ghcr/quay telemetry values.
  • Adds three test cases covering GHCR, Quay, and the negative case for unrecognized private registries (including the exact reference from #179).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/service/providers/ImageLinkProvider.ts Replaces three regex branches with explicit reference parsing and adds GHCR/Quay link builders.
src/test/providers/ImageLinkProvider.test.ts Adds positive tests for GHCR and Quay and a negative test locking in #179 behavior.

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

Refactor the regex-based matcher in ImageLinkProvider into an explicit
Docker image-reference parser that follows the registry-resolution rules
documented in github.com/distribution/reference: a path component before
the first '/' is treated as a registry hostname when it contains '.',
contains ':', or is exactly 'localhost'.

The previous matchers worked correctly for the public Docker Hub /
namespaced / MCR cases but silently produced no link for any image on
another registry, even well-known public ones. With the new parser:

- Docker Hub official, namespaced, and MCR cases keep their existing
  link targets and ranges (all 119 prior tests pass unchanged).
- ghcr.io/<owner>/<repo>[:tag] now links to the package page on
  github.com (.../pkgs/container/<repo>).
- quay.io/<owner>/<repo>[:tag] now links to its repository page.
- Unrecognized private registries (e.g. nrt.vultrcr.com/...,
  localhost:5000/..., registry.gitlab.com/...) explicitly return no
  link rather than relying on the namespace-regex incidentally
  rejecting them.

Adds three new test cases covering GHCR, Quay, and the unrecognized
private-registry scenario from issue microsoft#179.

Fixes microsoft#179
@coding-shalabh coding-shalabh force-pushed the fix/private-registry-image-links branch from dcd1deb to 0b7d6d5 Compare May 28, 2026 20:12
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.

Hover link on image: field in compose.yaml always points to Docker Hub, even for private registries

3 participants