Skip to content

Commit da97b6e

Browse files
committed
Add release runbook (docs/RELEASING.md) and link it from README
Document the full release process: version bump + changelog, the tag-push that triggers Docker images + the GitHub release, and the manual Raspberry Pi image build/upload + Firebase /download redirect deploy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GZ7bPhdN6H4wpYYqevcXFL
1 parent ec428e7 commit da97b6e

2 files changed

Lines changed: 140 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ Monthly operating cost: $0 (Signal + WhatsApp) to ~$6/mo (adding Twilio SMS).
168168
- **[docs/CLOUD-PROVISIONING.md](docs/CLOUD-PROVISIONING.md)** — Map provisioning architecture
169169
- **[docs/REMOTE-ACCESS.md](docs/REMOTE-ACCESS.md)** — Recommended Tailscale / Cloudflare deployment patterns
170170
- **[STATUS.md](STATUS.md)** — Implementation progress against the phased plan
171+
- **[CHANGELOG.md](CHANGELOG.md)** — Release history
172+
- **[docs/RELEASING.md](docs/RELEASING.md)** — Release runbook (version bump, tag, Pi image, website)
171173
- **[tests/README.md](tests/README.md)** — Test suite documentation
172174
- **[PLAN.md](PLAN.md)** — Product plan, security architecture, phased roadmap
173175
- **[SPEC.md](SPEC.md)** — Product specification

docs/RELEASING.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Releasing SafeCare
2+
3+
This is the end-to-end runbook for cutting a SafeCare release. There are three
4+
independent artifacts, and you can ship any subset:
5+
6+
1. **Docker images** (`ghcr.io/jasontitus/safecare-*`) + a **GitHub Release**
7+
used by PC/VPS deployments and the in-dashboard "System Updates" updater.
8+
Fully automated by `.github/workflows/release.yml` on a `v*` tag push.
9+
2. **Raspberry Pi SD-card image** (`safecare-vX.Y.Z.img.xz`) — the flashable
10+
appliance image linked from `safecare.app/download`. Built and uploaded
11+
manually.
12+
3. **Website** (`safecare.app`) — Firebase Hosting; the `/download` redirect
13+
points at the current Pi image in GCS.
14+
15+
Versions `0.4.1``0.4.6` were Pi-image-only releases (artifact 2) and did not
16+
bump the in-app version constant.
17+
18+
---
19+
20+
## 0. Prerequisites
21+
22+
- Clean `main`, all checks green: `pnpm typecheck && pnpm lint && pnpm test && pnpm build`.
23+
- For the Pi image: Docker running, ~10 GB free disk, 30–60 min.
24+
- For the upload/website: `gcloud` authenticated to the `safecare-maps`
25+
project and `firebase` CLI authenticated.
26+
27+
---
28+
29+
## 1. Bump the version + changelog (every release that ships code)
30+
31+
The source of truth for in-app update checks is `SAFECARE_VERSION`.
32+
33+
1. Edit `packages/shared/src/constants.ts`:
34+
```ts
35+
export const SAFECARE_VERSION = 'X.Y.Z';
36+
```
37+
2. Add a section to `CHANGELOG.md` (newest first) describing the changes, and
38+
add the matching link reference at the bottom of the file.
39+
3. Commit to `main`:
40+
```bash
41+
pnpm --filter @safecare/shared build # recompile the constant
42+
git add packages/shared/src/constants.ts CHANGELOG.md
43+
git commit -m "Release vX.Y.Z: bump version + changelog"
44+
git push origin main
45+
```
46+
47+
### Semver guidance
48+
49+
- **Patch** (`0.4.x`): bug fixes, reliability, Pi-image-only fixes.
50+
- **Minor** (`0.x.0`): new features, backwards-compatible.
51+
- **Major**: breaking changes to the data model, API, or deployment.
52+
53+
---
54+
55+
## 2. Docker images + GitHub Release (tag push)
56+
57+
Pushing a `v*` tag triggers `.github/workflows/release.yml`, which builds the
58+
backend/dashboard/pwa images for `linux/arm64,linux/amd64`, pushes them to GHCR
59+
tagged with the version and `latest`, and creates a GitHub Release with
60+
auto-generated notes.
61+
62+
```bash
63+
git tag -a vX.Y.Z <commit> -m "SafeCare vX.Y.Z" # <commit> = the main commit to release
64+
git push origin vX.Y.Z
65+
```
66+
67+
Verify: **Actions** tab shows the release workflow green, and
68+
`ghcr.io/jasontitus/safecare-backend:X.Y.Z` exists. Deployed dashboards will now
69+
report the update under **Settings > System Updates** (the checker compares
70+
`SAFECARE_VERSION` against the latest GitHub Release).
71+
72+
> Note: some managed/CI git proxies block tag pushes (HTTP 403) even when branch
73+
> pushes succeed. If so, push the tag from a normal clone/workstation.
74+
75+
---
76+
77+
## 3. Raspberry Pi image (optional per release)
78+
79+
Build the flashable appliance image with pi-gen in Docker:
80+
81+
```bash
82+
./scripts/rpi/build/build-image.sh safecare # or: rideshare | full
83+
# output: scripts/rpi/build/output/safecare-<date>.img.xz
84+
```
85+
86+
Rename to the release convention (`safecare-vX.Y.Z.img.xz`) so the public
87+
download URL is versioned:
88+
89+
```bash
90+
mv scripts/rpi/build/output/safecare-<date>.img.xz \
91+
scripts/rpi/build/output/safecare-vX.Y.Z.img.xz
92+
```
93+
94+
(Optional) flash + smoke-test before publishing: `./scripts/rpi/build/test-image.sh`.
95+
96+
---
97+
98+
## 4. Upload the image + publish the website redirect
99+
100+
`upload-image.sh` uploads to the `safecare-maps-osrm` GCS bucket, makes the
101+
object public, and rewrites the `/download` redirect in
102+
`infra/prebuilt/hosting/firebase.json` to point at the new image:
103+
104+
```bash
105+
./scripts/rpi/build/upload-image.sh scripts/rpi/build/output/safecare-vX.Y.Z.img.xz
106+
```
107+
108+
Then deploy the hosting change so `safecare.app/download` serves the new image:
109+
110+
```bash
111+
cd infra/prebuilt/hosting && firebase deploy --only hosting
112+
```
113+
114+
Commit the `firebase.json` change so the repo reflects the live redirect:
115+
116+
```bash
117+
git add infra/prebuilt/hosting/firebase.json
118+
git commit -m "Point /download redirect at safecare-vX.Y.Z.img.xz"
119+
git push origin main
120+
```
121+
122+
> Do not update the `/download` redirect to a `vX.Y.Z` image before the image is
123+
> actually uploaded — it would 404 the public download link. `upload-image.sh`
124+
> updates the redirect only after a successful upload.
125+
126+
---
127+
128+
## Release checklist
129+
130+
- [ ] `main` green (`typecheck`, `lint`, `test`, `build`)
131+
- [ ] `SAFECARE_VERSION` bumped
132+
- [ ] `CHANGELOG.md` entry + link reference added
133+
- [ ] version/changelog committed and pushed to `main`
134+
- [ ] `vX.Y.Z` tag pushed → release workflow green, GHCR images published
135+
- [ ] (if shipping Pi image) image built, renamed `safecare-vX.Y.Z.img.xz`
136+
- [ ] (if shipping Pi image) `upload-image.sh` run, `firebase deploy` done
137+
- [ ] (if shipping Pi image) `firebase.json` redirect committed to `main`
138+
- [ ] `safecare.app/download` serves the new image

0 commit comments

Comments
 (0)