Operations
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 pkg/brew/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 pkg/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 pkg/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), 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 plaindotfilesinpkg/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 + the same-commit local reusable-workflow references.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.