Skip to content

feat(image): support multi-binary Go release units - #69

Merged
jmgilman merged 5 commits into
mainfrom
feat/multi-binary-images
Aug 26, 2026
Merged

feat(image): support multi-binary Go release units#69
jmgilman merged 5 commits into
mainfrom
feat/multi-binary-images

Conversation

@jmgilman

Copy link
Copy Markdown
Contributor

Summary

The Go release unit previously supported exactly one application binary: release-cli stage failed on a duplicate linux/<arch> Binary record, the OCI leg staged one file as sources/<arch>/application, and the verifier hardcoded one entrypoint and one layer entry. This blocked multi-binary consumers (first case: componere/incus-spire-attestor, a SPIRE plugin pair shipping incus-agent + incus-server in one carrier image).

This PR generalizes the unit to a named binary set per platform:

  • goprof.SelectBinaries selects every linux/{amd64,arm64} Binary record, rejects duplicate (arch, name) pairs, and requires identical nonempty name sets across both architectures.
  • Projection schema bumps to release.dev/oci-build-inputs/v2: per name, exactly one amd64 and one arm64 entry.
  • image build (release.dev/image-build/v2) stages each binary as work/sources/<apkarch>/<binary-name> (the application sentinel is gone); canonical-binaries.sha256 lists every staged file; BuildResult.Binaries replaces Binary.
  • image verify (release.dev/image-verify/v2) derives the expected name set from work/sources (same-set validation), hashes ALL usr/bin/<name> entries in one streaming pass per platform layer (each exactly once, regular, 0755, uid/gid 0, size-bounded), and requires the config Entrypoint to be [/usr/bin/<name>] for some staged name. The --binary flag and RELEASE_BINARY extraction are removed.
  • Repo self-release melange.yaml installs staged release-cli by name; docs (adopt guide, reference, tutorial, example) document the by-name contract, the entrypoint rule, and the application<binary-name> migration.

Migration for existing adopters

At re-pin, change the melange pipeline from application to the GoReleaser binary name (e.g. incusos-builder: install ... incusos-builder). Single-binary projects are otherwise unchanged (N=1).

Validation

moon run root:check passes (format, lint, mocks, build, full test suite). New table tests cover N=1 and N=2 selection, duplicate (arch,name), asymmetric name sets, entrypoint not in set, missing/duplicate layer entries, and checksum ordering.

Melange copies work/sources/<apkarch>/<binary-name> rather than a
shared application file.
image verify loads expected names from the v2 projection, so the
builder no longer shuttles .result.binary through RELEASE_BINARY.
Consumers install each staged file by its GoReleaser name. The previous
shared application filename is a migration from the prior unit.
Select every linux/{amd64,arm64} Binary, stage each under its real name,
and verify all usr/bin entries in one layer pass. Single-binary consumers
are N=1 under the v2 schemas.
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