Skip to content

publish.yml: explicit tags, native multi-arch builds, masked identity secrets - #4

Merged
DeviaVir merged 1 commit into
Blockstream:mainfrom
DeviaVir:publish-tags-and-platforms
Oct 30, 2026
Merged

DeviaVir merged 1 commit into
Blockstream:mainfrom
DeviaVir:publish-tags-and-platforms

Conversation

@DeviaVir

Copy link
Copy Markdown
Contributor

Summary

These changes to publish.yml let public repositories publish versioned, multi-arch, signed images. Callers that do not use the new inputs see no change: the same <sha>-<timestamp> tag (with prod- for production), one build on ubuntu-24.04, and the same outputs.

New inputs

  • tags and moving-tags: publish exactly these tags instead of the derived tag.
    • A tag is immutable unless it is listed in moving-tags.
    • An existing tag that points to another digest fails the run before anything is pushed. An identical tag is skipped.
    • Only an explicit "manifest unknown" or "not found" answer counts as absent; any other registry error fails.
  • platforms: linux/amd64 and/or linux/arm64.
    • Each platform builds in its own matrix job on a native runner (ubuntu-24.04, ubuntu-24.04-arm).
    • publish unpacks every archive with the existing digest checks, and checks that its os/arch matches the platform.
    • It merges the archives into one OCI index, pushes it, and signs the index digest once.
  • build-args: literal KEY=VALUE build arguments, passed as single argv elements.
  • Identity from secrets: workload-identity-provider, service-account and image may now come from secrets with the same names. Public repositories' logs are public, and secrets are masked.
  • image-name: appended to the image (for example a secret prefix) for repositories that publish several images.

Restrictions

  • A caller that passes publisher secrets cannot also use build-secrets or build-arg-secrets. Otherwise the existing toJSON(secrets) hand-off would expose the publisher secrets to build steps.
  • When image comes from a secret, GitHub drops the image output because it contains a masked value. Use digest instead.

Security model unchanged

  • build has no OIDC token and no registry credentials.
  • publish runs no caller code.
  • A new prepare job (no permissions, no checkout) validates the inputs and builds the matrix.
  • All actions stay pinned by SHA.

Validation

  • actionlint (the same command as lint.yml): clean. zizmor --min-severity medium: no findings.
  • All embedded scripts pass bash -n and py_compile, and 43 edge-case executions passed.
  • Local registry test with real amd64 and arm64 buildx archives:
    • The index lists both platforms, and image-name composes the path correctly.
    • A re-run with the same tags makes no writes.
    • An immutable tag with new content fails before latest moves, and a moving latest updates.
    • A legacy single-image push gives the original digest.
  • Not verified yet: real GitHub artifact passing, native arm64 runner scheduling, OIDC, cosign and secret masking. These need a live caller run after release.

… secrets

- tags / moving-tags: publish exactly these tags instead of the derived
  <sha>-<timestamp> tag. Tags are immutable unless listed in moving-tags;
  an existing tag with a different digest fails before any push.
- platforms: build linux/amd64 and linux/arm64 on native runners, one
  matrix job each, merge the archives into one OCI index and sign it once.
- build-args: literal KEY=VALUE build arguments.
- workload-identity-provider / service-account / image may come from
  secrets, so public repositories do not print them in workflow logs.
  image-name appends a plain name to a secret image prefix.

Without the new inputs the workflow behaves exactly as before.
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.

1 participant