3.9 KiB
v0.1.9 Release Automation Retrospective
Date: 2026-06-22
Branch: develop
Production release: v0.1.9
Result
v0.1.9 is the first verified end-to-end automatic production release for 小虾 SaaS:
- Gitea tag push starts production release workflow.
- Dedicated
runtime-builder-01builds API/Worker runtime images. - Dedicated builder builds Web
apps/web/distin a Node Docker container. - Dedicated builder uploads both artifacts to production.
- Dedicated builder drives production deployment over SSH.
- Production host only extracts artifacts, loads runtime images, runs migrations, restarts containers, and health checks.
- Public Web/API smoke tests pass.
Verified Production State
After v0.1.9:
xiaoxia-api-productionrunsxiaoxia-saas-api:v0.1.9and is healthy.xiaoxia-worker-productionrunsxiaoxia-saas-worker:v0.1.9.xiaoxia-web-productionis healthy and serves prebuilt Web dist./var/lib/xiaoxia-saas-production/runtime-images-v0.1.9.taris present, about 325 MB./var/lib/xiaoxia-saas-production/release-v0.1.9.tar.gzis present, about 883 KB.
Public smoke results:
python scripts\smoke_public_auth_flow.py
public_auth_flow=ok
python scripts\smoke_public_upload_flow.py
public_upload_flow=ok
public project detail smoke
public_project_get=ok
What Repeated
The repeated tags were not feature releases; they were release-chain verification tags.
v0.1.6: runtime-builder checkout/token fix worked, but Gitea skipped downstream production deploy after cross-runnerneeds.v0.1.7: production deploy moved toruntime-builderover SSH; build/upload succeeded, but deploy failed becausedeploy-production.shdefaulted to/hostpaths while SSH uses host paths directly.v0.1.8: SSH deploy usedHOST_PREFIX=, but release artifact packaging used broad--exclude=dist, which removedapps/web/distand correctly failed the Web artifact gate.v0.1.9: artifact packaging changed to--exclude=./dist, preservingapps/web/dist; automatic release succeeded.
Usable rollback tags:
v0.1.5: previously verified stable production release.v0.1.9: current verified automatic production release.
Do not use v0.1.6, v0.1.7, or v0.1.8 as rollback targets unless intentionally reproducing release-chain failures.
Root Causes Fixed
-
GITHUB_TOKENwas not implicitly available in act_runner shell scripts.- Fix: checkout steps explicitly bind
GITHUB_TOKEN: ${{ github.token }}.
- Fix: checkout steps explicitly bind
-
Gitea
needswith production deploy on a different runner path skipped the downstream deploy job.- Fix: production deploy also runs on
runtime-builder, then SSHes to production.
- Fix: production deploy also runs on
-
Production deploy script defaults to
/hostfor Docker-in-Docker CI execution.- Fix: SSH deploy passes
HOST_PREFIX=so the script uses normal host paths.
- Fix: SSH deploy passes
-
Release source artifact accidentally included build output tarballs.
- Fix: exclude root
./distfrom release tar.
- Fix: exclude root
-
A broad
--exclude=distalso excluded Web dist.- Fix: use
--exclude=./dist, not--exclude=dist.
- Fix: use
Current Release Contract
For production v* tag releases:
- Production host must not build API or Worker images.
- Production host must not build frontend assets.
runtime-builder-01is the build and deployment driver.runtime-images-<tag>.tarmust exist before production deploy.release-<tag>.tar.gzmust includeapps/web/dist/index.html.- Production deploy must fail if either artifact is missing.
- Production smoke is required before saying release is done.
Follow-Ups
- Add an explicit dry-run workflow or staging release rehearsal to reduce tag-based trial and error.
- Keep
v0.1.6tov0.1.8documented as failed release-chain probes. - Consider adding an API version endpoint that reports the Docker image tag; current
/healthversion text can lag image tags. - Review temporary credential posture for builder SSH key and old registration tokens.