# 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/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 — " 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.