From a8eb7dfb400beff1af98e6b764cfc8daada1cb95 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 27 Jul 2026 14:37:12 +0100 Subject: [PATCH] fix(ci): move hashFiles() out of the job-level `if:` (2nd parse defect) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The duplicate `permissions:` key was necessary to fix but NOT sufficient: comprehensive-quality.yml still produced a run with ZERO jobs and no check run on the previous commit, i.e. it was still rejected at parse time. Second, independent defect, confirmed with actionlint: .github/workflows/comprehensive-quality.yml:156:9: calling function "hashFiles" is not allowed here. "hashFiles" is only available in "jobs..steps.*" contexts `hashFiles()` in a job-level `if:` makes Actions reject the WHOLE FILE, so none of the 11 jobs ever materialised. It was also semantically pointless there: at job level nothing is checked out yet, so the glob could never match. Moved the guard onto the two steps that actually need it, where it runs after checkout and is a valid context. Verified: `actionlint .github/workflows/*.yml` now reports zero expression or syntax errors across all 19 files; the only remaining output is shellcheck style/info (SC2086, SC2129, SC2035, ...) in unrelated workflows. Lesson for the estate: a strict YAML duplicate-key scan is NOT sufficient to prove an Actions workflow parses. YAML validity and Actions validity are different things — use actionlint. Co-Authored-By: Claude Opus 5 --- .github/workflows/comprehensive-quality.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/comprehensive-quality.yml b/.github/workflows/comprehensive-quality.yml index 5672d23..85ed387 100644 --- a/.github/workflows/comprehensive-quality.yml +++ b/.github/workflows/comprehensive-quality.yml @@ -153,15 +153,21 @@ jobs: accessibility: runs-on: ubuntu-latest timeout-minutes: 30 - if: hashFiles('**/*.html') != '' + # NOTE: `hashFiles()` is NOT available in a job-level `if:` — it is only + # valid in step-level contexts, and Actions rejects the WHOLE FILE at parse + # time if it appears here (zero jobs, no check run). It would also be + # meaningless at job level, since nothing is checked out yet. The guard + # therefore lives on the steps below, after checkout. steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4 - name: HTML accessibility check + if: hashFiles('**/*.html') != '' run: | echo "Checking for a11y attributes..." A11Y=$(grep -rE 'aria-|role=|alt=' --include="*.html" . 2>/dev/null | wc -l || echo "0") echo "A11y attributes found: $A11Y" - name: Lighthouse (if web project) + if: hashFiles('**/*.html') != '' run: | echo "Lighthouse would run on deployed URL"