Repository navigation
Ci/pr size check - #338
Ci/pr size check#338
Conversation
Add a reusable admin-pr-size workflow that fails a pull request when it changes more than `max_lines` lines (additions + deletions, default 600), counted with `git diff --numstat` against the merge base. An `ignore` input takes git glob pathspecs whose changes are not counted; stitch ignores uv.lock and package-lock.json. Release promotions and backmerges (PRs whose source branch is main, next, or production) are exempt, and the check only runs on pull_request events. It is not yet a required status check. Document the limit in CONTRIBUTING.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A PR from a fork's `main` (the usual way external contributors submit, per CONTRIBUTING.md) matched the release/backmerge exemption because it only compared the source branch name. Also require the head repository to be this repository. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use origin/$BASE_REF instead of the event's base SHA as the left side of the three-dot diff. If the base SHA predates a merge of the target into the PR branch, the merge base falls back to it and the target's own changes get counted (replaying #282 this way gives 7040 lines instead of 650). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the release/backmerge branch list out of the reusable workflow and into admin.yml, next to the ignore list, so all of stitch's PR size policy lives in the caller. The input is a JSON array because the job-level `if:` can only read lists via fromJSON(); it defaults to no exemptions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`max_lines` is a number input, so decimals are accepted, but the `-gt` comparison is integer-only. Inside an `if`, its error status was treated as false and the check passed (e.g. 1014 lines vs max_lines=600.5). Validate it up front and fail with a clear message instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CD summary
|
| service | url | fqdn |
|---|---|---|
| api | open | pr-0338-api.purplegrass-c07d0a94.westus2.azurecontainerapps.io |
| frontend | https://witty-mushroom-017a3dc1e-338.westus2.1.azurestaticapps.net | |
| stitch-llm | open | pr-0338-llm.purplegrass-c07d0a94.westus2.azurecontainerapps.io |
Database (1)
| db_name | postgres_host | postgres_port | postgres_db |
|---|---|---|---|
| pr_0338 | stitch-dev.postgres.database.azure.com |
5432 |
pr_0338 |
Jobs (2)
| job | image | postgres_db | api_url | auth_mode |
|---|---|---|---|---|
| db-migrations | ghcr.io/rmi/stitch-api:pr-0338@sha256:fc4bc9ad3b229857d3e4ec92580cec7b362761d9932d20f402b07e1f74010390 |
pr_0338 |
||
| seed | ghcr.io/rmi/stitch-seed:pr-0338@sha256:4eb21dabaf03de8d1db2eeb375dfa911371fdbb5835cc6361e095ccb93b35618 |
https://pr-0338-api.purplegrass-c07d0a94.westus2.azurecontainerapps.io/api/v1 |
stitch-client-bearer-token |
Images (3)
| build_time | commit_time | git_sha | image | image_digest |
|---|---|---|---|---|
| 2026-10-20T14:50:00Z | 2026-10-20T14:49:40Z | 5ce8055 | ghcr.io/rmi/stitch-api:pr-0338 |
ghcr.io/rmi/stitch-api:pr-0338@sha256:fc4bc9ad3b229857d3e4ec92580cec7b362761d9932d20f402b07e1f74010390 |
| 2026-10-20T14:49:58Z | 2026-10-20T14:49:40Z | 5ce8055 | ghcr.io/rmi/stitch-seed:pr-0338 |
ghcr.io/rmi/stitch-seed:pr-0338@sha256:4eb21dabaf03de8d1db2eeb375dfa911371fdbb5835cc6361e095ccb93b35618 |
| 2026-10-20T14:50:01Z | 2026-10-20T14:49:40Z | 5ce8055 | ghcr.io/rmi/stitch-stitch-llm:pr-0338 |
ghcr.io/rmi/stitch-stitch-llm:pr-0338@sha256:5601053519298cc6ea47ad2b0268a04a7801e9428361cd00ec9c35564878a3c6 |
CD summary
|
| service | url | fqdn |
|---|---|---|
| api | open | pr-0338-api.purplegrass-c07d0a94.westus2.azurecontainerapps.io |
| frontend | https://witty-mushroom-017a3dc1e-338.westus2.1.azurestaticapps.net | |
| stitch-llm | open | pr-0338-llm.purplegrass-c07d0a94.westus2.azurecontainerapps.io |
Database (1)
| db_name | postgres_host | postgres_port | postgres_db |
|---|---|---|---|
| pr_0338 | stitch-dev.postgres.database.azure.com |
5432 |
pr_0338 |
Jobs (1)
| job | image | postgres_db |
|---|---|---|
| db-migrations | ghcr.io/rmi/stitch-api:pr-0338@sha256:89b3f6bc5fa5c1dcec2b57bb2f62880554e1f8bb23c5f25f123e7568e99fec97 |
pr_0338 |
Images (3)
| build_time | commit_time | git_sha | image | image_digest |
|---|---|---|---|---|
| 2026-10-20T14:56:30Z | 2026-10-20T14:56:04Z | f3a67e9 | ghcr.io/rmi/stitch-api:pr-0338 |
ghcr.io/rmi/stitch-api:pr-0338@sha256:89b3f6bc5fa5c1dcec2b57bb2f62880554e1f8bb23c5f25f123e7568e99fec97 |
| 2026-10-20T14:56:53Z | 2026-10-20T14:56:04Z | f3a67e9 | ghcr.io/rmi/stitch-seed:pr-0338 |
ghcr.io/rmi/stitch-seed:pr-0338@sha256:895add6c38e9298b5575d58c1146eb3d6a9e8e7b5c88c3e8a556e99300458516 |
| 2026-10-20T14:56:28Z | 2026-10-20T14:56:04Z | f3a67e9 | ghcr.io/rmi/stitch-stitch-llm:pr-0338 |
ghcr.io/rmi/stitch-stitch-llm:pr-0338@sha256:f3b60b7d5337dc6ec19436a353cc741eec2e7cb252b6e25556bad54fe138dc35 |
There was a problem hiding this comment.
🟡 Changes recommended
Two moderate findings remain regarding exemption input validation and the check being modifiable by the PR itself.
1 open issue
What changed in this PR
Adds a reusable Admin CI check limiting pull requests to 600 changed lines, with lockfile exclusions and branch exemptions.
Changes:
- Documents PR size policy.
- Integrates the check into Admin Checks.
- Adds diff-based counting, validation, and exemptions.
| File | Description |
|---|---|
CONTRIBUTING.md |
Documents PR size limits and exemptions. |
.github/workflows/admin.yml |
Configures the PR-size check. |
.github/workflows/admin-pr-size.yml |
Implements validation, exemptions, and line counting. |
Review effort: Lite
CD summary
|
| service | url | fqdn |
|---|---|---|
| api | open | pr-0338-api.purplegrass-c07d0a94.westus2.azurecontainerapps.io |
| frontend | https://witty-mushroom-017a3dc1e-338.westus2.1.azurestaticapps.net | |
| stitch-llm | open | pr-0338-llm.purplegrass-c07d0a94.westus2.azurecontainerapps.io |
Database (1)
| db_name | postgres_host | postgres_port | postgres_db |
|---|---|---|---|
| pr_0338 | stitch-dev.postgres.database.azure.com |
5432 |
pr_0338 |
Jobs (1)
| job | image | postgres_db |
|---|---|---|
| db-migrations | ghcr.io/rmi/stitch-api:pr-0338@sha256:51289a67187091beab3a541fadbd9efb2f98b8e71318e1042ad06dd77cf1e934 |
pr_0338 |
Images (3)
| build_time | commit_time | git_sha | image | image_digest |
|---|---|---|---|---|
| 2026-10-20T15:08:07Z | 2026-10-20T15:07:42Z | b86411a | ghcr.io/rmi/stitch-api:pr-0338 |
ghcr.io/rmi/stitch-api:pr-0338@sha256:51289a67187091beab3a541fadbd9efb2f98b8e71318e1042ad06dd77cf1e934 |
| 2026-10-20T15:08:01Z | 2026-10-20T15:07:42Z | b86411a | ghcr.io/rmi/stitch-seed:pr-0338 |
ghcr.io/rmi/stitch-seed:pr-0338@sha256:3c29aa13d94b7ed4f779d37686dc414ce82579ba5a53cdf8668aab1176174426 |
| 2026-10-20T15:08:01Z | 2026-10-20T15:07:42Z | b86411a | ghcr.io/rmi/stitch-stitch-llm:pr-0338 |
ghcr.io/rmi/stitch-stitch-llm:pr-0338@sha256:72501767a1efe88963cee19b08a2d51feb97d91c3262a3fd5bb96906c297f673 |
The job-level `if:` used contains(fromJSON(...)), which matches substrings if the input isn't an array and ignores case, so a same-repo branch named `Main` or `NEXT` was exempt. Check the exemption in the bash step with an exact, case-sensitive match instead, and make exempt_head_branches newline-delimited like `ignore`. Exempt PRs now pass with a notice instead of being skipped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CD summary
|
| db_name | postgres_host | postgres_port | postgres_db |
|---|---|---|---|
| pr_0338 | stitch-dev.postgres.database.azure.com |
5432 |
pr_0338 |
Jobs (1)
| job | image | postgres_db |
|---|---|---|
| db-migrations | ghcr.io/rmi/stitch-api:pr-0338@sha256:c74266db14c72c08155b248a35a3e4d4d723f07bacef0e5c0f992ca76f47b18d |
pr_0338 |
Images (3)
| build_time | commit_time | git_sha | image | image_digest |
|---|---|---|---|---|
| 2026-10-20T15:34:09Z | 2026-10-20T15:33:49Z | 52748de | ghcr.io/rmi/stitch-api:pr-0338 |
ghcr.io/rmi/stitch-api:pr-0338@sha256:c74266db14c72c08155b248a35a3e4d4d723f07bacef0e5c0f992ca76f47b18d |
| 2026-10-20T15:34:08Z | 2026-10-20T15:33:49Z | 52748de | ghcr.io/rmi/stitch-seed:pr-0338 |
ghcr.io/rmi/stitch-seed:pr-0338@sha256:6e957368ca5b5a45800fa19924ce735c0dd910ef969ba3e3f1f8e9b0cf739cc3 |
| 2026-10-20T15:34:11Z | 2026-10-20T15:33:49Z | 52748de | ghcr.io/rmi/stitch-stitch-llm:pr-0338 |
ghcr.io/rmi/stitch-stitch-llm:pr-0338@sha256:e4a7c61c70954a1ba3a7341731041fff8c2275218cb5a1648b1787de6dceb79a |
|
I also just realized that I'd absolutely use this locally during development. I think Claude could also make some great use of it as a halting condition and/or warning. It's a strong signal that the workstream might be going in an undesirable direction, especially if it's run early in implementation and there's a lot left to change. It could as a bit of a self-check that's run periodically by the agent, and if it fails, the agent knows to stop and discuss the plan/design with the user. Or could be use in a loop to keep tests passing while reducing change size. |
Hmm. one of the things that I was back-and-forthing with myself with on this was to pull the inline bash script out to a separate file. But that sounds useful so that we could invoke it separately in local dev cycles |

