forgetest: the lint's docstrings and its row reason say what it reads, not what a workflow runs on

host_row_problems' docstring gave the reason a row is listed as "a
dispatch, a call or a schedule runs on no change". A workflow on
workflow_call alone runs on every run of the workflow that calls it
(forgeext's package.yml is one); the lint lists it because it does not
follow a call to its caller. The reason it printed, "<ci> runs on no
push or pull request", was false the same way for such a workflow, and
for a flow mapping (`on: {push: ...}`) that names push. The docstrings
of _on_every_run and workflow_runs said that a step under an `if:`
other than true does not run on every run, where the lint evaluates no
condition: a step under `always()` or `success()` runs on every run and
still counts as no step. The Test page of the site says each of these
as the lint applies it.

The docstrings now say what the lint reads: a row is listed when the
workflow's own `on:` names neither push nor pull_request as the lint
reads it (a dispatch, a call or a schedule alone, a call not followed
to its caller, a flow mapping), and a step with a condition counts as
no step because the lint evaluates none. The row's reason reads "<ci>:
the lint reads no push or pull_request in its own on:". The comments
of the two cases that hold these rules say the same. No rule changes:
the same rows are listed, for the same workflows.

Proof: forgetest-ci "Unit tests" (`python -B -m unittest discover -s
tests -v` in forgetest): test_manifest.py runs 39 tests, OK, on Windows
with python 3.14 and on Ubuntu 24.04 with python 3.12, with
test_the_workflow_has_to_run_the_host_test asserting the new reason. A
probe of host_row_problems: a workflow on workflow_call alone and one
whose flow-mapping `on:` names push are each listed with the new
reason, and a plain `on: [push]` one is not. The coverage lint on the
tree manifest from the recipe pins reports 0 uncovered paths, 0
host-tested row problems, 43 tests. pyflakes reports no undefined name.

Acceptance: none. forgetest is dev-only and in no fingerprint (the
source_sha of 43 of 43 tests is unchanged); the lint runs in CI, not in
a campaign, and tests/ are in no fingerprint.
This commit is contained in:
ScottW514
2026-10-16 23:43:23 -04:00
parent c717ecbcce
commit 2af9b0277f
2 changed files with 23 additions and 18 deletions
+19 -15
View File
@@ -577,12 +577,13 @@ def workflow_steps(text):
def _on_every_run(step):
"""Whether a step runs on every run of its workflow and its failure
fails the run: neither it nor its job carries an `if:` other than
`true`, or a `continue-on-error:` other than `false`. A step that
runs only under a condition, or whose failure the run tolerates,
proves nothing about what it runs, and neither does a step of a
workflow with a key the lint cannot read ("unread")."""
"""Whether the lint counts a step as one that runs on every run of
its workflow and fails the run when it fails: neither the step nor
its job carries an `if:` other than the literal `true` or a
`continue-on-error:` other than the literal `false`, and the
workflow has no key the lint cannot read ("unread"). The lint
evaluates no condition, so a step under `always()` or `success()`
counts as no step too."""
if step.get("unread"):
return False
for d in (step, step.get("job") or {}):
@@ -708,10 +709,11 @@ def workflow_runs(steps, test_path):
(tests.test_x, tests.test_x.Case.test_one); unittest discover from the
test's own directory with a pattern its name matches; pytest on the
test or its own directory. An argument to anything else (echo, a build,
an install) does not run the test. Only a step that runs on every run of
the workflow, and that fails the run when it fails, counts: a step under
an `if:` other than true, or with a `continue-on-error:` other than
false, on the step or on its job, runs nothing."""
an install) does not run the test. Only a step that _on_every_run
accepts counts: the lint evaluates no condition, so a step under an
`if:` other than the literal true, or with a `continue-on-error:`
other than the literal false, on the step or on its job, counts as
no step."""
full = posixpath.normpath(test_path)
stem, ext = posixpath.splitext(posixpath.basename(full))
compiled = ext in (".c", ".cc", ".cpp")
@@ -757,10 +759,12 @@ def host_row_problems(manifest, host=HOST_TESTED, root=REPO_ROOT, sources=SOURCE
"""HOST_TESTED rows that prove nothing: a glob that selects no
behavioral file of its component (the same defect as an empty covers
entry), a host test or a workflow that does not exist, a workflow that
cannot be read where it should be, one that runs on no push or pull
request (a dispatch, a call or a schedule runs on no change), one that
does not check out the test's repository, or one with no step that
runs the test on every run (workflow_runs). Whether a
cannot be read where it should be, one whose own `on:` names neither
push nor pull_request as the lint reads it (workflow_triggers: a
dispatch, a call or a schedule alone, a call not followed to the
workflow that calls it, and a flow mapping, which names no event),
one that does not check out the test's repository, or one with no
step that runs the test on every run (workflow_runs). Whether a
workflow runs its test is not checked where it cannot be read (see
read_source). Returns [(component, glob, host test, why)]."""
out = []
@@ -779,7 +783,7 @@ def host_row_problems(manifest, host=HOST_TESTED, root=REPO_ROOT, sources=SOURCE
if text is None:
continue
if not workflow_triggers(text) & {"push", "pull_request"}:
out.append((comp, pat, ref, "%s runs on no push or pull request" % ci))
out.append((comp, pat, ref, "%s: the lint reads no push or pull_request in its own on:" % ci))
continue
steps = workflow_steps(text)
test_repo, _sep, test_path = ref.partition(":")