Every workflow in .forgejo/workflows is scoped with `paths:`. That is right for build and test jobs -- no reason to compile the CAD module because a payment file moved -- but it leaves a structural hole: a commit touching only unfiltered paths runs no checks at all. Commit8c9ccb9fell straight through it, pushing 30 unresolved conflict-marker lines across five files. The worst of them was .forgejo/workflows/nigig-build.yml itself: with markers in it the file is not valid YAML, so all seven CAD gates silently stopped running. A workflow that does not parse does not fail -- it does not run, which is strictly worse than a red build because nothing announces it. `git diff --check` would have caught this and was already a step. It was in the file the same commit broke, and only ran for that workflow's filtered paths. So this workflow has no path filter, no toolchain dependency and no network dependency -- it cannot be knocked out by an unrelated build break -- and it validates the CI configuration itself: 1. No conflict markers anywhere in the tree. 2. Every workflow file parses as YAML and has a top-level `jobs:`. 3. Whitespace errors. Verified against the real failure, not a synthetic one: checked out8c9ccb9and confirmed check 1 reports all 30 marker lines and check 2 names both unparseable workflows. Also probed for false positives -- `>>`/`<<` shift operators, `// =======` comments and a "=======" string literal do not trip it, because the patterns are anchored to column 0 and the closing marker requires the trailing space git writes. Also fixes the fifth file from that commit, which I missed while repairing the others because I only grepped .rs and .yml: ARCHITECTURE.md still had two live conflicts on main. Both were stale-vs-current versions of my own lines; kept the current text. While there, refreshed every LOC figure in the file table from the actual files -- 14 of them were stale, workspace.rs by 64 lines.
90 lines
3.6 KiB
YAML
90 lines
3.6 KiB
YAML
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
|