> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stacyos.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Releasing

# Releasing StacyVM

StacyVM releases publish two deliverables:

* Static Linux binaries for `stacyvm` and `stacyvm-agent` under the GitHub release.
* A multi-arch container image at `ghcr.io/stacyos/stacyvm`.

Release binaries, `checksums.txt`, and the published container image digest are
signed with Sigstore keyless signing from the GitHub Actions release workflow.

## Release Workflow

The release workflow lives at `.github/workflows/release.yml`.

It runs automatically for tags that match `v*`:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
git tag <version>
git push origin <version>
```

It can also be started manually from GitHub Actions with:

* `version`: release version or image tag, for example `v0.14.4`.
* `publish_image`: whether to publish the GHCR image.
* `create_release`: whether to create a GitHub release with binary artifacts.

Tag-triggered releases always build binaries, create the GitHub release, and publish the container image.

## Binary Artifacts

Local release artifacts can be built with:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
make release-build-all VERSION=<version>
```

The command writes artifacts to `dist/`:

* `stacyvm-linux-amd64`
* `stacyvm-agent-linux-amd64`
* `stacyvm-linux-arm64`
* `stacyvm-agent-linux-arm64`
* `checksums.txt`

The release workflow also attaches:

* `<artifact>.sig`
* `<artifact>.pem`

for every binary and `checksums.txt`.

## Verifying A Release

Install `cosign`, then run:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
scripts/verify-release.sh <version> amd64
scripts/verify-release.sh <version> arm64
```

The verifier checks:

* Sigstore certificate identity for the StacyVM release workflow.
* Sigstore certificate issuer from GitHub Actions OIDC.
* Binary and agent SHA-256 entries in `checksums.txt`.

Manual verification for one artifact:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
cosign verify-blob stacyvm-linux-amd64 \
  --signature stacyvm-linux-amd64.sig \
  --certificate stacyvm-linux-amd64.pem \
  --certificate-identity-regexp 'https://github.com/StacyOS/stacyvm/.github/workflows/release.yml@refs/tags/v.*' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com'
```

## Container Image

The release workflow publishes:

* `ghcr.io/stacyos/stacyvm:<version>`
* `ghcr.io/stacyos/stacyvm:latest` for `v*` tag releases

The image digest is signed after publishing:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
cosign verify ghcr.io/stacyos/stacyvm@sha256:<digest> \
  --certificate-identity-regexp 'https://github.com/StacyOS/stacyvm/.github/workflows/release.yml@refs/tags/v.*' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com'
```

The Dockerfile accepts a `VERSION` build argument and uses BuildKit target platform args so the release workflow can publish `linux/amd64` and `linux/arm64` images from one workflow.

To test the image locally before publishing:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
docker build --build-arg VERSION=dev -t stacyvm:dev .
docker run --rm stacyvm:dev version
```

## Preflight Checklist

Before tagging:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
make test
make build
cd web && npm run build
scripts/check-swagger.sh
stacyvm config lint --production --file deploy/stacyvm.production.yaml
make release-build-all VERSION=<version>
```

When linting the production template, provide real `STACYVM_AUTH_API_KEY` and `STACYVM_AUTH_ADMIN_API_KEY` values through the environment so placeholder secrets do not pass the release gate.

Also confirm the production deployment templates still render:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
docker compose --env-file deploy/.env.example -f deploy/docker-compose.yml config
```

After the release workflow publishes artifacts, verify both architectures:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
scripts/verify-release.sh <version> amd64
scripts/verify-release.sh <version> arm64
```

Or run the full post-release gate:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
scripts/post-release-validate.sh <version>
STACYVM_VALIDATE_INSTALLER=true scripts/post-release-validate.sh <version>
```

The full gate confirms that every binary, checksum, signature, and certificate
asset exists on the GitHub release, runs signature and checksum verification for
both architectures, and can exercise `scripts/install.sh` in verify-only mode on
Linux.

For a GitHub-hosted Linux evidence bundle, run the manual **Public Readiness
Certification** workflow against the published tag. It validates the release,
runs installer verify-only, certifies the selected runtime on the runner, and
uploads the generated Markdown reports. Treat this as CI-host evidence only;
production-host runtime claims still require `scripts/certify-runtime.sh` on
the actual host.

## Notes

* Do not store release secrets in `stacyvm.production.yaml`; pass them through environment variables.
* Keep release notes in `docs/releases/` up to date before creating a GitHub release.
* Do not publish public self-serve releases without Sigstore signatures and checksums.
* Platform conformance for Docker, gVisor/Kata, Firecracker, and PRoot remains host-gated and should be reported separately from generic build health.
