Compare commits

...

7 commits

Author SHA1 Message Date
Jean-Michel Tremblay
3bb0e5f678 Merge branch 'ci-forgejo-build'
All checks were successful
Build and Test / build-and-test (push) Successful in 33s
2026-06-19 15:13:14 -04:00
Jean-Michel Tremblay
fafd763d99 Split deploy: auto-stage on tag, manual activate via button
All checks were successful
Build and Test / build-and-test (push) Successful in 34s
build.yml now only stages the binary into ~/hsa-app/releases on tag
(no symlink swap or restart). Activation is a separate workflow_dispatch
workflow (deploy.yml) the user triggers from the Forgejo Actions tab,
passing the tag to point the symlink at and restart. Update INSTALL.md
to describe the stage/activate split.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:12:22 -04:00
Jean-Michel Tremblay
f47e611e2c Deploy tagged releases via versioned dir + symlink swap
All checks were successful
Build and Test / build-and-test (push) Successful in 36s
On tag push, scp the binary to ~/hsa-app/releases/hsa-app-V<tag>/hsa,
repoint the ~/hsa-app/hsa symlink, and restart the user systemd
service. Add deploy/hsa_app.service unit and deploy/INSTALL.md with
host layout, one-time install, deploy, and rollback steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:08:20 -04:00
Jean-Michel Tremblay
2f817d16d0 CI: deploy binary to versioned dir on tag push
All checks were successful
Build and Test / build-and-test (push) Successful in 35s
On a tag push, scp the built hsa binary to ~/hsa-app-V<tag> on the
target host (created if missing). Reuses the FORGEJO_SSH key; host and
user come from the HSA_APP_HOST / HSA_APP_USER repo vars. Branch
pushes still only build and test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:44:16 -04:00
Jean-Michel Tremblay
cddc42b32d CI: disable VCS stamping in containerized build
All checks were successful
Build and Test / build-and-test (push) Successful in 34s
git inside the golang container flags the mounted repo as dubious
ownership (different UID), so `go build` fails obtaining VCS status
(exit 128). The binary doesn't need git version stamping here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:39:14 -04:00
Jean-Michel Tremblay
5bf03feb94 CI: target the shell runner label instead of docker
Some checks failed
Build and Test / build-and-test (push) Failing after 36s
The only registered act_runner advertises the `shell` label, not
`docker`, so `runs-on: docker` left the job queued forever. The host
has the docker CLI (the resume repo builds via `docker run` on this
same runner), so keep running the build/test inside a golang container.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:36:25 -04:00
Jean-Michel Tremblay
15335a9f4c Add Forgejo Actions workflow to build and test on push
Some checks are pending
Build and Test / build-and-test (push) Waiting to run
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:31:20 -04:00
4 changed files with 163 additions and 0 deletions

View file

@ -0,0 +1,30 @@
name: Build and Test
on: [push]
jobs:
build-and-test:
runs-on: shell
steps:
- name: Checkout
run: |
git clone --branch ${{ github.ref_name }} ${{ github.server_url }}/${{ github.repository }}.git .
- name: Test
run: docker run --rm -w /src -v $PWD:/src golang:1.26 go test ./...
- name: Build
run: docker run --rm -w /src -v $PWD:/src -e CGO_ENABLED=0 golang:1.26 go build -buildvcs=false -ldflags "-s -w" -o hsa ./cmd/hsa
- name: Upload binary
uses: actions/upload-artifact@v3
with:
name: hsa
path: hsa
- name: Stage release
if: startsWith(github.ref, 'refs/tags/')
run: |
echo "${{ secrets.FORGEJO_SSH }}" > /tmp/deploy_key
chmod 600 /tmp/deploy_key
TAG=${{ github.ref_name }}
REL=hsa-app/releases/hsa-app-V$TAG
TARGET=${{ vars.HSA_APP_USER }}@${{ vars.HSA_APP_HOST }}
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no $TARGET "mkdir -p $REL"
scp -i /tmp/deploy_key -o StrictHostKeyChecking=no hsa $TARGET:$REL/hsa
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no $TARGET "chmod +x $REL/hsa"
rm /tmp/deploy_key

View file

@ -0,0 +1,24 @@
name: Deploy
on:
workflow_dispatch:
inputs:
tag:
description: 'Release version to activate, e.g. 0.0.0a1 (must already be staged in ~/hsa-app/releases/hsa-app-V<tag>/hsa)'
required: true
jobs:
deploy:
runs-on: shell
steps:
- name: Activate release
run: |
echo "${{ secrets.FORGEJO_SSH }}" > /tmp/deploy_key
chmod 600 /tmp/deploy_key
TAG=${{ github.event.inputs.tag }}
TARGET=${{ vars.HSA_APP_USER }}@${{ vars.HSA_APP_HOST }}
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no $TARGET \
"cd hsa-app \
&& test -f releases/hsa-app-V$TAG/hsa \
&& chmod +x releases/hsa-app-V$TAG/hsa \
&& ln -sfn releases/hsa-app-V$TAG/hsa hsa \
&& systemctl --user restart hsa_app"
rm /tmp/deploy_key

