forgetest-ci: the undefined-name step prints why it failed, and fails a run SIGINT stopped

The comment over the step said that a signal fails it. pyflakes ends a
SIGINT and a SIGPIPE itself, with status 1 ("... stopped" for SIGINT),
and status 1 goes on to the grep, so a run SIGINT stopped mid-tree
passed the step with nothing judged. And every failure the step gained
for a status other than 0 or 1 left no cause in the step log: the
group's 2>&1 also captures bash's own notice of a signal ("Killed"),
and nothing printed pyflakes.txt, so a usage error or a killed run
showed only the pyflakes version line before the failure.

The capture is printed when the pyflakes group fails, and the grep
also takes the "... stopped" line. The comment says what fails the
step: the grep's lines, a SIGINT stop, any status other than 0 or 1,
and a capture that cannot be written; a SIGPIPE ends with status 1 and
no line, and a write to the capture file raises none.

Proof: the step body, read with PyYAML from this workflow and, as the
control, from the workflow before this change, run under bash -e over
the forgetest tree on Ubuntu 24.04 with python 3.12 and pyflakes 4.0.3
(the install line a no-op: the interpreter on PATH is a shim to a
venv). The tree as it is exits 0 with both bodies, and an undefined
name planted exits 1 with its line in the log. A run that exits 2 and
a run killed by SIGKILL while it blocks on a FIFO exit 1 with both
bodies; the step log of the former body holds only the version line,
and this one prints "unrecognized arguments" and the "Killed" notice.
A run stopped by SIGINT exits 0 with the former body and 1 with this
one, its "... stopped" line in the log. A working directory that
cannot be written exits 1 with both, its "Permission denied" in the
log.

Acceptance: none; CI only. .github/ is outside meta-forgefirm and
every covers map.
This commit is contained in:
ScottW514
2026-10-16 23:49:02 -04:00
parent fc6b7797af
commit 6473e7d9ae
+8 -4
View File
@@ -144,13 +144,17 @@ jobs:
- name: No undefined names (the live drills never execute on the host) - name: No undefined names (the live drills never execute on the host)
working-directory: forgefirm/forgetest working-directory: forgefirm/forgetest
# pyflakes exits 1 for any message, unused imports included, so the # pyflakes exits 1 for any message, unused imports included, so the
# grep is the gate; any other status (a signal, a usage error) or a # grep is the gate. A run stopped by SIGINT exits 1 too, and its
# capture that cannot be written fails the step. # "... stopped" line fails the grep. Any other status (a usage
# error, a signal pyflakes does not handle) fails the step and
# prints the capture, and a capture that cannot be written fails it
# too. pyflakes ends a SIGPIPE with status 1 and no line, and a
# write to the capture file raises none.
run: | run: |
python -m pip install pyflakes python -m pip install pyflakes
python -B -m pyflakes --version python -B -m pyflakes --version
{ python -B -m pyflakes forgetest tests || test $? -eq 1; } > pyflakes.txt 2>&1 { python -B -m pyflakes forgetest tests || test $? -eq 1; } > pyflakes.txt 2>&1 || { cat pyflakes.txt; exit 1; }
if grep -E "undefined name|Traceback" pyflakes.txt; then exit 1; fi if grep -E "undefined name|Traceback|^\.\.\. stopped$" pyflakes.txt; then exit 1; fi
- name: Shared UI files match forgectrl at its pinned revision - name: Shared UI files match forgectrl at its pinned revision
working-directory: forgefirm working-directory: forgefirm