Release checklist¶
The release owner (a maintainer) goes through this list for every minor release. Patch releases skip the release candidate when they only contain fixes that were verified on their own. Tick the boxes in the release pull request.
Image tags¶
| Tag pushed | Images published | GitHub release |
|---|---|---|
vX.Y.Z |
X.Y.Z, X.Y, latest |
release, notes from the X.Y.Z section of CHANGELOG.md |
vX.Y.Z-rc1 (anything with a -) |
X.Y.Z-rc1, rc |
pre-release, notes from [Unreleased] plus changes/unreleased/ |
A pre-release never moves latest or X.Y. docker-compose.yml follows a minor version (slotserve:X.Y), so
existing installations only pick up final releases of their minor.
To check the tag rules without publishing anything, run the Release workflow by hand (Actions → Release →
Run workflow) with a tag such as v0.0.0-test: it prints and checks the image tags and the notes, and builds,
pushes and releases nothing.
1. Before the release candidate¶
- [ ] Every change of the release has a fragment in
changes/unreleased/or an entry under[Unreleased]inCHANGELOG.md;python tools/release_notes.py checkpasses andpreviewreads well. - [ ] Changed behaviour of existing installations is listed under Breaking changes, with what to do.
- [ ] CI is green on
main(lint, backend, frontend, end-to-end, docs, Docker image). - [ ] Database migrations of the release are tested against a copy of the previous release's data directory.
- [ ] The minor version in
docker-compose.ymland the docs is the one being released. - [ ] The docs are current:
mkdocs build --strictpasses,backend/tests/test_docs_anchors.pypasses, the operations runbooks cover every new setting an admin must know, and the upgrade section lists what people will notice. - [ ] Security review of what the release adds (see Security review below), signed off in the release pull request.
2. Release candidate¶
- [ ] Bump the version in
backend/pyproject.toml,backend/slotserve/__init__.pyandfrontend/package.jsontoX.Y.Z(the candidate is tagged on that commit). - [ ]
git tag vX.Y.Z-rc1 && git push origin vX.Y.Z-rc1; the workflow publishesX.Y.Z-rc1andrc. - [ ] Verification on real hardware with
python -m tools.verifyacross the verification matrix; every report (verify-report-<host>-<version>.md) is attached to the release pull request, with the manual checks filled in and every failure turned into an issue. - [ ] Upgrade, backup and restore rehearsed on a copy of real data.
- [ ] The candidate runs on at least one real installation for 3 days or more without new problems. Each fix
gets a new candidate (
-rc2, ...).
3. Release¶
- [ ]
python tools/release_notes.py release X.Y.Z(moves[Unreleased]and the fragments under## [X.Y.Z] - <today>and deletes the fragments); reviewCHANGELOG.md. - [ ] Commit (
Release X.Y.Z), thengit tag vX.Y.Z && git push origin main vX.Y.Z. - [ ] The workflow publishes
X.Y.Z,X.Yandlatestand creates the GitHub release; check the release page anddocker pull ghcr.io/peleryuan/slotserve:X.Y.
4. After the release¶
- [ ] The documentation site shows the new version's docs.
- [ ] Announce the release with its breaking changes: the GitHub release page (its notes come from the changelog) links the upgrade runbook; point the issue tracker's pinned discussion or the project's chat group at it.
- [ ] Open the next
[Unreleased]work; problems found after the release becomeX.Y.(Z+1)fixes.
Security review¶
Before the first release candidate, a maintainer who did not write the change goes through what the release adds and checks each item with a proof of concept against a running installation (most are also covered by tests; the point is to see them fail on a real browser and a real Docker host):
- [ ] New write endpoints are covered by the CSRF test generated from the routes; in a browser, the CSRF page
written by
tools/verifychanges nothing from another origin, from a direct port or from the web port. - [ ] Sign-in: a cookie signed with the old default key is refused; the first admin needs the setup code; throttling locks per account and address; changing a password signs out other sessions.
- [ ] Credentials: new kinds of keys are scoped and expire; no secret appears in logs, the audit log,
doctor --json,/api/healthevidence or a saved image (docker inspect,docker history). - [ ] Container fields: every new field of the container spec is in the golden spec tests and reviewed; no new
privilege, capability, host namespace, device or bind mount outside the allowed folders; hardening holds
(
no-new-privileges, dropped capabilities, process and memory limits). - [ ] Published ports: every port the release opens is in Ports and firewall, is
behind the SlotServe login or needs an explicit confirmation, and dev environment pages cannot act in
SlotServe or in another environment (the web origin checks of
tools/verify). - [ ] Root-equivalent settings (engine commands, mounted folders, images) ask for the password again and are announced to all admins.
Verification matrix¶
Run tools/verify (see Verify on real hardware) on enough installations to cover:
| Dimension | Cover |
|---|---|
| Machines | A Linux machine with an NVIDIA GPU; a machine without GPU |
| Deployment | Docker Compose with the published candidate image; without Docker |
| Dev environments | Every built-in template booked with a GPU, without GPU, kept and continued, saved as an image; a shared idle environment |
| Logins | SSH key, environment password, web interfaces through a reverse proxy with HTTPS |
| Storage | Host folder, NFS, SMB |
| Engines | llama.cpp; vLLM |
| Notifications | Telegram and one other chat platform; the inbox |
| Browsers | Chrome, Firefox, Safari |
| Failures | Out of memory in an environment, a fork bomb (--destructive), Docker restarted, host rebooted, disk nearly full: the health table and the alerts tell the truth, and SlotServe recovers |
Each report records the host, versions (SlotServe, driver, Docker) and the results; the manual browser checks are ticked in the report by the person who ran them.
Upgrade, backup and restore rehearsal¶
- [ ] A copy of a real data directory of the previous release starts on the candidate: snapshot taken, migration report clean, the health table as expected; then roll back to the snapshot with the previous image and upgrade again (Roll back).
- [ ] The daily bundle is copied to a backup target on another machine (a NAS path and a managed storage).
- [ ] A bundle is restored on another machine with
slotserve restore; the reconciliation report matches what really happened. - [ ] An admin who did not write the runbooks resets an admin password and restores from a backup using only Operations; every point where they got stuck is fixed in the docs.