NBPR.Artifact.Resolvers.GHCR (NBPR v0.2.1)

Copy Markdown View Source

Resolver for {:ghcr, "ghcr.io/<owner>"} site specs.

Each nbpr package maps to one OCI image at ghcr.io/<owner>/<package_name>. Build variants (package version, system, system-version, build-opts) become tags. Anonymous pull works for packages flipped to public visibility — the resolver does not authenticate.

Wire flow per fetch:

  1. GET /token?service=ghcr.io&scope=repository:<image>:pull → anonymous JWT
  2. GET /v2/<image>/manifests/<tag> (Bearer + Accept manifest media type) → manifest JSON
  3. Pick the first layer whose mediaType matches application/vnd.nbpr.tarball.v1+tar+gzip
  4. GET /v2/<image>/blobs/<digest> (Bearer, autoredirect) → bytes streamed to disk

Summary

Functions

Checks anonymously whether <image>:<tag> already has a manifest published.

Functions

tag_exists?(image, tag)

@spec tag_exists?(String.t(), String.t()) :: {:ok, boolean()} | {:error, term()}

Checks anonymously whether <image>:<tag> already has a manifest published.

Returns {:ok, true} for HTTP 200, {:ok, false} for HTTP 404, and {:error, reason} for other failures (auth, network, malformed JSON). Uses the same anonymous-pull token flow as get/2, so packages need public visibility on GHCR for this to work without credentials.

Used by mix nbpr.publish to short-circuit when the artefact's tag is already published — NBPR's cache-key model treats published tarballs as immutable, so re-pushing the same key is wasted work.