From b5ebf94d84c3c4f3595b051b5c132bd06eb8fb8d Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 1 Jun 2026 19:35:39 +0100 Subject: [PATCH] fix(rust-ci-reusable): wrap bare job-level if: in \${{ }} so GH Actions parses (fixes #322) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GH Actions silently fails to parse the entire caller workflow when the reusable's job-level \`if:\` is a bare expression containing \`hashFiles(format('{0}/...', inputs.X))\`. The parse failure shows up estate-wide as 0s-duration "completed failure" runs since 2026-05-26 across 43+ callers, with the caller's workflow name reported as the path (\`.github/workflows/rust-ci.yml\`) instead of the YAML \`name:\` field — GitHub's tell-tale "workflow file issue". The audit and coverage jobs (lines 187, 215) already used \`\${{ ... }}\` wrapping and parsed cleanly. The check (109) and test (149) jobs used the bare form because, viewed in isolation, the YAML spec permits both. Empirically confirmed via 5-commit experiment on panic-attack#95: caller @cc5a372a → fail (name=path) rust-ci-reusable.yml caller @main → fail (name=path) rust-ci-reusable.yml caller w/governance.yml shape → fail (name=path) rust-ci-reusable.yml caller pointing at governance-reusable → PASS (name="Rust CI") caller verbatim clone of governance.yml → PASS Only the swap to governance-reusable.yml made the parse succeed → the bug is in rust-ci-reusable.yml specifically. The only structural diff between governance-reusable.yml and rust-ci-reusable.yml in the \`if:\` shape is exactly this bare-vs-wrapped split, and the bare lines in rust-ci-reusable.yml had a \`format()\` + \`inputs.X\` substitution that GH's expression parser rejects at job-level without the \`\${{ }}\` hint. Closes hyperpolymath/standards#322. Falsifies hypotheses 1+2+3 from the issue (caller structure, SHA resolution, workflow_id cache); root cause is hypothesis 4 (bare \`if:\` with \`hashFiles(format(inputs.X))\` at job level). Verified locally: - yamllint clean - yaml.safe_load parses both pre- and post-fix - the experiment branch panic-attack#95 last commit (governance-shape pointing at governance-reusable.yml) had name='Rust CI' parsed correctly Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/rust-ci-reusable.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust-ci-reusable.yml b/.github/workflows/rust-ci-reusable.yml index 34614839..8032f1a2 100644 --- a/.github/workflows/rust-ci-reusable.yml +++ b/.github/workflows/rust-ci-reusable.yml @@ -106,7 +106,7 @@ jobs: check: name: Cargo check + clippy + fmt runs-on: ${{ inputs.runs-on }} - if: hashFiles(format('{0}/Cargo.toml', inputs.working_directory)) != '' + if: ${{ hashFiles(format('{0}/Cargo.toml', inputs.working_directory)) != '' }} permissions: contents: read defaults: @@ -146,7 +146,7 @@ jobs: name: Cargo test runs-on: ${{ inputs.runs-on }} needs: check - if: hashFiles(format('{0}/Cargo.toml', inputs.working_directory)) != '' + if: ${{ hashFiles(format('{0}/Cargo.toml', inputs.working_directory)) != '' }} permissions: contents: read defaults: