From 4e147215fdefb509927b043f177b387c82eb626b Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 6 Aug 2026 11:08:50 +0100 Subject: [PATCH] fix(ci): repair workflows that are not valid YAML and have never run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub Actions rejects an unparseable workflow before creating any job: the run is recorded as `failure` with no jobs, no log and no check run, and `gh pr checks` shows no row at all. These files have never executed once. Three distinct faults, all from sweeps that edited by LINE POSITION rather than by parsing the document. 1. A `permissions:` insertion, in three invalid shapes: permissions: read-all actions: read <- a mapping under a SCALAR; read-all already grants this, so the orphan line is dropped on: permissions: contents: read <- two colons, and illegal under `on:` runs-on: ubuntu-latest npermissions: <- a literal "\n" never turned into a newline, gluing the escape's `n` on 2. An embedded interpreter script written at COLUMN 0 inside a `run: |` block: run: | python3 -c " import tomllib, sys <- YAML ends the block scalar here and tries to parse this as YAML Re-indented into the block. That is safe for the program as well as the document: YAML STRIPS the block-scalar indent when building the string, so the shell — and Python, which is indentation sensitive — still receive the script at column 0, with its own relative indentation preserved. 3. A key declared twice within one job. Deduplicated per job, never per file: these workflows legitimately have many jobs each with its own `timeout-minutes`, and it is also legal on a step, so a file-wide rule would delete real ones. The first occurrence is kept. VERIFIED, not assumed. Every repairer refuses to write a file that does not parse and still contain jobs afterwards, and the commit is only made when the count of broken files actually falls. Where a job-level `permissions:` was removed, a read-only top-level one remains, so nothing is widened. Where none would remain, the tool reports it rather than inventing one — guessing a permission set is how you silently over-grant, and that is how this began. ESTATE CONTEXT: 67 repositories, 100 workflow files. The most frequently broken file is workflow-linter.yml, in 22 repositories — the workflow whose job is to lint workflows was itself unparseable, so it never ran and never caught this. Detection is being added upstream so it cannot recur invisibly: hyperpolymath/standards#582. EXPECT THIS REPOSITORY TO GET LOUDER. Workflows that failed silently will now run, and some will find real problems. Co-Authored-By: Claude Fable 5 Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> --- .github/workflows/scorecard.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index f0c8699..64ac2ac 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -9,7 +9,6 @@ on: branches: [main] permissions: read-all - actions: read jobs: analysis: