Skip to content

Merge master back into dev after 1.0.0-beta.52 #1307

Merge master back into dev after 1.0.0-beta.52

Merge master back into dev after 1.0.0-beta.52 #1307

Workflow file for this run

name: Gate integrity
# CLASS DEFECT fix (tsk-o2vhcq): every gate workflow triggered on
# `pull_request` checks out the PR MERGE REF (actions/checkout's default on
# that event) and runs its checker script FROM THAT CHECKOUT. A PR can
# therefore edit its own checker (and its own workflow YAML -- `pull_request`
# runs the workflow file from the merge ref too) to always-exit-0 and
# green-pass the very check that is supposed to gate it.
#
# This workflow breaks that loop:
# * It triggers on `pull_request_target`, so the workflow file AND this
# script are resolved from the BASE branch, never from the PR head. A PR
# editing this workflow or its checker is inert here.
# * It does NOT check out or execute PR code. `actions/checkout` is pinned
# to `ref: ${{ github.base_ref }}` (the base branch) -- the PR merge ref is
# deliberately never fetched. The base-ref checker then inspects the PR diff
# via the GitHub REST API only.
# * It fails any PR whose diff touches a protected gate file -- the
# PROTECTED_PREFIXES set in scripts/check_gate_integrity.py (workflows,
# gate checkers, gate data and test config) -- unless the PR carries the
# human-set `gate-integrity-allow` label. The checker is the single
# source of truth for the protected set; this comment deliberately does
# not enumerate it.
#
# Token permissions are minimal (contents: read, pull-requests: read); the
# GITHUB_TOKEN never acquires write scope here, and PR-controlled code is never
# run, so a malicious PR cannot escalate through this job.
# `edited` is not cosmetic here. Retargeting a PR's base branch fires `edited`
# (carrying `changes.base`) and no other activity type, so without it this gate
# never re-inspects the new base..head file list. `dev` runs loose branch
# protection (`strict: false`), so the head SHA does not move on a retarget and
# nothing else forces a re-run -- a PASS earned against one base would keep
# satisfying the required check against another whose diff touches protected
# gate files. `edited` also fires on title/body edits; re-running is cheap and
# read-only, so the gate takes the extra runs rather than the bypass.
on:
pull_request_target:
types: [opened, synchronize, reopened, edited, labeled, unlabeled]
branches: [master, dev]
permissions:
contents: read
pull-requests: read
jobs:
gate-integrity:
name: Gate integrity
runs-on: ubuntu-latest
# permissions are set at the workflow root above; restated here so the
# job is safe even if copy-pasted into another workflow.
permissions:
contents: read
pull-requests: read
steps:
- name: Resolve PR base ref
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
base=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }} --jq .base.ref)
if [ -z "$base" ]; then
echo "::error::Resolved base ref is empty" >&2
exit 1
fi
echo "BASE_REF=$base" >> $GITHUB_ENV
# On `pull_request_target` checkout defaults to the base branch,
# not the merge ref. Pinning `ref` to base_ref guarantees
# the base-ref checker (and this workflow) execute from base.
# The resolve step above sets BASE_REF to the PR's actual base
# branch via the GitHub API; github.base_ref is the fallback.
- uses: actions/checkout@v7
with:
ref: ${{ env.BASE_REF || github.base_ref }}
fetch-depth: 1
- uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Inspect PR diff via API for self-editing gates
# Fail closed on infrastructure errors (exit 2) so a transient API
# blip never reads as green -- see check_gate_integrity.EXIT_ERROR.
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
python scripts/check_gate_integrity.py "$PR_NUMBER"