Fan out: formats and architectures

Goal: one submission builds every format the tree claims, for every architecture you ship, and docker pull serves the whole matrix from one address.

Formats: build once, package many

Packaging formats are additive: a tree with a Dockerfile and a Makefile claims both. A formats selector turns one submission into one group of jobs under one group id:

$ saggar submit ./my-project --formats auto      # every claimant
$ saggar submit ./my-project --formats deb,docker

auto runs one exclusive build-system job plus all packaging formats; the list pins the set. When the group has one build-system job (single arch), it runs first. Where the whole group builds on one machine, the packaging jobs package a snapshot of its built tree: build once, package many. Builds on paired runners share no disk, so each packaging job builds its own tree there; --no-reuse-build disables the snapshot where it would apply.

Architectures: one job per combination

--arches composes the arch fan-out on top:

$ saggar submit ./my-project --formats auto --arches amd64,riscv64

One job per combination: formats × arches. (--arch names a single target instead and conflicts with --arches.)

Multi-arch docker: one pull address

For the docker format, --arches builds each foreign arch with --platform (RUN steps under emulation need binfmt/qemu on the runner; FROM scratch + COPY trees need none). Once every arch is green, the group’s images are bound into one OCI image index, published as the group’s own artifact (arch: all, version = the group id):

$ docker pull saggar.dev/val/my-project:staging

That single address serves the index; the client picks the manifest matching its own platform. The group id is a second address for the same index, and each arch’s job id still pulls that one arch directly.

A failed arch degrades loudly. There is no index; the other arches’ tags keep working.

Downloading the whole matrix

$ saggar download --group g-1a2b3c4d -o out/

Every job of the group; a member with no artifact (build-check success) is reported and skipped.