Skip to content

Add GitHub pull request creation cap support - #111

Merged
Humbedooh merged 3 commits into
apache:mainfrom
potiuk:feature/pr-creation-cap
Sep 21, 2026
Merged

Humbedooh merged 3 commits into
apache:mainfrom
potiuk:feature/pr-creation-cap

Conversation

@potiuk

@potiuk potiuk commented Jul 10, 2026

Copy link
Copy Markdown
Member

What

Implements support for GitHub's pull request creation cap
— an interaction limit that caps how many open pull requests a user without write access may have
open at one time. Users with write access are unaffected.

It uses the PATCH /repos/{owner}/{repo}/interaction-limits/pulls/creation-cap endpoint (schema taken
from GitHub's OpenAPI description, since the REST docs were not yet published when the changelog went out).

Configuration

Nested under the existing github.pull_requests block:

github:
  pull_requests:
    creation_cap:
      enabled: true
      max_open_pull_requests: 5   # optional, 1-1000; GitHub default used if omitted
  • enabled: false turns the cap off.
  • Removing the creation_cap section disables a cap that was previously managed by .asf.yaml.

Changes

  • asfyaml/feature/github/__init__.py — creation_cap strictyaml schema + directive registration
  • asfyaml/feature/github/pr_creation_cap.py — new directive (payload build, 1–1000 range validation,
    disable-on-removal, noop-aware, idempotent PATCH)
  • tests/github_pr_creation_cap.py — 9 tests (schema validation + enable/disable/removal/out-of-range/noop)
  • README.md — new "Pull request creation cap" subsection + ToC entry

Testing

Full suite passes (105 tests), ruff and mypy clean on the new code.

@potiuk
potiuk force-pushed the feature/pr-creation-cap branch from 939fcb8 to 7286ea7 Compare July 10, 2026 16:44

@o-nikolas o-nikolas left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would love to see this supported by asf.yaml

Comment thread asfyaml/feature/github/pr_creation_cap.py
@potiuk

potiuk commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Hello dear infra - could we get it reviewed and merged? We need to have some tools to at least attempt to fight with the AI slop.

@raulcd

raulcd commented Jul 29, 2026

Copy link
Copy Markdown
Member

We would certainly use this in apache/arrow. Thanks @potiuk for pushing this.

Comment thread asfyaml/feature/github/pr_creation_cap.py Outdated

@ppkarwasz ppkarwasz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@janhoy

janhoy commented Sep 3, 2026

Copy link
Copy Markdown

+1

@hainenber

Copy link
Copy Markdown

+1 to this. Apache Superset project will utilize this asap.

@thisisnic

Copy link
Copy Markdown
Member

Also +1 - we'd love to see this merged soon so we can use this in Arrow

@potiuk

potiuk commented Sep 7, 2026

Copy link
Copy Markdown
Member Author

It would be great to merge it finally. Is there anything blocking it ?

Implements the pull request creation cap interaction limit
(community/maintainers#840), which limits
the number of open pull requests a user without write access may have open
at one time via the PATCH /repos/{owner}/{repo}/interaction-limits/pulls/
creation-cap endpoint.

Configured under github.pull_requests.creation_cap with `enabled` and an
optional `max_open_pull_requests` (1-1000). Removing the section disables a
cap previously managed by .asf.yaml. Includes tests and README docs.

Generated-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Addresses review feedback: the PATCH to the interaction-limits endpoint
silently ignored failures. Follow the pattern used by the rulesets
directive and raise a descriptive exception for non-2xx responses
(403/404/422/500 get specific messages, anything else a generic one).

Also add a note that an omitted max_open_pull_requests is intentional:
the key is left out of the payload so GitHub applies its own default.
@potiuk
potiuk force-pushed the feature/pr-creation-cap branch from 6f5addf to 827347e Compare September 18, 2026 05:44
The guard returned before the PATCH whenever `enabled` was false and the
cached previous .asf.yaml carried no `creation_cap` section. That made
`enabled: false` unable to turn off a cap that was actually on, which
happens in two ordinary situations: the cache at /x1/asfyaml is cold, as
it is in CI and in sandbox runs, or the cap was switched on by hand in the
repository settings rather than through .asf.yaml.

Observed against a sandbox repository: with the cap live at enabled/5,
applying `creation_cap: {enabled: false}` printed no "Disabling" line and
left the cap untouched.

The `else: return` above already covers the one case the guard existed
for -- no `creation_cap` section now and none before -- so dropping it is
enough. An explicit `enabled: false` now always sends the PATCH, which is
idempotent, and matches what README already documented. The cost is one
extra API call per .asf.yaml change for repositories that keep
`enabled: false` set permanently.

Generated-by: Claude Opus 5
@potiuk

potiuk commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

Rebased onto current main — the branch predated the --branch flag that #127 added to asfyaml-run, so the sandbox workflow couldn't run against it at all.

Sandbox-tested at 894566b against my own potiuk/infrastructure-asfyaml-sandbox, using the workflow from #127:

Both confirmed by reading /interaction-limits/pulls/creation-cap back afterwards.

The response check from the second commit also fired for real: an earlier run with an under-scoped token produced Not allowed to set the pull request creation cap on '…': Resource not accessible by personal access token and failed the run rather than passing silently.

Third commit fixes a gap the sandbox testing exposed. enabled: false could not turn off a cap that was actually on, unless the cached previous .asf.yaml already carried a creation_cap section. The guard returned before the PATCH — so it broke whenever the /x1/asfyaml cache was cold, and whenever a cap had been switched on by hand in the repository settings rather than through .asf.yaml. The else: return above already covers the only case that guard existed for, so removing it was enough; an explicit enabled: false now always PATCHes, which is idempotent and matches what README already documented. Cost is one extra API call per .asf.yaml change for repos that keep enabled: false set permanently.

Worth flagging separately: the disable-on-removal path depends on that same cache, so it isn't exercised by the sandbox or CI — unit tests only.

cc @Humbedooh

@Humbedooh
Humbedooh merged commit f920268 into apache:main Sep 21, 2026
5 checks passed
Andrushika added a commit to Andrushika/infrastructure-asfyaml that referenced this pull request Sep 22, 2026
The pull request creation cap from apache#111 applies to every user without
write access. GitHub keeps a per-repository bypass list of users who may
open pull requests regardless of the cap, but .asf.yaml could not set
it, so a project that wanted some contributors exempt had to maintain
that list by hand in the repository settings.

creation_cap.bypass_users is a list of GitHub logins. When the key is
present the bypass list is made to match it on every run: missing users
are added and anyone else is removed, comparing logins
case-insensitively. `bypass_users: ~` empties the list. When the key is
omitted the list is left alone, so a list kept in the repository
settings keeps working. Removing the whole creation_cap section
deliberately does not clear the list, because that would depend on the
previous_yaml cache, which is not exercised outside production.
Andrushika added a commit to Andrushika/infrastructure-asfyaml that referenced this pull request Sep 22, 2026
The pull request creation cap from apache#111 applies to every user without
write access. GitHub keeps a per-repository bypass list of users who may
open pull requests regardless of the cap, but .asf.yaml could not set
it, so a project that wanted some contributors exempt had to maintain
that list by hand in the repository settings.

creation_cap.bypass_users is a list of GitHub logins. When the key is
present the bypass list is made to match it on every run: missing users
are added and anyone else is removed, comparing logins
case-insensitively. `bypass_users: ~` empties the list. When the key is
omitted the list is left alone, so a list kept in the repository
settings keeps working. Removing the whole creation_cap section
deliberately does not clear the list, because that would depend on the
previous_yaml cache, which is not exercised outside production.
dwsmith1983 pushed a commit to dwsmith1983/datafusion that referenced this pull request Oct 4, 2026
## Which issue does this PR close?

Follows [DataFusion discussion
apache#24413](apache#24413).

## Rationale for this change

See discussion for the rationale, most people are voting for 'set limit
to 3' from the discussion.

## What changes are included in this PR?

Enable `github.pull_requests.creation_cap` in `.asf.yaml` and set
`max_open_pull_requests` to `3`.

- ASF support:
[apache/infrastructure-asfyaml#111](apache/infrastructure-asfyaml#111).
- Airflow example followed by this change:
[apache/airflow#73758](apache/airflow#73758).

Whitelist support through `.asf.yaml` is being added in
[apache/infrastructure-asfyaml#135](apache/infrastructure-asfyaml#135),
which is still open. Before that I think it's possible to do some manual
close/reopen, if some contributor have > 3 concurrent PRs that is
mergeable.

## What is the testing strategy for this PR?

Should work since it's following the pattern in other ASF project above

I don't know if it's possible to test before merging

## Are there any user-facing changes?

NA
potiuk pushed a commit to potiuk/infrastructure-asfyaml that referenced this pull request Oct 9, 2026
The pull request creation cap from apache#111 applies to every user without
write access. GitHub keeps a per-repository bypass list of users who may
open pull requests regardless of the cap, but .asf.yaml could not set
it, so a project that wanted some contributors exempt had to maintain
that list by hand in the repository settings.

creation_cap.bypass_users is a list of GitHub logins. When the key is
present the bypass list is made to match it on every run: missing users
are added and anyone else is removed, comparing logins
case-insensitively. `bypass_users: ~` empties the list. When the key is
omitted the list is left alone, so a list kept in the repository
settings keeps working. Removing the whole creation_cap section
deliberately does not clear the list, because that would depend on the
previous_yaml cache, which is not exercised outside production.
Omega359 pushed a commit to Omega359/arrow-datafusion that referenced this pull request Oct 11, 2026
## Which issue does this PR close?

Follows [DataFusion discussion
apache#24413](apache#24413).

## Rationale for this change

See discussion for the rationale, most people are voting for 'set limit
to 3' from the discussion.

## What changes are included in this PR?

Enable `github.pull_requests.creation_cap` in `.asf.yaml` and set
`max_open_pull_requests` to `3`.

- ASF support:
[apache/infrastructure-asfyaml#111](apache/infrastructure-asfyaml#111).
- Airflow example followed by this change:
[apache/airflow#73758](apache/airflow#73758).

Whitelist support through `.asf.yaml` is being added in
[apache/infrastructure-asfyaml#135](apache/infrastructure-asfyaml#135),
which is still open. Before that I think it's possible to do some manual
close/reopen, if some contributor have > 3 concurrent PRs that is
mergeable.

## What is the testing strategy for this PR?

Should work since it's following the pattern in other ASF project above

I don't know if it's possible to test before merging

## Are there any user-facing changes?

NA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants