From b7b2bd4b5d62a5037321a23104c40f372208a123 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:45 +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/cflite_batch.yml | 1 - .github/workflows/cflite_pr.yml | 1 - .github/workflows/codeql.yml | 1 - .github/workflows/makefile-blocker.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/.github/workflows/cflite_batch.yml b/.github/workflows/cflite_batch.yml index 3476506..e4bd876 100644 --- a/.github/workflows/cflite_batch.yml +++ b/.github/workflows/cflite_batch.yml @@ -4,7 +4,6 @@ on: schedule: - cron: '0 0 * * 0' # Weekly permissions: read-all - actions: read jobs: fuzz: runs-on: ubuntu-latest diff --git a/.github/workflows/cflite_pr.yml b/.github/workflows/cflite_pr.yml index fa0efaa..2143e21 100644 --- a/.github/workflows/cflite_pr.yml +++ b/.github/workflows/cflite_pr.yml @@ -7,7 +7,6 @@ on: - 'Cargo.toml' - 'Cargo.lock' permissions: read-all - actions: read jobs: fuzz: runs-on: ubuntu-latest diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a425c69..5c730d5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,7 +8,6 @@ on: schedule: - cron: '0 6 1 * *' permissions: read-all - actions: read jobs: analyze: runs-on: ubuntu-latest diff --git a/.github/workflows/makefile-blocker.yml b/.github/workflows/makefile-blocker.yml index 819e82c..8ea21b9 100644 --- a/.github/workflows/makefile-blocker.yml +++ b/.github/workflows/makefile-blocker.yml @@ -11,7 +11,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all - actions: read jobs: check: runs-on: ubuntu-latest