Releasing: CI, the release and publish workflows
Part of the developer notes; the index is in CLAUDE.md.
Releasing
- CI (
.github/workflows/ci.yml, every PR and push todev/main): app build and type check,cargo clippy -D warnings,cargo testfor core andoppx, ruff (syntax and undefined names) for the gateway, frontend and scripts, the connector tests (scripts/test_connectors.py), the agent tests with the document packages, the gateway’s input check (scripts/test_inputs.py), the regex check (scripts/check_regexes.py: every pattern compiled and proven free of catastrophic backtracking, with its own tests inscripts/test_check_regexes.py), shell syntax, and the PR title check for PRs intomain. The GPU lifecycle test stays manual. - Release (
.github/workflows/release.yml, a merged PR intomainwith a release prefix, or run by hand with a bump and a changelog line):scripts/bump_version.pybumps every version file and adds theCHANGELOG.mdentry. The workflow commits “Release vX.Y.Z” tomain, tags it, fast-forwardsdevwhen possible, then starts Publish for the tag. - Publish (
.github/workflows/publish.yml,workflow_dispatchwith a tag; redo a release withgh workflow run publish.yml --ref main -f tag=vX.Y.Z). It always runs onmain(thegithub-pagesenvironment only deploys frommain) and checks out the tag for everything it builds:oppxforx86_64/aarch64-unknown-linux-musl(static) andaarch64/x86_64-apple-darwin, withOPPX_RELEASE_TARGETset;oppxsfor the two Linux musl targets; the app as.deb(withoppxsand its unit inside:beforeBundleCommandbuilds it,bundle.linux.deb.filesplaces it) and AppImage (nooppxs: an AppImage is one file).- A GitHub release with the archives,
SHA256SUMS,install.sh,install-server.sh, and notes frommain’sCHANGELOG.md. - The docs (
scripts/gen_docs.py+ mdBook) on GitHub Pages.
- No backend image is published. The app carries the build files (
docker::BUILD_FILES: the Dockerfile,gateway.py,inputs.py,reqtrace.py,searchguard.py,start-sglang.sh,supervisord.conf, embedded withinclude_str!) and buildsopenphalanx-backend:<version>-<hash of those files>on the first start (docker::ensure_image): Docker pulls the official SGLang image, pinned by digest in the Dockerfile, and adds ~45 MB on top. A changed gateway or Dockerfile gets a new tag and is rebuilt, so neither users nor developers run a stale image; older tags of ours are removed after a build. Cluster members build the same way when a split worker starts. A customimagesetting is pulled instead. - Why two workflows: a tag pushed with
GITHUB_TOKENstarts no workflow, but a dispatch does. Apull_requestrun can’t deploy Pages, because its ref is the PR’s merge ref, notmain. - One-time repository settings: Actions → workflow permissions “Read and write”; Pages → source “GitHub Actions”.
mainis protected by a ruleset (PR and status checks required), andGITHUB_TOKENcan’t be put on a ruleset’s bypass list, so the release commit is pushed with a write deploy key: its private half is theRELEASE_DEPLOY_KEYsecret (ssh-keyon the checkout inrelease.yml), and “Deploy keys” is a bypass actor on the ruleset. Without it the push is refused with GH013 (v0.6.0’s first run: the admin’s bypass covers the merge, not the workflow’s push). The commit and tag are pushed with--atomic, so a refusal leaves no tag. - Dependency updates (Renovate,
renovate.json): the Mend Renovate app opens update PRs intodev(nevermain, where each PR would need a release prefix and cut a release), titled[chore] …, once a release has been public for 7 days (minimumReleaseAge, withinternalChecksFilter: strictso no PR appears before that). Minor and patch updates come grouped in one PR, majors one each, and the lock files are refreshed on Monday mornings; nothing auto-merges. The SGLang base image digest gets its own PR (labelledneeds-gpu-test: it changes every backend tag, so run the lifecycle example before merging), as do the pinnedrecheck/typescriptof the regex check. The CI runtimes are deliberately at the bottom of the supported range and Renovate leaves them alone: Python 3.12 (the private Aider engine), Node.js 20, andubuntu-22.04for the.deb/AppImage builds. The Dependency Dashboard issue lists what is pending or held back. Check a change to the file withnpx --package renovate renovate-config-validator --strict renovate.json. - Lint the workflows locally with
docker run --rm -v "$PWD:/repo" -w /repo rhysd/actionlint:latest.