nigig-org/.forgejo/workflows/nigig-map.yml
nigig-ci 833181faec
All checks were successful
nigig-map / test (push) Successful in 5m41s
repo hygiene / hygiene (push) Successful in 4s
ci(map): fix the ratchet aborting before it could evaluate anything
First real run of nigig-map.yml reported failure at 530 passed /
9 failed -- exactly the baseline it was supposed to allow.

The step ran `out="$(cargo test ...)"` under the runner's `-e` shell.
cargo test exits 101 while any test fails, and a failing command
substitution in a plain assignment aborts the step immediately, so
neither the parse nor the comparison ever executed. The `set -o
pipefail` I had added made it worse, not better.

`|| status=$?` puts the assignment inside a tested compound command,
which -e exempts, so the script keeps control and decides for itself.

Verified against the same `bash -e` the runner uses:
  at baseline      530 passed / 9 failed  -> exit 0, "OK"
  regressed        527 passed / 12 failed -> exit 1, "12 failing ...
                                             baseline is 9"
  restored         530 passed / 9 failed  -> exit 0

My bug, introduced in de698b1. The rest of that workflow was sound:
the same run proved checkout, native deps, the pinned-toolchain
install and the build gate all pass, which is the first time this
crate has ever built in CI.
2026-08-04 05:15:00 +00:00

148 lines
6.3 KiB
YAML

name: nigig-map
# CI workflow for the map rendering crate.
#
# Enforces:
# 1. The map crate compiles (lib + tests).
# 2. The test suite is green.
# 3. No regressions in tile parsing, style compilation, or tessellation.
#
# This workflow was added to catch runtime errors like:
# - 'too many elements (N > 100000)' from overpass_parser
# - 'type mismatch for property style_light: expected MapThemeStyle'
# - triangulation failures in tile_disk
on:
push:
paths:
- 'crates/apps/map/**'
- 'Cargo.lock'
- 'Cargo.toml'
- 'rust-toolchain.toml'
- '.forgejo/workflows/nigig-map.yml'
pull_request:
paths:
- 'crates/apps/map/**'
- 'Cargo.lock'
- 'Cargo.toml'
- 'rust-toolchain.toml'
- '.forgejo/workflows/nigig-map.yml'
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
# Makepad needs a desktop/GL stack even for a check build.
- name: Install native dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq \
pkg-config libwayland-dev libxcursor-dev libxrandr-dev \
libxi-dev libx11-dev libgl1-mesa-dev libasound2-dev \
libglib2.0-dev libssl-dev libsqlite3-dev libudev-dev \
libpulse-dev libxkbcommon-dev
# NOT `actions/setup-rust@v1`. That action does not exist on this
# instance's action registry (data.forgejo.org) and Forgejo does
# not fall back to github.com, so the job died in "Set up job"
# with "repository not found" and cancelled all seven steps. It
# had therefore never built anything. See .forgejo/RUNNER.md.
#
# It also asked for `toolchain: stable`, which contradicts the
# 1.97.1 pin in rust-toolchain.toml. This installs the declared
# version, matching pay-domain.yml.
- name: Install the declared toolchain
run: |
set -e
version="$(sed -n 's/^[[:space:]]*channel[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' \
rust-toolchain.toml | head -n 1)"
curl --fail --location --proto '=https' --tlsv1.2 https://sh.rustup.rs -o /tmp/rustup-init
chmod 700 /tmp/rustup-init
/tmp/rustup-init -y --profile minimal --default-toolchain "$version" \
--component rustfmt --component clippy --no-modify-path
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Cache cargo registry
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-map-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-map-
# The gate that matters: until now this crate did not compile at
# all. Keep it first so a regression is unambiguous.
- name: Build map crate
run: cargo build --manifest-path crates/apps/map/Cargo.toml
# `cargo test` (no filter) still fails to COMPILE two of the four
# test targets -- tests/ui.rs imports makepad_widgets::makepad_test,
# and tests/makepad_visual_tests.rs plus the criterion bench import
# private modules and a dev-dependency that is not declared. Those
# are separate pre-existing defects, not map logic.
#
# The 535 unit tests in src/ are real and were never executed
# before the crate compiled. Nine of them fail on genuine logic
# (4 mvt_parser, 1 overpass_parser, 4 sprite classification), so
# this is a ratchet rather than a hard gate: it holds the line at
# the current count and fails if it gets worse.
- name: Unit tests (ratchet)
run: |
# No `set -e` / `set -o pipefail` here, deliberately. The runner
# already runs steps under `-e`, and `cargo test` exits non-zero
# while the baseline is above 0, so the command substitution
# below would abort the step before any ratchet logic ran. That
# is exactly what happened on the first run of this workflow:
# 530 passed / 9 failed -- precisely the baseline -- reported as
# a failure. Capture the status, then decide.
BASELINE=9
# `out=$(cmd)` under -e aborts on a non-zero cmd before the next
# line runs, so `status=$?` never executes. `|| status=$?` keeps
# the assignment inside a tested compound command, which -e
# exempts.
status=0
out="$(cargo test --manifest-path crates/apps/map/Cargo.toml --lib 2>&1)" \
|| status=$?
echo "$out"
echo "cargo test exit status: $status"
line="$(echo "$out" | grep -E '^test result:' | tail -n 1)"
failed="$(echo "$line" | sed -n 's/.* \([0-9]\+\) failed.*/\1/p')"
passed="$(echo "$line" | sed -n 's/.* \([0-9]\+\) passed.*/\1/p')"
echo "passed=$passed failed=$failed baseline=$BASELINE"
if [ -z "$failed" ]; then
echo "ERROR: could not parse a test result line."
exit 1
fi
if [ "$failed" -gt "$BASELINE" ]; then
echo "ERROR: $failed failing unit tests, baseline is $BASELINE."
echo "A new unit test regression was introduced."
exit 1
fi
if [ "$failed" -lt "$BASELINE" ]; then
echo "$failed < $BASELINE: lower BASELINE in this workflow."
fi
echo "OK"
# rustfmt could not parse view.rs while the crate was broken, so it
# silently skipped all of src/ and only ever checked tests/. With
# the parse error fixed it reports 392 pre-existing diffs in src/.
# Reformatting them wholesale would bury the next real diff, so
# this reports and does not gate -- the same reasoning already
# recorded in doc-engine.yml and sms.yml.
- name: Formatting (report only)
run: |
cargo fmt --manifest-path crates/apps/map/Cargo.toml -- --check \
|| echo "NOTE: pre-existing formatting drift, not gated yet."
# Likewise clippy: -D warnings against a crate with 132 existing
# warnings is a step that always fails, which gets ignored.
- name: Clippy (report only)
run: |
cargo clippy --manifest-path crates/apps/map/Cargo.toml \
|| echo "NOTE: pre-existing clippy findings, not gated yet."