Skip to content

chore: restore shared ancestry between dev and main #986

chore: restore shared ancestry between dev and main

chore: restore shared ancestry between dev and main #986

name: Repo Health
on:
pull_request_target:
branches: [dev]
types: [opened, synchronize, reopened]
# pull_request_target gives write token even for fork PRs.
# SAFETY: We check out the BASE branch (trusted scripts) and fetch the PR
# head only as a git ref for analysis — no PR-supplied code is executed.
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
# ─── Bootstrap Protection (BLOCKING) ────────────────────────────────
bootstrap-protection:
name: Bootstrap Protection
runs-on: ubuntu-latest
timeout-minutes: 3
if: github.actor != 'dependabot[bot]'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
with:
sparse-checkout: |
scripts/check-bootstrap-deps.mjs
sparse-checkout-cone-mode: false
- name: Fetch PR head (data only — not executed)
run: git fetch origin ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #v6
with:
node-version: '22'
- name: Check bootstrap dependencies
id: bootstrap
run: |
set +e
OUTPUT=$(node scripts/check-bootstrap-deps.mjs --ref ${{ github.event.pull_request.head.sha }} 2>&1)
EXIT_CODE=$?
echo "$OUTPUT"
echo "result<<EOF" >> "$GITHUB_OUTPUT"
echo "$OUTPUT" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
echo "exit_code=$EXIT_CODE" >> "$GITHUB_OUTPUT"
exit $EXIT_CODE
# ─── Diff Size Guard (WARNING) ─────────────────────────────────────
diff-guard:
name: Diff Size Guard
runs-on: ubuntu-latest
timeout-minutes: 2
if: github.actor != 'dependabot[bot]'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
with:
fetch-depth: 0
- name: Fetch PR head (data only — not executed)
run: git fetch origin ${{ github.event.pull_request.head.sha }}
- name: Check for likely contamination
run: |
git fetch origin dev --quiet
FILE_COUNT=$(git diff --name-only origin/dev...${{ github.event.pull_request.head.sha }} | wc -l)
COMMIT_COUNT=$(git rev-list --count origin/dev..${{ github.event.pull_request.head.sha }})
# Heuristic: if a single-commit PR touches more than 30 files, it's likely contaminated
if [ "$COMMIT_COUNT" -le 2 ] && [ "$FILE_COUNT" -gt 30 ]; then
echo "::warning::⚠️ This PR has $COMMIT_COUNT commit(s) but touches $FILE_COUNT files."
echo "::warning::This may indicate branch contamination from broad staging (--all or .) on a stale branch."
echo "::warning::Please verify all changed files are intentional: git diff --name-only origin/dev...${{ github.event.pull_request.head.sha }}"
else
echo "✅ Diff looks proportional: $COMMIT_COUNT commit(s), $FILE_COUNT file(s)."
fi
# ─── Squad File Leakage (WARNING) ───────────────────────────────────
squad-leakage:
name: Squad File Leakage
runs-on: ubuntu-latest
timeout-minutes: 3
if: github.actor != 'dependabot[bot]'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
with:
fetch-depth: 0
- name: Fetch PR head (data only — not executed)
run: git fetch origin ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #v6
with:
node-version: '22'
- name: Detect .squad/ leakage
id: leakage
run: |
git fetch origin dev --quiet
OUTPUT=$(node scripts/check-squad-leakage.mjs origin/dev ${{ github.event.pull_request.head.sha }} 2>&1)
echo "$OUTPUT"
echo "result<<EOF" >> "$GITHUB_OUTPUT"
echo "$OUTPUT" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: Comment on leakage
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 #v9
with:
script: |
const { run } = await import(`${process.env.GITHUB_WORKSPACE}/scripts/repo-health-comment.mjs`);
await run({
github,
context,
output: `${{ steps.leakage.outputs.result }}`,
job: 'leakage',
});
# ─── Architectural Review (INFORMATIONAL) ───────────────────────────
architectural-review:
name: Architectural Review — Structure & Design Rules
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.actor != 'dependabot[bot]'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
with:
fetch-depth: 0
- name: Fetch PR head (data only — not executed)
run: git fetch origin ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #v6
with:
node-version: '22'
- name: Run architectural review
id: arch
run: |
git fetch origin dev --quiet
OUTPUT=$(node scripts/architectural-review.mjs origin/dev ${{ github.event.pull_request.head.sha }} 2>&1)
echo "$OUTPUT"
echo "result<<EOF" >> "$GITHUB_OUTPUT"
echo "$OUTPUT" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: Comment on findings
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 #v9
with:
script: |
const { run } = await import(`${process.env.GITHUB_WORKSPACE}/scripts/repo-health-comment.mjs`);
await run({
github,
context,
output: `${{ steps.arch.outputs.result }}`,
job: 'architectural',
});
# ─── Security Review (INFORMATIONAL) ────────────────────────────────
security-review:
name: Security Review — Permissions & Secrets
runs-on: ubuntu-latest
timeout-minutes: 5
if: github.actor != 'dependabot[bot]'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
with:
fetch-depth: 0
- name: Fetch PR head (data only — not executed)
run: git fetch origin ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 #v6
with:
node-version: '22'
- name: Run security review
id: security
run: |
git fetch origin dev --quiet
OUTPUT=$(node scripts/security-review.mjs origin/dev ${{ github.event.pull_request.head.sha }} 2>&1)
echo "$OUTPUT"
echo "result<<EOF" >> "$GITHUB_OUTPUT"
echo "$OUTPUT" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: Comment on findings
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 #v9
with:
script: |
const { run } = await import(`${process.env.GITHUB_WORKSPACE}/scripts/repo-health-comment.mjs`);
await run({
github,
context,
output: `${{ steps.security.outputs.result }}`,
job: 'security',
});