From 6473e7d9ae1ce626943565bd3dfbd46ca0b0389b Mon Sep 17 00:00:00 2001 From: ScottW514 Date: Fri, 16 Oct 2026 23:49:02 -0400 Subject: [PATCH] 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. --- .github/workflows/forgetest-ci.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/forgetest-ci.yml b/.github/workflows/forgetest-ci.yml index 5874eb8..386ba68 100644 --- a/.github/workflows/forgetest-ci.yml +++ b/.github/workflows/forgetest-ci.yml @@ -144,13 +144,17 @@ jobs: - name: No undefined names (the live drills never execute on the host) working-directory: forgefirm/forgetest # 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 - # capture that cannot be written fails the step. + # grep is the gate. A run stopped by SIGINT exits 1 too, and its + # "... 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: | python -m pip install pyflakes python -B -m pyflakes --version - { python -B -m pyflakes forgetest tests || test $? -eq 1; } > pyflakes.txt 2>&1 - if grep -E "undefined name|Traceback" pyflakes.txt; then exit 1; fi + { python -B -m pyflakes forgetest tests || test $? -eq 1; } > pyflakes.txt 2>&1 || { cat pyflakes.txt; exit 1; } + if grep -E "undefined name|Traceback|^\.\.\. stopped$" pyflakes.txt; then exit 1; fi - name: Shared UI files match forgectrl at its pinned revision working-directory: forgefirm