-
-
Notifications
You must be signed in to change notification settings - Fork 0
64 lines (58 loc) · 2.5 KB
/
Copy pathlock-sync-gate.yml
File metadata and controls
64 lines (58 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# SPDX-License-Identifier: MPL-2.0
name: Lock Sync Gate
# Fails any pull request whose .github/workflows/actions.lock has 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." A single grouped Dependabot bump can take out most
# of a repository's CI that way, because Dependabot rewrites `uses:` refs in the
# YAML and cannot touch the lockfile. Measured across 200 repositories on
# 2026-09-22: 39 had silently dead CI from exactly this cause.
# See hyperpolymath/standards#968.
#
# This workflow deliberately carries NO `uses:` of its own. It checks out by
# calling git in a `run:` step instead of using actions/checkout, so it has no
# lockfile entry to go stale and is structurally immune to the very failure it
# detects. Do not add a `uses:` to this file.
#
# There is also no `paths:` filter, on purpose: a filtered workflow never
# reports on pull requests that miss the filter, which deadlocks any branch
# ruleset that requires this check.
on:
workflow_dispatch:
pull_request:
push:
branches: [main]
permissions:
contents: read
concurrency:
group: lock-sync-gate-${{ github.ref }}
cancel-in-progress: true
jobs:
lock-sync:
name: actions.lock is in sync with the workflow YAML
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check out without actions/checkout
env:
REPO: ${{ github.repository }}
SHA: ${{ github.event.pull_request.head.sha || github.sha }}
TOKEN: ${{ github.token }}
run: |
set -euo pipefail
# Authenticate the fetch. An anonymous clone works only for public
# repositories; this gate must also run on private ones. The header
# form is used rather than a token in the remote URL so the
# credential is never written into .git/config.
AUTH="AUTHORIZATION: basic $(printf 'x-access-token:%s' "${TOKEN}" | base64 -w0)"
git init -q .
git remote add origin "https://github.com/${REPO}.git"
git -c http.extraheader="${AUTH}" fetch -q --depth 1 origin "${SHA}"
git checkout -q FETCH_HEAD
echo "checked out ${SHA}"
- name: Verify lockfile synchronisation
run: |
set -euo pipefail
test -x scripts/check-lock-sync.sh \
|| { echo "::error::scripts/check-lock-sync.sh missing or not executable"; exit 1; }
./scripts/check-lock-sync.sh