Release Pipeline¶
End-to-end flow from git tag v0.2.503 && git push --tags to a fully
signed, distributed release on GitHub + Homebrew + Scoop + AUR.
Release workflows are triggered by either release.created or
release.published. Packaging starts at creation; distribution and the
single security chain start at publication and run in parallel where
dependencies allow.
git push --tags (you)
│
▼
┌────────────────────────────┐
│ GitHub creates Release │ (auto, from tag)
└─┬──────────────────────────┘
├── on: release.created
│ └── release-package-dot.yml
│ → dot-VERSION.tar.gz + .zip
│
└── on: release.published
│
├──────────────────────────────────┐
▼ ▼
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ release-distribute-*.yml │ │ security-release.yml │
│ ┌─────────────────────┐ │ │ → SBOM + provenance │
│ │ homebrew → tap PR │ │ │ → ALL_SHA256SUMS │
│ │ scoop → bucket PR│ │ │ → cosign sig + cert │
│ │ aur → AUR push │ │ │ → verify full bundle │
│ └─────────────────────┘ │ └─────────────────────────────┘
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ release-attestation-check │ (Mondays + on demand)
│ → opens issue if missing │
└─────────────────────────────┘
Workflows¶
| Workflow | Trigger | Owns | Outputs |
|---|---|---|---|
release-package-dot.yml |
release.created, dispatch |
Build deterministic dot-VERSION.{tar.gz,zip} from bin/, lib/, share/, completions. |
Two release assets. |
security-release.yml (sbom job) |
release.published, dispatch |
Generate SPDX SBOM via anchore/sbom-action. Cosign keyless sign the SBOM. | dotfiles-sbom.spdx.json + .sig + .pem. |
security-release.yml (provenance job) |
needs sbom | SLSA L3 provenance via slsa-framework/slsa-github-generator. | dotfiles-sbom.spdx.json.intoto.jsonl. |
security-release.yml (manifest job) |
needs provenance + complete asset set | Build ALL_SHA256SUMS over every release asset, Cosign-sign it, and verify its signature and digests. |
ALL_SHA256SUMS + .sig + .pem. |
release-distribute-homebrew.yml |
release.published, dispatch |
Hash dot-VERSION.tar.gz, regenerate install/homebrew/dot.rb, push branch + PR to sebastienrousseau/homebrew-tap. |
One PR on the tap repo. |
release-distribute-scoop.yml |
release.published, dispatch |
Hash dot-VERSION.zip, rewrite install/scoop/dot.json via jq (both 64bit + arm64 point at same zip), PR to sebastienrousseau/scoop-bucket. |
One PR on the bucket repo. |
release-distribute-aur.yml |
release.published, dispatch |
Hash dot-VERSION.tar.gz, rewrite pkgver + sha256sums in install/aur/PKGBUILD, regenerate .SRCINFO via dockerised makepkg, push to ssh://[email protected]/dot-cli-git.git. |
One commit on AUR. |
release-attestation-check.yml |
weekly cron + dispatch | Verify the latest release carries the full attestation bundle (SBOM + sig + cert + intoto + manifest + sig + cert). | Opens or comments on a tracking issue. |
Event ownership and readiness¶
GitHub fires release.created the moment a Release record exists.
That starts the packaging step, which depends only on source bytes at
the tag and does not need other assets to be present.
release.published fires later, when a human flips the Release from
draft to public (or when a Release is created already-public, the
events fire together). Distribution and the security chain start from
this event. Publication does not mean independently triggered asset
publishers have finished, so the manifest job waits for all 13 required
package, documentation, SBOM, signature, and provenance assets before
it downloads or signs the bundle. The final integrity job then verifies
the manifest's Cosign identity and every recorded digest.
Both release and dispatch paths of security-release.yml are
idempotent: re-running the manifest job after late asset uploads picks
up the new state and the --clobber flag overwrites the previous
manifest sig + cert.
Secrets used¶
| Secret | Used by | Setup |
|---|---|---|
GITHUB_TOKEN |
every workflow (auto) | n/a |
ACTIONS_BOT_SIGNING_KEY |
distribute-* (signed commits on tap repos), bump-reusable-pins.yml, update-deps.yml |
See docs/security/AUTOMATION_SECRETS.md. |
AUR_SSH_KEY |
release-distribute-aur.yml only |
SSH ED25519 keypair; public key on the srousseau AUR profile, private key in this secret. See memory/reference_aur_account.md for the AUR Edit-Account form quirk that bit us during setup. |
Distribution targets¶
| Target | Repo | First-run prereq |
|---|---|---|
| Homebrew | sebastienrousseau/homebrew-tap |
Tap repo exists (currently bare README + LICENSE). Workflow creates the Formula/dot.rb path on first publish. |
| Scoop | sebastienrousseau/scoop-bucket |
Bucket repo exists (currently bare). Workflow creates bucket/dot.json on first publish. |
| AUR | ssh://[email protected]/dot-cli-git.git |
Manual one-time step: the maintainer must create the package entry via the AUR web UI before the workflow's git clone can succeed. The workflow exits with a clear error message on the first run if the repo doesn't exist. |
Verifying a release¶
See docs/security/VERIFY_RELEASE.md for the consumer-facing
verification recipe. The pipeline produces four orthogonal
attestations (SBOM, Cosign signature on SBOM, SLSA provenance,
unified Cosign-signed manifest) and a verifier can check any of them
independently.
Known caveats¶
- AUR
pkgname=dot-cli-git: AUR's-gitconvention means "tracks git HEAD", but the workflow publishes tagged stable releases. Either rename to plaindotfilesininstall/aur/PKGBUILDand register that package, or accept the misnomer. Documented in the v0.2.503 PR (#895). - Signed-Releases retroactive: the unified manifest landed in v0.2.503. Releases v0.2.500-502 carry the SBOM bundle only. We do not re-tag older releases (would break consumer pins). The OSSF Scorecard score climbs naturally as new releases land.
- First-tag rehearsal: tag a
v0.2.503-rc1once before the real v0.2.503 to live-test the full pipeline without burning the final release tag. The workflows are idempotent so a real v0.2.503 still works after the rc.
See also¶
docs/security/VERIFY_RELEASE.md— consumer-facing verification.docs/security/CI_PINNING.md— reusable workflow pin policy + thebump-reusable-pins.ymlauto-bump bot.docs/security/AUTOMATION_SECRETS.md— how each automation secret is generated, scoped, and rotated.docs/operations/ROADMAP_V0_2_503.md— the 7-workstream plan this pipeline executed.