CI & Release

Everything released is built by Nix. There is no docker build anywhere in the repo’s release path, so nothing floats: CI and your machine produce byte-identical images from the same lockfile.

flowchart LR
    push["push / PR"] --> chk["flake-check workflow<br/>nix flake check --all-systems --no-build<br/>+ image closure dry-run"]
    tag["push tag v*"] --> rel["release-images workflow (ubuntu)"]
    rel --> build["nix build .#image-<svc>"]
    build --> pushghcr["docker load + tag + push<br/>ghcr.io/shsingh/opensase-&lt;svc&gt;<br/>:latest + :version"]
    pushghcr --> sbom["SPDX SBOM per image (anchore)"]

Workflows

Workflow Trigger What it does
.github/workflows/flake-check.yml PRs, pushes to master nix flake check --all-systems --no-build + --dry-run builds of all image closures
.github/workflows/release-images.yml tags v*, manual matrix-builds the four images on Linux runners, publishes to GHCR, SBOMs each

Images

Built with pkgs.dockerTools.buildLayeredImage — see nix/images.nix. Linux-only outputs (the services are linux-first); darwin systems skip image outputs.

nix run .#load-images     # build all four locally + docker load (linux host)

Publishing a release

Releases are GPG-signed tags — the workflow verifies the tag (git tag -v) and fails before publishing anything unsigned:

git tag -s v0.1.0 -m "OpenSASE v0.1.0: initial Nix-built container release"
git push origin v0.1.0

The workflow matrix-builds the four images, pushes to GHCR (:latest + the version), and opens a draft release whose notes are generated on the runner:

  • digest table for all four images
  • commit changelog since the previous tag
  • SPDX SBOMs attached as release assets
  • 60-second compose deploy snippet

Review and publish the draft to ship. Consumers need nothing but an OCI runtime.

Docs site

.github/workflows/pages.yml renders this site with Quarto and deploys it to GitHub Pages on pushes to master touching _quarto.yml, docs/**, index.qmd, or the README.