ci: run make check on every push and pull request #49

Merged
claudiomaradonna merged 4 commits from feat/forgejo-ci into main 2026-11-12 12:09:23 +01:00
Collaborator

Why

castrum's fast gate, make check (yamllint, ShellCheck, ansible-lint,
the playbook syntax check and the repository's gate scripts), ran only
when a contributor remembered to run it before a push. A forgotten run
let a lint finding or a broken gate reach main unseen, to be found by
the next contributor whose own run failed on someone else's change. The
forge now has runners, so it can run the gate itself.

Running make test (molecule) in CI as well was set aside for now: it
needs rootless podman and a raised inotify limit on the runner. Any
deployment from CI was set aside too, since it would put SSH keys and
vault passwords for every tenant on the runner.

What changed

Before, nothing ran on a push. Now every push to main, and every
pull request against it, runs make setup && make check on a
runner labelled docker, and reports the result as a commit status.
The job runs in node:22-trixie, pinned by digest: Node serves the
checkout action, and its system python3 with python3-apt lets the
docker_engine gate run its python3-debian case. The checkout action
comes from code.forgejo.org, pinned by commit, and does not leave the
job's token in .git/config for the code make setup fetches. The
job uses no secret.

CONTRIBUTING.md#running-the-gates now says what the forge runs and
what stays local, and AGENTS.md drops its "nothing runs the gates
automatically" clause. The workflow lives in
.forgejo/workflows/check.yml.

The first run found make check failing under ShellCheck 0.10, the
version Debian 13 ships: it reports tests/molecule/run.sh's trap-only
handler as SC2317, where 0.11 says SC2329, the only one the script
disabled. The script now disables both.

How to verify

  1. Have a Forgejo account that can push to this repository, and a
    runner with the docker label registered for it.

  2. The problem, on main: open a pull request from any scratch branch
    against main; it shows no status check.

  3. The solution: from this branch, make a scratch branch, break one
    gate and push it:

    git switch -c ci-trial-red origin/feat/forgejo-ci
    printf 'key: [unclosed\n' > broken.yml
    git add broken.yml && git commit -m 'test: break yamllint'
    git push origin ci-trial-red
    

    Open a pull request from ci-trial-red against main. The check
    workflow's run fails at the "Run the fast gate" step,
    with yamllint naming broken.yml. This pull request's own run
    passes, its log shows each == gate: line, and it has no
    python3-debian case not run line. Close it and delete
    ci-trial-red afterwards.

make check passed locally on each commit, and the forge's run on
this pull request passed after the ShellCheck fix. Not tried: the red
run of step 3; make test, since the change touches no role.

Considerations

The sentence "main accepts only a change whose run has passed" in
CONTRIBUTING becomes true only once main's existing protection rule
requires this workflow's pull_request status, so merge after that is
set. Pushes run the job only on main, so a pull request's branch
runs it once, for the pull request event. The image digest and the
action's commit are bumped by hand, as the workflow's comment says.

## Why castrum's fast gate, `make check` (yamllint, ShellCheck, ansible-lint, the playbook syntax check and the repository's gate scripts), ran only when a contributor remembered to run it before a push. A forgotten run let a lint finding or a broken gate reach `main` unseen, to be found by the next contributor whose own run failed on someone else's change. The forge now has runners, so it can run the gate itself. Running `make test` (molecule) in CI as well was set aside for now: it needs rootless podman and a raised inotify limit on the runner. Any deployment from CI was set aside too, since it would put SSH keys and vault passwords for every tenant on the runner. ## What changed Before, nothing ran on a push. Now every push to `main`, and every pull request against it, runs `make setup && make check` on a runner labelled `docker`, and reports the result as a commit status. The job runs in `node:22-trixie`, pinned by digest: Node serves the checkout action, and its system `python3` with `python3-apt` lets the `docker_engine` gate run its `python3-debian` case. The checkout action comes from code.forgejo.org, pinned by commit, and does not leave the job's token in `.git/config` for the code `make setup` fetches. The job uses no secret. `CONTRIBUTING.md#running-the-gates` now says what the forge runs and what stays local, and `AGENTS.md` drops its "nothing runs the gates automatically" clause. The workflow lives in `.forgejo/workflows/check.yml`. The first run found `make check` failing under ShellCheck 0.10, the version Debian 13 ships: it reports `tests/molecule/run.sh`'s trap-only handler as SC2317, where 0.11 says SC2329, the only one the script disabled. The script now disables both. ## How to verify 1. Have a Forgejo account that can push to this repository, and a runner with the `docker` label registered for it. 2. The problem, on `main`: open a pull request from any scratch branch against `main`; it shows no status check. 3. The solution: from this branch, make a scratch branch, break one gate and push it: ```bash git switch -c ci-trial-red origin/feat/forgejo-ci printf 'key: [unclosed\n' > broken.yml git add broken.yml && git commit -m 'test: break yamllint' git push origin ci-trial-red ``` Open a pull request from `ci-trial-red` against `main`. The `check` workflow's run fails at the "Run the fast gate" step, with yamllint naming `broken.yml`. This pull request's own run passes, its log shows each `== gate:` line, and it has no `python3-debian case not run` line. Close it and delete `ci-trial-red` afterwards. `make check` passed locally on each commit, and the forge's run on this pull request passed after the ShellCheck fix. Not tried: the red run of step 3; `make test`, since the change touches no role. ## Considerations The sentence "`main` accepts only a change whose run has passed" in CONTRIBUTING becomes true only once `main`'s existing protection rule requires this workflow's `pull_request` status, so merge after that is set. Pushes run the job only on `main`, so a pull request's branch runs it once, for the pull request event. The image digest and the action's commit are bumped by hand, as the workflow's comment says.
Nothing ran the gates automatically, so a forgotten make check let a
lint finding or a broken gate reach main unseen. The job runs in
node:22-trixie, pinned by digest: Node serves the checkout action, and
its system python3 with python3-apt lets the docker_engine gate run its
python3-debian case. The checkout action is pinned by commit to the
code.forgejo.org copy, independent of the instance's default actions
URL.
docs(contributing): say what the forge runs
Some checks failed
check / check (push) Failing after 5m3s
check / check (pull_request) Failing after 3m15s
e1d755a464
fix(tests): pass ShellCheck 0.10 in the molecule runner
Some checks failed
check / check (push) Successful in 19m29s
check / check (pull_request) Has been cancelled
3cc199b039
ShellCheck 0.11 reports the trap-only interrupted() handler as SC2329,
which the runner already disables, but 0.10, Debian 13's ShellCheck and
the CI image's, reports each of its lines as SC2317, so make check failed
there. Disabling both keeps the script clean under either version.
ci: run on pushes to main only
All checks were successful
check / check (pull_request) Successful in 19m22s
check / check (push) Successful in 19m34s
3553a82ba4
A pull request's branch ran the job twice, once for the push and once
for the pull request. Pull requests are covered by their own event, so
pushes need running only on main, where merges land.
claudiomaradonna deleted branch feat/forgejo-ci 2026-11-12 12:09:29 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
claudiomaradonna/castrum!49
No description provided.