name: repo hygiene # The one workflow with NO path filter. # # Every other workflow in this directory gates a specific crate and is # scoped with `paths:`. That is correct for build and test jobs -- there # is no reason to compile the CAD module because a payment file moved. # But it leaves a structural hole: a commit that touches only unfiltered # paths runs no checks whatsoever. # # That hole is not hypothetical. Commit 8c9ccb9 pushed 30 unresolved # conflict-marker lines across five files: # # .forgejo/workflows/nigig-build.yml <- invalid YAML: the CAD gates # could not even be parsed, # so they silently stopped running # .forgejo/workflows/pdf.yml # crates/apps/.../cad/workspace.rs <- ~3,000 lines also lost # crates/apps/.../spreadsheet-engine/src/formula2.rs # crates/apps/.../cad/ARCHITECTURE.md # # `git diff --check` already existed as a step inside nigig-build.yml and # would have caught this -- but it was in the file the same commit broke, # and it only ran for paths under that workflow's filter. # # So the checks here must satisfy three properties: # 1. no path filter, # 2. no dependency on the Rust toolchain or the network, so they cannot # be knocked out by an unrelated build break, and # 3. they must validate the CI configuration itself. on: push: pull_request: jobs: hygiene: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v4 # An unresolved merge is the highest-severity thing that can reach # main: the file does not parse, and if it is a workflow the checks # that would have caught it stop running. - name: No conflict markers anywhere in the tree run: | set -euo pipefail # Anchored to line start, and the closing marker requires the # trailing space git writes, so ordinary text (a Markdown rule, # a Rust shift operator) does not trip it. if git grep -nE '^(<{7} |={7}$|>{7} )' -- \ ':(exclude).forgejo/workflows/repo-hygiene.yml'; then echo echo "ERROR: unresolved conflict markers are committed above." echo "Resolve the merge before pushing; these files do not parse." exit 1 fi echo "OK" # A workflow that is not valid YAML does not fail -- it does not run. # That is strictly worse than a red build, because it is invisible. - name: Every workflow file must be valid YAML run: | set -euo pipefail python3 - <<'PY' import sys, pathlib, yaml bad = [] for f in sorted(pathlib.Path('.forgejo/workflows').glob('*.yml')): try: doc = yaml.safe_load(f.read_text()) except Exception as exc: bad.append((f, exc)) continue if not isinstance(doc, dict) or 'jobs' not in doc: bad.append((f, 'no top-level `jobs:` mapping')) for f, why in bad: print(f"{f}: {why}") if bad: print() print("ERROR: the workflow file(s) above do not parse, so their") print("checks are silently not running.") sys.exit(1) print("OK") PY # Whitespace errors: trailing space, spaces-before-tab, and the # marker-adjacent damage a bad merge leaves behind. - name: Reject whitespace errors run: git diff --check "$(git rev-list --max-parents=0 HEAD | tail -1)"..HEAD || git diff --check