pediatric-ai-scribe-v3/CONTRIBUTING.md
Daniel 36cb742ce7
All checks were successful
Forgejo Docker Build / Root app tests (push) Successful in 54s
Forgejo Docker Build / Build Docker image (push) Successful in 7s
ci: fix the failing job, split deploy out, and drop the Android build
Three things, one subject: making CI say the truth about this repo.

## The red on every run was ours, not the runners'

Every docker-build run came back success, success, failure — the same
shape for weeks. The failing job was `deploy`, and it was failing to
*not run*:

    if: ${{ github.event.inputs.deploy == 'true' }}

On a push there is no github.event.inputs at all. This Forgejo does not
treat that as false and skip; it dispatches the job, the runner cannot
resolve it, and the task ends in "Early termination". The runners were
never at fault, and nothing about them needed changing.

The `'runs-on' key not defined` line is a red herring: the `build` job
prints it too and succeeds. It names the job's *needs* target, not the
job, and the old android-apk workflow used `needs:` happily for months.

Deploy is now its own workflow with only workflow_dispatch — no
condition to evaluate, so nothing can be dispatched by mistake. No job
in either file now carries a job-level `if`. The one conditional left is
a *step* (push to registry), and step conditions are evaluated by the
runner once the job is already running, which is why that one has always
worked.

## dev and main

docker-build now runs on `dev` as well. Both branches prove the same two
things — tests pass, image builds — and only `main` publishes the image,
so nothing on `dev` can be mistaken for something deployable. Deploying
stays a person pressing a button after looking at the change.
CONTRIBUTING.md documents the flow.

## Android

Removed: the mobile/ Capacitor project, docs/mobile-build.md, and the
Android bits of scripts/release.sh. All of it is in git history — 4613a278
is the last commit that had it — for when it is rebuilt.

src/utils/platform.js stays. isMobileClient only decides token lifetime,
it is twelve lines, and it is the contract a future app would come back
to; deleting it would be a change to auth for no gain.

.github/workflows/ went too — all five. There is no GitHub remote on
this repository, so none of them has ever run, and two of them wrote
into mobile/ paths that no longer exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-12 23:30:52 +02:00

2.6 KiB

Contributing

Commit format

Conventional Commits. Nothing parses these automatically any more — the auto-version workflow was a GitHub one and this repository has no GitHub remote — but the prefixes still say what a change is, and scripts/release.sh still wants a version chosen the same way.

Prefix Bump
fix: patch bug fix
feat: minor new feature
feat!: / fix!: / BREAKING CHANGE: in body major breaking change
docs: refactor: chore: test: style: ci: build: none no release

Manual release

scripts/release.sh 6.2.0 --push       # bump, commit, tag, push

Branches

main is production. It is what scripts/deploy.sh deploys and what the container registry publishes from. dev is where work lands first.

feature work ──▶ dev ──▶ (tests pass, you try it) ──▶ main ──▶ deploy
Branch On push, CI does Publishes an image
dev runs the test suite, then builds the image no
main runs the test suite, builds the image, pushes it to the registry yes

dev builds the image but does not publish it, so nothing on dev can be mistaken for something deployable. Both branches prove the same two things — the tests pass and the image builds — which is the point: by the time a change reaches main the only new question is whether it is right, not whether it works mechanically.

Deploying is never automatic. It is the Deploy workflow, run by hand from the Actions tab, after you have looked at the change. That is deliberate: the step between "tests pass" and "this is live" is a person deciding, and a push is not a decision. scripts/deploy.sh then pins the image, waits for health, asks /api/build which revision is actually serving, and rolls back if the answer disagrees.

To merge up:

git checkout main && git merge --no-ff dev && git push forgejo main

--no-ff keeps the merge visible, so a release is one commit to point at and one commit to revert.

Local dev

docker compose up -d                  # Postgres + app
docker logs -f pediatric-ai-scribe

Web changes hot-reload via browser refresh (JS/CSS cached 1h — add ?v= query or clear cache; the build-ID server-side cache-buster appends ?v=<git SHA> automatically on fresh page loads).

Server code changes require ./scripts/build-image.sh && docker compose up -d --no-build.

DB migrations

src/db/database.js is the baseline (idempotent CREATE-IF-NOT-EXISTS). New changes go in migrations/ via node-pg-migrate. See docs/migrations.md.