Skip to content

ci(workflow): adopt hardened hypatia-scan from hyperpolymath/hypatia#237 (API-only retry) - #129

Closed
hyperpolymath wants to merge 1 commit into
mainfrom
ci/adopt-hardened-hypatia-scan-workflow-v2
Closed

hyperpolymath wants to merge 1 commit into
mainfrom
ci/adopt-hardened-hypatia-scan-workflow-v2

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Why a v2

Original PR #126 was reverted by #128 because a shallow clone caught gitbot-fleet mid-restructure and produced a commit treating 1777 files as deletions.

A local full-clone retry was attempted but failed: this repo contains files with : in their names (e.g. shared-context/findings/.../2026-02-14T00:00:00Z.json), which Windows filesystems can't materialise. git clone exits 128.

This v2 is created server-side via API (PUT /contents), which by definition can only change one file at a time. The diff is structurally guaranteed to be a single-file change.

Verify PR diff stats

Should be changedFiles: 1, +N -M on hypatia-scan.yml only. Sanity-checked: post-create tree has the same number of blobs as main's tree.



Replaces the local copy of `.github/workflows/hypatia-scan.yml` with the
canonical version from upstream main, fixing three issues:

1. `working-directory: ${{ env.HOME }}/hypatia` — env.HOME isn't a GHA
   context so the cd failed and the scanner was never built.
2. `hypatia-cli.sh scan .` without `--exit-zero` — scanner exit-1 on
   findings short-circuited the step under `set -e`.
3. No baseline gate — any pre-existing critical/high failed the build.

This re-do of the propagation is via API PUT /contents (created
server-side, single-file commit). The original PR #126 used a local
shallow clone that caught gitbot-fleet mid-restructure and committed
1777 files-as-deletions; reverted by #128. A local full-clone is also
impossible because some files in this repo have `:` in their names
(e.g. ISO-8601 timestamps) which Windows filesystems reject.

API commits are web-flow-style unsigned. The squash-merge on main will
produce a web-flow-signed commit that satisfies the required-signatures
ruleset.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 14, 2026
Workflow file was deleted from main; this commit restores the hardened
v2 workflow from PR #129 head branch directly into main via fresh PR.
File content identical to ci/adopt-hardened-hypatia-scan-workflow-v2.
hyperpolymath added a commit that referenced this pull request May 14, 2026
Workflow file was deleted from main; this commit restores the hardened
v2 workflow from PR #129 head branch directly into main via fresh PR.
File content identical to ci/adopt-hardened-hypatia-scan-workflow-v2.
@hyperpolymath

Copy link
Copy Markdown
Owner Author

Superseded by #142. The original head branch was based on a state where hypatia-scan.yml existed in main; main has since dropped that file (revert/pr-126-mass-deletion). #142 restores the identical hardened workflow content directly on top of current main.

@hyperpolymath
hyperpolymath deleted the ci/adopt-hardened-hypatia-scan-workflow-v2 branch May 14, 2026 20:59
hyperpolymath added a commit that referenced this pull request Sep 22, 2026
## What this fixes

`.github/workflows/actions.lock` had drifted from the workflow YAML.
That drift is
not cosmetic: **GitHub refuses such a run at startup, creating zero
jobs**, and
reports only *"This run likely failed because of a workflow file
issue."* Most of a
repository's CI can be silently dead for days without a single red tick,
because a
run that never starts posts no check.

Measured across the estate on 2026-09-22: **13 of 37** repositories
swept were in
this state.

## Why it happened here

GitHub's startup check compares the lockfile ref to the workflow's
`uses:` ref as a
**literal string**. `gh actions-lock` compares them by **resolved
commit**. The two
disagree whenever a lock entry names a tag that dereferences to exactly
the commit
the YAML pins — the tool prints `All N workflows valid` and GitHub still
kills the
run.

Proof, on `hyperpolymath/awesome-nickel/codeql.yml`:

| commit | YAML `uses:` | lock entry | literal match | outcome |
|---|---|---|---|---|
| `ad035f4e` (09-21) | `codeql-action/init@v4.38.0` |
`codeql-action@v4.38.0` | yes | ran |
| `9d83550d` (09-22) | `codeql-action/init@b96794f0…` |
`codeql-action@v4.38.0` | **no** | `startup_failure`, jobs=0 |

`v4.38.0` dereferences to `b96794f0…` — the *same commit* the YAML pins
— and the run
still died. A cross-workflow control at the same heads (`boj-build.yml`,
lock-matched)
was green, so the lock is not globally broken; the failure is scoped to
the one
workflow whose entry mismatches.

## What changed

- `.github/workflows/actions.lock` regenerated and made **transitively
closed**. A ref
named under `workflows:` or inside another record's nested `uses:` with
no top-level
`dependencies:` record is a dangling edge and kills the run at startup.
- **No workflow YAML was modified.** Only the lockfile changed, plus the
two new files
  below.
- `gh actions-lock` was run with `--no-migrate-local-actions`, which
prevents it
rewriting `uses: ./…` into `uses: $/…` — an invalid form that itself
causes startup
  death.

## The recurrence gate (the actual defect)

Regenerating alone is a one-week fix: Dependabot rewrites `uses:` refs
in the YAML on a
schedule and **cannot touch the lockfile**, so the repo re-breaks on the
next grouped
bump. This PR therefore also adds:

- `.github/workflows/lock-sync-gate.yml` — fails any PR whose lockfile
has drifted.
- `scripts/check-lock-sync.sh` — the check itself.

The gate deliberately carries **no `uses:` of its own** — it checks out
by calling `git`
in a `run:` step instead of `actions/checkout`, so it has no lockfile
entry to go stale
and is structurally immune to the very failure it detects. It also has
no `paths:`
filter, on purpose: a filtered workflow never reports on PRs that miss
the filter, which
would deadlock any branch ruleset requiring this check.

The gate hard-fails on desync. It is not `continue-on-error` and not a
`::warning::`,
which cannot fail a job.

### Note on `gh actions-lock --verify-local`

The gate does **not** call `gh actions-lock --verify-local`, which was
the originally
proposed mechanism. That tool is measured wrong in both directions: it
reports STALE on
job-level reusable-workflow refs it cannot parse (upstream #129 — 5
repos in this sweep
are false reds from exactly that), and it reports valid on the
tag-vs-SHA literal
mismatch above. `check-lock-sync.sh` tests literal-string equality,
which is what GitHub
actually enforces.

## Expected on this PR

Workflows that have not executed since the desync began will run here
for the first
time, and some may go red for reasons unrelated to this change. Per the
estate stopping
rule each becomes its own issue with acceptance criteria, not a blocker
on this PR.

Tracking: hyperpolymath/standards#968

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01X3hgXxWm6umMgZkjYyHnnm

---------

Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant