# Release Process

`safe-bundle` releases are tag driven.

## Preflight

1. Confirm the working tree is clean.
2. Update `CHANGELOG.md`.
3. Run the local gate:

   ```sh
   cargo fmt -- --check
   cargo test --locked
   cargo clippy --all-targets --locked -- -D warnings
   powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\ci-smoke.ps1
   powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\dependency-policy.ps1
   cargo +1.85.0 check --locked
   cargo package --locked
   ```

4. Confirm GitHub Actions is green on `main`.
5. Confirm repository rules allow maintainers or release automation to create
   `refs/tags/v*` tags. If tag creation is restricted, the tag push will fail
   before the release workflow can run.

## Tag

Use an annotated version tag:

```sh
git tag -a v1.1.0 -m "safe-bundle v1.1.0"
git push origin v1.1.0
```

The `Release` workflow verifies the tag, creates a draft GitHub Release, builds
cross-platform binaries, uploads checksums, and publishes the draft when all
jobs pass.

## Artifacts

The release workflow uploads:

- `safe-bundle-v<version>-x86_64-unknown-linux-gnu.tar.gz`
- `safe-bundle-v<version>-x86_64-apple-darwin.tar.gz`
- `safe-bundle-v<version>-aarch64-apple-darwin.tar.gz`
- `safe-bundle-v<version>-x86_64-pc-windows-msvc.zip`
- `.sha256` sidecar files for every archive.
- The packaged crate archive from `cargo package`.

Each binary archive is extracted and smoke-tested in the release workflow before
it is uploaded.

## Integrity and Provenance

Every uploaded archive must have a SHA-256 sidecar file. The release workflow
extracts and smoke-tests each packaged binary before upload.

The release workflow also generates GitHub artifact attestations for the crate
archive and binary archives. Verify them with:

```sh
gh attestation verify <artifact> -R wildmason/safe-bundle
```

Or verify all assets for a tag from a checkout:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\verify-release.ps1 -Tag v1.1.0
```

For checksum-only verification of an already downloaded asset directory:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\verify-release.ps1 `
  -AssetDir .\target\release-check\v1.1.0 `
  -SkipAttestations
```

Detached GPG or cosign signatures are not required unless downstream packaging
or distribution channels need them.

## Crates.io

Crates.io publication is a manual maintainer step after the GitHub Release
workflow succeeds:

```sh
git checkout v1.1.0
cargo publish --dry-run --locked
cargo publish --locked
```

Publish from the release tag so the crate contents match the GitHub Release
crate archive. Do not publish if the GitHub Release workflow failed. The
crates.io token must have permission to publish updates for the existing
`safe-bundle` crate.

## Package Managers

After the GitHub Release has been verified, generate package-manager recipe
drafts from the release sidecars:

```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\generate-packaging-recipes.ps1 -Tag v1.1.0
```

Review the generated Homebrew formula and Scoop manifest before copying them
into the downstream tap or bucket repositories. See
[package manager recipes](PACKAGING.md) for the full workflow.

Current downstream repositories:

- Homebrew tap: `https://github.com/wildmason/homebrew-tap`
- Scoop bucket: `https://github.com/wildmason/scoop-bucket`
