What anodizer builds
Artifacts the `anodizer release` pipeline produces: binaries, archives, packages, installers, containers, and signing material.
What anodizer builds
Output formats and the builds[] / archives[] / dockers_v2[] / signs[]
keys that drive them. Native binaries for 6 targets ship on every release
(linux amd64/arm64, darwin amd64/arm64, windows amd64/arm64), built with
cargo + cargo-zigbuild + cross.
Live configuration
Build / archive / nfpm / dockers_v2 / sign blocks from
cfgd/.anodizer.yaml
(snapshot 2026-05-24) — every key referenced in the tables below is wired
here.
defaults:
targets:
- x86_64-unknown-linux-gnu
- aarch64-unknown-linux-gnu
- x86_64-apple-darwin
- aarch64-apple-darwin
- x86_64-pc-windows-msvc
cross: auto
# Per-crate (one workspace shown):
builds:
- binary: cfgd
mod_timestamp: "{{ CommitTimestamp }}"
archives:
- name_template: "{{ ProjectName }}-{{ Version }}-{{ Os }}-{{ Arch }}"
formats: [tar.gz]
format_overrides:
- { os: windows, formats: [zip] }
files: [LICENSE, README.md]
universal_binaries:
- { name_template: "{{ ProjectName }}", replace: false }
checksum:
name_template: "{{ ArtifactName }}.sha256"
algorithm: sha256
split: true
# Top-level:
upx:
- id: default
enabled: true
args: ["--best", "--lzma"]
targets: [x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu,
x86_64-apple-darwin, x86_64-pc-windows-msvc]
nfpms:
- id: cfgd
formats: [deb, rpm, apk]
maintainer: "TJ Smith <tj@jarvispro.io>"
contents:
- { src: LICENSE, dst: /usr/share/doc/cfgd/LICENSE }
- { src: README.md, dst: /usr/share/doc/cfgd/README.md }
# dockers_v2: pushes a multi-arch image index in one step (no separate manifest).
dockers_v2:
- id: cfgd
dockerfile: Dockerfile.agent.release
images: ["ghcr.io/tj-smith47/cfgd"]
tags: ["{{ Version }}", "v{{ Version }}", "latest"]
sbom: true
signs:
- { id: cosign-checksum, artifacts: checksum, cmd: cosign }
- { id: cosign-source, artifacts: source, cmd: cosign }
docker_signs:
- { id: cosign-images, artifacts: manifests, cmd: cosign }
binary_signs:
- { id: cosign-bin, artifacts: binary, cmd: cosign }
sboms:
- { id: default, cmd: syft, artifacts: archive, documents: ["{{ .ProjectName }}-{{ .Version }}.cdx.json"] }
Build
Archives and checksums
| Key | Status | Notes |
checksum.algorithm | ✅ Verified | Lockstep. sha256 default → the combined anodizer_0.23.0_checksums.txt. Full list: sha1/224/256/384/512, sha3-*, blake2s/2b, blake3, crc32, md5 |
checksum.split | ✅ Verified | Per-crate. cfgd .anodizer.yaml (checksum.split: true on the cfgd workspace) — cfgd v0.6.1 ships a .sha256 sidecar next to every asset instead of one combined file. anodizer runs the combined mode |
Linux packages
macOS and Windows installers (built on Linux CI)
These formats are assembled on an ordinary Linux runner — no macOS or
Windows host in the build matrix. Anodizer's own dogfood config wires all five
(anodizer .anodizer.yaml,
app_bundles: / dmgs: / pkgs: / msis: / nsis: blocks), built unsigned
in CI. Code-signing and notarization still require the platform's own
credentials; the bundles themselves do not. As of
v0.23.0 all of
them — including the Linux-desktop .AppImage and .flatpak bundles — ship
as live release assets (amd64 + arm64).
| Key | Status | Notes |
notarize.macos | 🤝 Help wanted | Cross-platform (rcodesign). Implementation requires sign.certificate (P12 file), sign.password, and notarize.{issuer_id, key, key_id}, i.e. an Apple Developer Program membership. Not dogfoodable on Linux runners without a paid Apple account |
notarize.macos_native | 🤝 Help wanted | Needs Apple Developer cert on a macOS runner |
Container images
| Key | Status | Notes |
dockers_v2[] | ✅ Verified | ghcr.io/tj-smith47/anodizer carries 34 semver tags plus latest, each a linux/amd64 + linux/arm64 index pushed in one buildx invocation; cfgd's three images (cfgd, cfgd-operator, cfgd-csi) cover the per-crate shape |
dockers_v2[].images → multi-registry push | ✅ Verified | anodizer .anodizer.yaml lists two registries under one entry (ghcr.io/tj-smith47/anodizer plus a private registry.jarvispro.io/anodizer mirror), so a single buildx run pushes every tag to both. Only the GHCR half is publicly checkable |
docker_manifests[] | 🤝 Help wanted | No dogfood config declares one: dockers_v2 already pushes a multi-arch index, so a separate manifest step has nothing to stitch (# No docker_manifests needed marks all three sites in cfgd .anodizer.yaml). The key exists for the case of stitching images that were not built by dockers_v2 in the same run, which none of our projects has |
dockers_v2[].build_args / labels / annotations | ✅ Verified | cfgd .anodizer.yaml (build_args.VERSION + org.opencontainers.image.* annotations) |
dockers_v2[].sbom: true | ✅ Verified | cfgd .anodizer.yaml (sbom: true on all three dockers_v2 images) |
docker_digest.name_template | ✅ Verified | cfgd .anodizer.yaml (docker_digest.name_template: "cfgd_{{ .Tag }}.digest") |
dockers_v2[].use: buildx | ✅ Verified | crates/stage-docker/src/detect.rs (buildx is the default backend) |
dockers_v2[].use: podman / docker_manifests[].use: docker / podman | 🤝 Help wanted | Linux-only backend selectors. No live release exercises the non-buildx path |
docker_hub.description | ✅ Verified | Live at hub.docker.com/r/tsmthtj/anodizer — the dockerhub: publisher syncs description + full_description (from README.md) each release; at v0.15.5 (run 28882554907) it read the remote repo and logged skipped dockerhub PATCH … description / full_description match remote (summary: dockerhub … succeeded) |
Signing
| Key | Status | Notes |
signs[] (cosign, keyless) | ✅ Verified | Single-crate and per-crate. brontes signs its source tarball keyless — Fulcio OIDC, no key secret: brontes-0.3.0-source.tar.gz.sig via brontes .anodizer.yaml (signs[].if: "{{ not IsSnapshot }}"); cfgd the same, per checksum sidecar: cfgd v0.3.5 cosign bundle |
binary_signs[] / docker_signs[] (cosign, keyful) | ✅ Verified | Lockstep. anodizer signs with a stored key, not keyless: --key=env://COSIGN_KEY in anodizer .anodizer.yaml, with COSIGN_KEY / COSIGN_PASSWORD supplied by release.yml and nightly.yml. The image half is publicly checkable: ghcr.io/tj-smith47/anodizer carries 37 cosign .sig tags alongside its image tags |
signs[] (gpg) | ✅ Verified | anodizer_0.23.0_checksums.txt.sig |
signs[].artifacts | ✅ Verified | cfgd .anodizer.yaml (signs: declares artifacts: checksum and artifacts: source slots). The artifacts: source selector is proven live by brontes: brontes-0.3.0-source.tar.gz.sig |
docker_signs[].artifacts: manifests | ✅ Verified | Both shapes wire it: anodizer .anodizer.yaml (lockstep, one image) and cfgd .anodizer.yaml (per-crate, three). The signatures are the .sig tags sitting beside each image tag on ghcr.io/tj-smith47/anodizer |
| Cosign TUF warm-up lock + warm-cache fast path | ✅ Verified (tests) | crates/stage-sign/src/tuf_cache.rs — keyless cosign's first run initializes its sigstore TUF trust root under a host-level advisory flock so parallel cold starts don't race; a warm cache (go-tuf or sigstore-go layout) skips the serialized first sign entirely. Validated locally by racing 8 parallel keyless sign-blob invocations on a warm cache; awaits a live multi-shard release for public proof |
sboms[] | ✅ Verified | CycloneDX via syft. anodizer-0.23.0.cdx.json. sboms[].artifacts: source (SBOM over the source tarball instead of build outputs) is proven live by brontes: brontes-0.3.0.cdx.json |
${artifact} / ${document} substitution | ✅ Verified | crates/stage-sbom/src/stage.rs ($artifact, $artifactID, $document, $document<N> substitution into the SBOM tool's argv) |