Adds a CI check to the "Admin" family to check that PRs are smallish (currently 600 LoC changed/added/removed). The bulk of this is in a bash script inlined in the workflow file (should be extracted if we move this over to
RMI/actions), which has some modest hardening (such as checking that line limit is an integer, or failing if the exemptions are malformed).Some neat features:
HEADbranches:next,production, so that releases and backmerges, which are gong to be bigger than a single PR's worthWhat
Adds a Check PR size job to Admin Checks. It fails a PR that changes more than 600 lines (additions + deletions), so oversized PRs get split before they reach review.
How it works
admin-pr-size.yml, called fromadmin.yml, with three inputs:max_lines: default 600. Must be a whole number; anything else fails the check with a clear error.ignore: newline-delimited git glob pathspecs that aren't counted. Stitch passes**/uv.lockand**/package-lock.json.exempt_head_branches: JSON array of source branches in this repo whose PRs skip the check. Stitch passesmain,next,production(release promotions and backmerges).git diff --numstatfrom the merge base with the target branch's current tip to the PR head. This matches GitHub's "Files changed" view.git diff --statis printed to the job log so authors can see where the lines are.pull_requestevents. It's skipped on push/schedule/dispatch runs of Admin Checks. Fork PRs are never exempt, even from a branch namedmain.Impact on recent PRs
Of the last ~48 non-release PRs, 7 would have failed: #316, #293, #283, #282, #277, #276, #267. Dependabot PRs pass because lockfiles are ignored (#270: 607 raw lines → 16 counted).
Not in this PR
Check PR size / Check PR sizetogitflow-main.overlay.jsonand update the live ruleset at the same time.pull_requestevent types.Testing
mainpartway through: 650 against the target's tip (matches GitHub), versus 7040 if diffed from the pre-merge base.max_linesvalidation:600.5,-1, empty,abcand" 600"fail with an error. Before the fix,600.5silently passed a 1014-line PR.on:truthy warnings.if:(exemption + same-repo condition). This PR's own run covers the non-exempt path. The exempt path will run on the next release PR.AI assistance
Claude Code drafted the workflow and docs, ran the local replays above, and reviewed the branch. I made the design decisions (fail with no override, configurable ignore list, release/backmerge exemption, not required yet), simplified the script and messages, and reviewed each change before committing.
🤖 Generated with Claude Code