# Release Process

## Prepare

Make sure the `main` branch is clean, all CI checks pass and there are no
pending pull requests that should be included.

## Create the release

Run `make release` from the repository root:

```
make release
```

This will, in order:

1. Read the current version from `meson.build` and propose the next patch
   version (you can type a different version when prompted).
2. Update the version string in `meson.build`.
3. Create a signed commit `grout: release vX.Y.Z` with contributor statistics
   generated by `devtools/git-stats`.
4. Create a GPG-signed annotated tag `vX.Y.Z` with the same statistics.
5. Generate a detached GPG signature of the source tarball
   (`grout-X.Y.Z.tar.gz.asc`) by piping `git archive` output through `gpg
   --detach-sign --armor`.
6. Push the commit and tag to GitHub.
7. Create a draft GitHub Release with the `.asc` signature attached.

## CI pipeline

Once the tag is pushed, the `publish.yml` workflow triggers automatically and
will:

- Run the full CI check matrix (multiple compilers, architectures, DPDK/FRR
  versions).
- Build `.rpm` and `.deb` packages for x86_64 and aarch64.
- Build and push multi-arch container images to `quay.io/grout/grout` tagged
  with the version number (e.g. `0.16.3` and `0.16`).
- Upload the built packages to the draft release.
- Add auto-generated release notes and publish the release (remove draft).

## Source tarball verification

GitHub does not sign its source archive downloads. To establish a trust chain
from the maintainer's GPG key to the downloaded tarball, `make release`
generates a detached signature over the `git archive` output and uploads it to
the GitHub Release as `grout-X.Y.Z.tar.gz.asc`.

GitHub's archive tarballs are bit-for-bit reproducible from `git archive`, so
the signature can be verified against the downloaded tarball directly:

```
gpg --verify grout-X.Y.Z.tar.gz.asc grout-X.Y.Z.tar.gz
```
