Skip to content

Commit 81bb2ae

Browse files
kim-emclaude
andcommitted
ci: block merging PRs that increase technical debt unless reviewed
The existing technical debt metrics script already reports changes in a PR summary comment. This PR makes it a merge gate: when debt increases, a `blocked-by-increases-technical-debt` label blocks bors. A reviewer can add `allow-increases-technical-debt` to unblock. The detection uses fail-closed logic: we grep for the safe patterns ("Decrease" / "No changes") and treat everything else as an increase, so a wording change in the external mathlib-ci script adds the label rather than silently skipping it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b7fcb00 commit 81bb2ae

2 files changed

Lines changed: 76 additions & 2 deletions

File tree

.github/workflows/PR_summary.yml

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: Post PR summary comment
22

33
on:
44
pull_request_target:
5+
types: [opened, synchronize, reopened, labeled, unlabeled]
56

67
# Limit permissions for GITHUB_TOKEN for the entire workflow
78
permissions:
@@ -13,7 +14,10 @@ jobs:
1314
build:
1415
name: "post-or-update-summary-comment"
1516
runs-on: ubuntu-latest
16-
if: github.repository == 'leanprover-community/mathlib4'
17+
if: >-
18+
github.repository == 'leanprover-community/mathlib4' &&
19+
github.event.action != 'labeled' &&
20+
github.event.action != 'unlabeled'
1721
1822
steps:
1923
- name: Checkout code
@@ -222,6 +226,16 @@ jobs:
222226
echo "Compute technical debt changes"
223227
techDebtVar="$("${CI_SCRIPTS_DIR}/reporting/technical-debt-metrics.sh" pr_summary)"
224228
229+
# If technical debt did NOT increase, remove the label; otherwise add it.
230+
# We test for the *safe* patterns rather than the *unsafe* one so that if
231+
# mathlib-ci changes the script's output wording we fail closed (label added)
232+
# rather than open (label silently not added).
233+
if printf '%s' "${techDebtVar}" | grep -qE 'Decrease in tech debt:|No changes to technical debt\.'; then
234+
gh pr edit "${PR}" --remove-label increases-technical-debt
235+
else
236+
gh pr edit "${PR}" --add-label increases-technical-debt
237+
fi
238+
225239
echo "Compute documentation reminder"
226240
workflowFilesChanged="$(grep '^\.github/workflows/' changed_files.txt || true)"
227241
if [ -n "${workflowFilesChanged}" ]
@@ -293,3 +307,63 @@ jobs:
293307
--url https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/file-removed \
294308
--header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}'
295309
fi
310+
311+
# This job gates merging via the `blocked-by-increases-technical-debt` label
312+
# in bors.toml.
313+
#
314+
# Why a separate label? Bors's block_labels has no conditional logic, so we
315+
# need a derived label to express "increases-technical-debt AND NOT
316+
# allow-increases-technical-debt". See the analogous comment on
317+
# check-large-import (in a companion PR) for the full rationale.
318+
#
319+
# Three labels, each managed by exactly one actor:
320+
# - `increases-technical-debt` — managed by the `build` job
321+
# - `blocked-by-increases-technical-debt` — managed by this job
322+
# - `allow-increases-technical-debt` — managed by the reviewer
323+
check-technical-debt:
324+
name: "Check technical debt"
325+
needs: build
326+
runs-on: ubuntu-latest
327+
if: always() && github.repository == 'leanprover-community/mathlib4'
328+
329+
steps:
330+
- name: Check for increases-technical-debt label
331+
env:
332+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
333+
PR_NUMBER: ${{ github.event.pull_request.number }}
334+
REPO: ${{ github.repository }}
335+
run: |
336+
labels=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json labels --jq '.labels[].name')
337+
338+
has_increases=false
339+
has_allow=false
340+
341+
if printf '%s\n' "$labels" | grep -qx "increases-technical-debt"; then
342+
has_increases=true
343+
fi
344+
345+
if printf '%s\n' "$labels" | grep -qx "allow-increases-technical-debt"; then
346+
has_allow=true
347+
fi
348+
349+
if [ "$has_increases" = true ] && [ "$has_allow" = false ]; then
350+
gh pr edit "$PR_NUMBER" --repo "$REPO" --add-label blocked-by-increases-technical-debt
351+
echo "::error::This PR increases technical debt. Add the 'allow-increases-technical-debt' label after review to unblock."
352+
echo ""
353+
echo "This PR has the 'increases-technical-debt' label, indicating that it"
354+
echo "increases one or more technical debt metrics."
355+
echo ""
356+
echo "To unblock this PR, a reviewer should:"
357+
echo " 1. Check the PR summary comment for the technical debt changes."
358+
echo " 2. Consider whether the increase can be avoided."
359+
echo " 3. If the increase is acceptable, add the 'allow-increases-technical-debt' label."
360+
echo ""
361+
echo "Note: not all technical debt increases are avoidable. If you believe this"
362+
echo "check is too aggressive, please report it on the mathlib4 Zulip channel:"
363+
echo "https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/increases-technical-debt.20label"
364+
exit 1
365+
else
366+
gh pr edit "$PR_NUMBER" --repo "$REPO" --remove-label blocked-by-increases-technical-debt
367+
fi
368+
369+
echo "Technical debt check passed."

bors.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
status = ["ci (staging) / Build", "ci (staging) / Lint style", "ci (staging) / Post-Build Step", "ci (staging) / Post-CI job"]
22
use_squash_merge = true
33
timeout_sec = 7200
4-
block_labels = ["WIP", "blocked-by-other-PR", "merge-conflict", "awaiting-CI"]
4+
block_labels = ["WIP", "blocked-by-other-PR", "merge-conflict", "awaiting-CI", "blocked-by-increases-technical-debt"]
55
delete_merged_branches = true
66
update_base_for_deletes = true
77
cut_body_after = "\n---"

0 commit comments

Comments
 (0)