95
deploy/INSTALL.md Normal file
View file

@ -0,0 +1,95 @@
# Deploying hsa-app
The app runs as a **user systemd service** (no sudo). Deployment is two steps:
1. **Stage (automatic on tag)** — pushing a git tag builds + tests, then CI
copies the binary into `~/hsa-app/releases/hsa-app-V<tag>/hsa`. Nothing goes
live yet.
2. **Activate (manual button)** — run the **Deploy** workflow from the Forgejo
Actions tab ("Run workflow"), entering the tag to activate. It points the
`~/hsa-app/hsa` symlink at that release and restarts the service.
The symlink decouples "what's on disk" from "what's running," so activation and
rollback are just a symlink repoint + restart.
## Layout on the host
Mutable state (DB, env, config) lives at the top of `~/hsa-app/` and survives
every deploy. Only the binaries live under `releases/`.
```
~/hsa-app/
hsa_app.sh # launcher: sources env file, exec's the binary
hsa_app.env # environment (KEY=VALUE)
config.json
hsa.db, hsa.db-shm, hsa.db-wal # SQLite state
releases/
hsa-app-V0.0.0a0/hsa
hsa-app-V0.0.1/hsa
hsa -> releases/hsa-app-V0.0.1/hsa # current symlink, swapped on deploy
```
## The current symlink
Create/repoint it **from inside `~/hsa-app`** so the relative target resolves
against the link's own directory (running `ln -s` from `~` produces a broken
link that points at `~/hsa-app/hsa-app/...`):
```bash
cd ~/hsa-app
chmod +x releases/hsa-app-V<tag>/hsa
ln -sfn releases/hsa-app-V<tag>/hsa hsa # -f replace, -n don't follow existing link
ls -l hsa # target must resolve (not broken)
```
This same `ln -sfn` + `chmod +x` is what the CI deploy step runs on each tag.
## Install the service (once)
Save [hsa_app.service](hsa_app.service) to `~/.config/systemd/user/hsa_app.service`,
then:
```bash
loginctl enable-linger "$USER" # run the service without an active login session
systemctl --user daemon-reload
systemctl --user enable --now hsa_app
systemctl --user status hsa_app
journalctl --user -u hsa_app -f # follow logs
```
### Why these choices
- **User service** (`systemctl --user`) — no sudo, matches the home-dir deploy.
`enable-linger` lets it start at boot / stay up without an interactive login.
- **`Type=exec`** — `hsa_app.sh` ends in `exec "$BIN"`, so the binary becomes the
unit's main process; signals and exit codes propagate correctly.
- **`WorkingDirectory=%h/hsa-app`** — relative paths in the env file resolve here.
The launcher's comment recommends absolute paths for `DB_PATH` / `STORAGE_DIR` /
`BACKUP_DIR` / `CONFIG_PATH`; either works.
- **ExecStart passes the env file as `$1`** — matches `hsa_app.sh`'s first-arg
precedence, so no `/etc/hsa-app/...` file is needed. `%h` expands to the home dir.
- The launcher defaults its binary to `./hsa` next to itself (`~/hsa-app/hsa`, the
symlink), so a restart after a symlink swap runs the new release automatically.
## Deploy a tagged release
Pushing a tag stages the binary automatically. To activate it, open the repo's
**Actions → Deploy** workflow, click **Run workflow**, and enter the tag (e.g.
`0.0.0a1`). To activate from the host instead:
```bash
cd ~/hsa-app
chmod +x releases/hsa-app-V<tag>/hsa
ln -sfn releases/hsa-app-V<tag>/hsa hsa
systemctl --user restart hsa_app
```
## Roll back
Every release stays under `releases/`, so rollback is a symlink repoint:
```bash
cd ~/hsa-app
ln -sfn releases/hsa-app-V<old-tag>/hsa hsa
systemctl --user restart hsa_app
```

14
deploy/hsa_app.service Normal file
View file

@ -0,0 +1,14 @@
[Unit]
Description=HSA app
After=network-online.target
Wants=network-online.target
[Service]
Type=exec
WorkingDirectory=%h/hsa-app
ExecStart=%h/hsa-app/hsa_app.sh %h/hsa-app/hsa_app.env
Restart=on-failure
RestartSec=2
[Install]
WantedBy=default.target