hsa-app/deploy/CICD.md

78 lines
3.7 KiB
Markdown
Raw Permalink Normal View History

# CI/CD — what git actions trigger what
The pipeline is a single Forgejo Actions workflow,
[.forgejo/workflows/build.yml](../.forgejo/workflows/build.yml), triggered on every
push (`on: [push]`, which covers both branch and tag pushes). This document explains
which git action produces which outcome. For one-time host setup, the on-disk
layout, and manual deploy/rollback, see [INSTALL.md](INSTALL.md).
## Trigger behavior at a glance
| You push… | Build + test | Stage binary to host | Activate (go live) |
|---|:---:|:---:|:---:|
| any branch (no tag) | ✅ | — | — |
| a **release** tag `X.Y.Z` (e.g. `1.4.0`) | ✅ | ✅ | ✅ |
| a **pre-release** tag (anything else, e.g. `0.0.0a3`) | ✅ | ✅ | — |
- **Branch push** → builds and runs the full test suite, uploads the `hsa` binary as
a run artifact. Nothing touches the server. This is your PR / pre-merge gate.
- **Release tag** `X.Y.Z` → builds, tests, copies the binary to the host, and makes
it live (symlink swap + service restart).
- **Pre-release tag** → builds, tests, and copies the binary to the host, but does
**not** activate it. Use this to park a build on the server (QA, manual
activation) without flipping production.
The release-vs-pre-release decision is purely the tag name: the **Activate** step
runs only when the tag matches the regex `^[0-9]+\.[0-9]+\.[0-9]+$`. Note this means
a `v`-prefixed tag (`v1.4.0`) would build + stage but **not** activate — tag with
**bare numbers** (`1.4.0`).
## What each step does
1. **Checkout**`git clone` of the pushed branch/tag (the runner doesn't use a
checkout action).
2. **Test**`go test ./...` inside a `golang:1.26` container.
3. **Build** — static binary: `CGO_ENABLED=0 go build -buildvcs=false -ldflags "-s -w"`
(pure-Go SQLite, so no C toolchain; `-buildvcs=false` avoids the container's
dubious-ownership git error).
4. **Upload binary** — the `hsa` binary as a downloadable run artifact.
5. **Stage release** *(tags only)*`scp` the binary to
`~/hsa-app/releases/hsa-app-V<tag>/hsa` on the host and `chmod +x` it.
6. **Activate release** *(release tags `X.Y.Z` only)*`ln -sfn` the
`~/hsa-app/hsa` symlink to the new release and `systemctl --user restart hsa_app`.
Pre-release tags log "staged but not activated" and stop here.
## Cutting a release
```bash
# 1. land your change on main (push branch -> CI builds/tests -> merge)
# 2. tag and push:
git tag -a 1.4.0 -m "1.4.0 — <summary>"
git push origin 1.4.0
```
The tag push runs the whole pipeline through Activate. Watch it under the repo's
**Actions** tab; the **Activate release** step is the one that goes live. Roll back
by activating an older still-staged release (see [INSTALL.md](INSTALL.md)).
## Runner requirements
- One Forgejo `act_runner` registered with the **`shell`** label (`runs-on: shell`).
The job runs directly on the host, which therefore must have the **docker CLI**
available (the Test/Build steps run inside `golang:1.26` via `docker run`).
- The deploy steps `ssh`/`scp` from the runner host to the app host (they may be the
same machine). The app must run as a **user systemd service** named `hsa_app`,
reachable via `systemctl --user` — which requires `loginctl enable-linger` for the
deploy user (see [INSTALL.md](INSTALL.md)).
## Required repo configuration (Settings → Actions)
| Name | Kind | Purpose |
|---|---|---|
| `FORGEJO_SSH` | **Secret** | private SSH key authorized on the app host |
| `HSA_APP_HOST` | **Variable** | app host name / IP |
| `HSA_APP_USER` | **Variable** | SSH user that owns `~/hsa-app` and the user service |
If these are missing, branch pushes still build/test, but the Stage/Activate steps
fail on tags.