All checks were successful
repo hygiene / hygiene (push) Successful in 3s
cad-module was the last red job and now passes. Board updated. Also records that pdf.yml/fuzz reporting "skipped" is correct -- it is gated on schedule || workflow_dispatch -- so nobody spends time investigating it as a failure. The caveat stays prominent: several jobs are green because their gate is deliberately loose (the nigig-map unit-test ratchet sits at 9 real failures, and its fmt/clippy steps are report-only). Those are listed under Known-not-gated so a full green board is not mistaken for a healthy codebase.
225 lines
7.4 KiB
Markdown
225 lines
7.4 KiB
Markdown
# CI runners
|
|
|
|
Until 2026-08-02 this repository had **zero registered runners and zero
|
|
workflow runs**. Seven workflow files existed and none of them had ever
|
|
executed — for any commit, on any branch, ever:
|
|
|
|
```
|
|
GET /api/v1/repos/andodeki/nigig-org/actions/runners -> []
|
|
GET /api/v1/repos/andodeki/nigig-org/actions/tasks -> {"total_count": 0}
|
|
```
|
|
|
|
A gate that never runs is not a gate. Registering the first runner
|
|
immediately turned up four defects that had been sitting on `main`,
|
|
described at the bottom of this file.
|
|
|
|
## Registering a runner
|
|
|
|
`gitdab.com` is Gitea 1.22 (Actions API compatible with
|
|
`forgejo-runner`). Any Linux host with Docker, or without it in host
|
|
mode, will do.
|
|
|
|
### 1. Get a registration token
|
|
|
|
Repo → Settings → Actions → Runners → "Create new runner", or:
|
|
|
|
```bash
|
|
curl -H "Authorization: token $GITEA_TOKEN" \
|
|
https://gitdab.com/api/v1/repos/andodeki/nigig-org/actions/runners/registration-token
|
|
```
|
|
|
|
Note this instance answers `GET` on that endpoint; `POST` returns 405.
|
|
|
|
### 2. Install and register
|
|
|
|
```bash
|
|
VERSION=6.3.1
|
|
curl -sSLo forgejo-runner \
|
|
"https://code.forgejo.org/forgejo/runner/releases/download/v${VERSION}/forgejo-runner-${VERSION}-linux-amd64"
|
|
chmod +x forgejo-runner
|
|
|
|
./forgejo-runner register --no-interactive \
|
|
--instance https://gitdab.com \
|
|
--token "<registration-token>" \
|
|
--name "<runner-name>" \
|
|
--labels 'ubuntu-latest:docker://node:20-bookworm'
|
|
```
|
|
|
|
Every job in `.forgejo/workflows/` uses `runs-on: ubuntu-latest`, so
|
|
that label must exist or nothing is ever scheduled.
|
|
|
|
**Host mode** (no Docker) also works and is what the first runs used:
|
|
|
|
```bash
|
|
--labels 'ubuntu-latest:host://-self-hosted'
|
|
```
|
|
|
|
Host mode runs jobs directly on the machine as the runner user. Jobs
|
|
`sudo apt-get install` native dependencies and write to `$HOME/.cargo`,
|
|
so use a disposable machine or a dedicated unprivileged user. Docker
|
|
mode is preferable for anything long-lived.
|
|
|
|
### 3. Run it
|
|
|
|
```bash
|
|
./forgejo-runner generate-config > config.yml
|
|
./forgejo-runner daemon --config config.yml
|
|
```
|
|
|
|
Confirm with:
|
|
|
|
```bash
|
|
curl -H "Authorization: token $GITEA_TOKEN" \
|
|
https://gitdab.com/api/v1/repos/andodeki/nigig-org/actions/runners
|
|
```
|
|
|
|
`"status": "active"` means it is polling.
|
|
|
|
## Action resolution — read this before adding `uses:`
|
|
|
|
Forgejo resolves `uses: owner/name@ref` against **`data.forgejo.org`**,
|
|
not `github.com`, and there is **no fallback**. An action that does not
|
|
exist there fails the job in `Set up job`, which cancels every
|
|
subsequent step — so the job reports failure having compiled nothing,
|
|
and the log looks like an infrastructure blip rather than a config bug.
|
|
|
|
Verify before committing:
|
|
|
|
```bash
|
|
git ls-remote --heads https://data.forgejo.org/<owner>/<name>
|
|
```
|
|
|
|
Known state:
|
|
|
|
| Action | Resolves? |
|
|
|---|---|
|
|
| `actions/checkout@v4` | yes |
|
|
| `actions/setup-java@v4` | yes |
|
|
| `actions/cache@v3` | yes |
|
|
| `actions/setup-rust@v1` | **no** |
|
|
| `android-actions/setup-android@v3` | **no** |
|
|
|
|
Prefer an inline `run:` step over a third-party action. `sms.yml`
|
|
installs the Android SDK with `cmdline-tools` directly for this reason.
|
|
|
|
## Reading job logs
|
|
|
|
The REST API on this instance returns 404 for
|
|
`/api/v1/repos/{owner}/{repo}/actions/tasks/{id}/logs`. The web UI's
|
|
JSON endpoint works:
|
|
|
|
```
|
|
POST /andodeki/nigig-org/actions/runs/<run_number>/jobs/<job_index>/attempt/1
|
|
Content-Type: application/json
|
|
|
|
{"logCursors":[{"step":0,"cursor":null,"expanded":true}, ...]}
|
|
```
|
|
|
|
`<job_index>` is the 0-based position of the job in the workflow file,
|
|
and `<run_number>` is `run_number` from the tasks API — not the task id.
|
|
Repeat with the returned `cursor` per step to page through output.
|
|
|
|
## What the first real runs found
|
|
|
|
All were invisible defects on `main`, each fixed in its own commit:
|
|
|
|
1. **`android-actions/setup-android@v3` does not exist on
|
|
data.forgejo.org.** The `android` job in `sms.yml` — the only job
|
|
that compiles the ~600 lines of JNI behind
|
|
`#[cfg(target_os = "android")]` — died in `Set up job` and cancelled
|
|
all seven of its steps.
|
|
|
|
2. **Five of six `tools/*.sh` were committed mode 100644.** Every one is
|
|
invoked as `./tools/<name>.sh`; both `pay-domain.yml` jobs died with
|
|
`Permission denied` at their first substantive step. Now gated in
|
|
`repo-hygiene.yml`.
|
|
|
|
3. **`cargo-deny --config` was passed to the binary instead of to the
|
|
`check` subcommand** in `pay-domain.yml`, so the dependency audit
|
|
exited 2 without auditing anything, skipping the three boundary gates
|
|
behind it.
|
|
|
|
4. **`repo-hygiene.yml` was never scheduled.** It was written as
|
|
|
|
```yaml
|
|
on:
|
|
push:
|
|
pull_request:
|
|
```
|
|
|
|
Valid YAML, and the spelling GitHub documents for "all branches" —
|
|
but this instance does not schedule it. The one workflow with no path
|
|
filter, whose entire purpose is to run on every commit, had never run
|
|
once. `on: [push, pull_request]` fixes it. Use the list form here.
|
|
|
|
5. **`actions/setup-rust@v1` does not exist** either, so `nigig-map.yml`
|
|
fails in `Set up job`. Not fixed — the `map` crate does not compile
|
|
on `main` regardless, so that workflow has more than a CI problem.
|
|
|
|
## Current state
|
|
|
|
Latest result per job, all on a real runner:
|
|
|
|
| Workflow | Job | Status |
|
|
|---|---|---|
|
|
| doc-engine.yml | engine, consumer | pass |
|
|
| nigig-build.yml | supply-chain, full-crate-check | pass |
|
|
| nigig-build.yml | cad-module, full-crate-check, supply-chain | pass |
|
|
| nigig-map.yml | test | pass |
|
|
| pay-domain.yml | isolated-payment-tests, payment-ui-tests | pass |
|
|
| pdf.yml | engine, makepad-integration | pass |
|
|
| pdf.yml | fuzz | skipped (schedule / workflow_dispatch only) |
|
|
| repo-hygiene.yml | hygiene | pass |
|
|
| sms.yml | gates, robius-sms, android, nigig-sms, supply-chain | pass |
|
|
|
|
**Every job passes.** `pdf.yml/fuzz` is gated on
|
|
`schedule || workflow_dispatch`, so `skipped` is its correct result on
|
|
a push.
|
|
|
|
That is a starting line, not a finish line — see below for what is
|
|
green because it is genuinely healthy versus green because the gate is
|
|
deliberately loose.
|
|
|
|
### Known-not-gated
|
|
|
|
Things that are broken but deliberately not failing a build, so nobody
|
|
mistakes silence for health:
|
|
|
|
- **`nigig-map` unit tests**: ratchet at 9 failures, not a hard gate.
|
|
530 pass; the 9 are real logic bugs (4 `mvt_parser`, 1
|
|
`overpass_parser`, 4 `sprite` classification) that were invisible
|
|
until the crate compiled.
|
|
- **`nigig-map` test targets**: `tests/ui.rs` imports
|
|
`makepad_widgets::makepad_test`; `tests/makepad_visual_tests.rs` and
|
|
`benches/tile_decode_bench.rs` import `pub(crate)` modules, and
|
|
`criterion` is not a declared dev-dependency. The workflow runs
|
|
`--lib` only for that reason.
|
|
- **`nigig-map` fmt/clippy**: report-only. 392 pre-existing fmt diffs in
|
|
`src/` (rustfmt could not parse `view.rs` before, so it silently
|
|
skipped the whole directory) and 132 clippy warnings.
|
|
|
|
### Runner capacity
|
|
|
|
One runner with `capacity: 1` serialises every job; a push touching
|
|
several filtered paths takes a while to drain. Raise `capacity`, or add
|
|
runners, if that becomes annoying.
|
|
|
|
### Writing a ratchet step
|
|
|
|
The runner executes `run:` blocks under `bash -e`. A bare
|
|
|
|
```bash
|
|
out="$(cargo test ...)"
|
|
```
|
|
|
|
aborts the step the moment the command exits non-zero — which is always
|
|
true while a ratchet baseline is above zero — so the comparison never
|
|
runs and the step fails at exactly the count it was meant to allow.
|
|
This bit nigig-map.yml on its first run. Use:
|
|
|
|
```bash
|
|
status=0
|
|
out="$(cargo test ... 2>&1)" || status=$?
|
|
```
|
|
|
|
`|| status=$?` makes it a tested compound command, which `-e` exempts.
|