Skip to content

chore(ci): require approved issues or vouchers for PRs - #1917

Merged
randoneering merged 5 commits into
mainfrom
chore/contribution-eligibility
Oct 5, 2026
Merged

randoneering merged 5 commits into
mainfrom
chore/contribution-eligibility

Conversation

@tinsever

@tinsever tinsever commented Oct 4, 2026

Copy link
Copy Markdown
Member

What changed?

Adds a Contribution eligibility check. A PR passes if it links an open issue labeled ready-for-contribution, or if the author is a maintainer, a vouched contributor, or an approved bot. Everyone else gets a failing check that tells them what to do.

The workflow only runs code and reads policy from main, never from the PR. It reruns when the PR, its issues, labels, or the voucher list change, plus an hourly run to catch sidebar links and permission changes. Dependabot PRs are checked after CI finishes because bot-triggered runs can get a read-only token.

Vouchers live in .github/contribution-policy.json, keyed by GitHub account ID so renames keep them. The core team (andrejsshell, randoneering, tinsever) is vouched and Dependabot is the only exempt bot.

CONTRIBUTING.md, the PR template, and scripts/ci/README.md explain the new rule and how to manage vouchers. CI now runs the new tests.

The check doesn't block anything until it's added as a required status check on main. Setup steps are in CONTRIBUTING.md under Managing Vouchers.

Related issue

None, maintainer change.

How did you check it?

  • node --test scripts/contribution-eligibility/*.test.mjs (17 passing)
  • Validated the checked-in policy file with validatePolicy
  • pnpm lint passes
  • Not run on GitHub yet. It needs to be on main before the workflow can run.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T11:37:53.583895Z 0f9c23a Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added the size/l label Oct 4, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Require approved issues or vouchers for pull requests

✨ Enhancement ⚙️ Configuration changes 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add a contribution check requiring an approved issue or an explicit author exemption.
• Reconcile open PRs from trusted main-branch code when eligibility may change.
• Document voucher management and enforcement setup; add policy and workflow tests.
Diagram

graph TD
  Events["GitHub events"] --> Runner["Trusted workflow"] --> Policy["Main policy"] --> Decision{"Eligible?"} --> Checks["Commit check"] --> Rules["Branch rules"]
  Runner --> Metadata["GitHub metadata"] --> Decision
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Recheck only affected pull requests
  • ➕ Fewer GitHub API calls and shorter runs as the repository grows.
  • ➖ Requires reliable reverse mapping from changed issues to PRs and careful handling of queued events, policy changes, and shared commits.

Recommendation: Keep full reconciliation for now: it favors correct revocation and recovery from missed or replaced events over API efficiency. Monitor runtime and rate limits as open-PR volume grows before considering targeted reconciliation.

Files changed (12) +931 / -6

Enhancement (4) +325 / -0
check-runs.mjsPublish eligibility check runs on commits +31/-0

Publish eligibility check runs on commits

• Creates or updates a named check run for a head SHA, translating pending and final results into GitHub check states and linking contributors to the rules.

scripts/contribution-eligibility/check-runs.mjs

check.mjsReconcile every open pull request +131/-0

Reconcile every open pull request

• Loads and validates policy, evaluates author exemptions or linked issues, and verifies that PR metadata has not changed before reporting success. Clears previous results, applies the least permissive result to shared head commits, and publishes failures when evaluation errors occur.

scripts/contribution-eligibility/check.mjs

github.mjsQuery GitHub PRs and linked issues +94/-0

Query GitHub PRs and linked issues

• Adds an authenticated API client with request validation and pagination for open PRs and GraphQL closing-issue references. Restricts linked issues to the current repository.

scripts/contribution-eligibility/github.mjs

policy.mjsValidate vouchers and assess eligibility +69/-0

Validate vouchers and assess eligibility

• Validates documented, unique account-ID entries; exempts approved bots, vouched contributors, and maintainers; and requires other authors to link an open issue with the approval label.

scripts/contribution-eligibility/policy.mjs

Tests (3) +428 / -1
ci.ymlRun contribution-eligibility tests in CI +1/-1

Run contribution-eligibility tests in CI

• Adds the new Node test files to the existing security-controls test step.

.github/workflows/ci.yml

check.test.mjsTest reconciliation and check publication +307/-0

Test reconciliation and check publication

• Covers approvals, revocations, exemptions, API and policy failures, changed PRs, shared commits, pagination, and check-run states using a simulated GitHub API.

scripts/contribution-eligibility/check.test.mjs

policy.test.mjsTest policy validation and eligibility rules +120/-0

Test policy validation and eligibility rules

• Checks the committed policy, account renames, bot and maintainer boundaries, invalid vouchers, and approved-issue requirements.

scripts/contribution-eligibility/policy.test.mjs

Documentation (3) +88 / -5
PULL_REQUEST_TEMPLATE.mdPrompt authors to link an approved issue +3/-1

Prompt authors to link an approved issue

• Explains the required issue label, exemption categories, and where to find the contribution rules.

.github/PULL_REQUEST_TEMPLATE.md

CONTRIBUTING.mdExplain eligibility and voucher administration +76/-4

Explain eligibility and voucher administration

• Describes approved issue links, exemptions, rechecks, and how vouchers are granted or revoked. Provides the branch-rule steps needed to make the published check required.

CONTRIBUTING.md

README.mdDocument the separate eligibility workflow +9/-0

Document the separate eligibility workflow

• Summarizes its trusted-code boundary, eligibility rule, test command, and links to setup instructions.

scripts/ci/README.md

Other (2) +90 / -0
contribution-policy.jsonDefine initial vouchers and bot exemption +26/-0

Define initial vouchers and bot exemption

• Records three core-team vouchers and the Dependabot exemption by numeric GitHub account ID, with human-readable reasons.

.github/contribution-policy.json

contribution-eligibility.ymlReconcile eligibility from a trusted workflow +64/-0

Reconcile eligibility from a trusted workflow

• Triggers reconciliation on relevant GitHub events and an hourly schedule, with a CI-completion path for Dependabot. Checks out main and grants the permissions needed to read metadata and publish checks without executing PR code.

.github/workflows/contribution-eligibility.yml

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Listing outages leave stale checks green ✓ Resolved
Description
reconcile() lists open pull requests and publishes initial pending checks before its per-PR error
handler, so errors in either step abort without replacing existing check results. If approval was
revoked after a successful run, the old successful check can remain on the head commit despite the
workflow failure, contrary to the fail-closed claim in CONTRIBUTING.md.
Code

CONTRIBUTING.md[R109-110]

+issue links, and never runs anything from the PR. If the policy file is broken
+or the GitHub API errors out, the check fails instead of letting the PR
Evidence
openPullRequests() propagates request errors, and reconcile() waits for the complete PR list
before publishing pending checks. The initial publication loop also runs before the per-PR catch
block, while checkPublisher() propagates publication errors. Consequently, either early error can
leave a previous successful result unchanged, although the contribution guide says GitHub API errors
fail the check.

AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent: AGENTS.md: Keep Affected Secondary Entry Points Consistent
CONTRIBUTING.md[108-111]
scripts/contribution-eligibility/check.mjs[57-66]
scripts/contribution-eligibility/github.mjs[31-38]
scripts/contribution-eligibility/github.mjs[41-50]
scripts/contribution-eligibility/check.mjs[49-80]
scripts/contribution-eligibility/check-runs.mjs[18-30]
CONTRIBUTING.md[108-112]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
PR-listing and initial check-publication failures can abort reconciliation without replacing an earlier successful eligibility check. The guide's unconditional fail-closed claim does not account for this behavior.
## Fix Focus Areas
- CONTRIBUTING.md[108-111]
- scripts/contribution-eligibility/check.mjs[49-72]
- scripts/contribution-eligibility/github.mjs[41-50]
- scripts/contribution-eligibility/check-runs.mjs[18-30]
## Recommended Fix
Retry discovery and initial publication failures. If discovery still fails, either qualify the guide's fail-closed claim to describe the limitation or provide a way to invalidate prior successes, such as using a durable record of previously checked open head commits and any head available from the triggering event to publish failure checks before exiting. Add a test where approval is revoked and PR listing fails.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread CONTRIBUTING.md Outdated
@tinsever

tinsever commented Oct 4, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 77dd9b6c7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/contribution-eligibility.yml Outdated
@tinsever

tinsever commented Oct 4, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37ce548954

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/contribution-eligibility/check.mjs Outdated
@tinsever

tinsever commented Oct 4, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 21f212377d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/contribution-eligibility.yml
@tinsever

tinsever commented Oct 4, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 0f9c23a467

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@randoneering
randoneering merged commit b0f41d6 into main Oct 5, 2026
21 checks passed
@randoneering
randoneering deleted the chore/contribution-eligibility branch October 5, 2026 03:01
adeyholar pushed a commit to adeyholar/kaneo that referenced this pull request Oct 5, 2026
### Features

- make cross-column dragged card sortable: usekaneo#1894
- **i18n:** add zh-TW locale: usekaneo#1893
- **integrations:** add label-based sync in advanced settings: usekaneo#1908

### Bug Fixes

- **web:** show the task label editor on narrow screens: usekaneo#1924
- convert ineligible contributions to draft pull requests: [291da4a](usekaneo@291da4a)
- **i18n:** translate the zh-CN strings added since the last sync: usekaneo#1916
- **ci:** exclude skipped events from eligibility concurrency: usekaneo#1917

### Credits

Huge thanks to @VictorOnwukwe, @kenny-ish, @ApplesBear-X, @tinsever, and @FunnyQ for helping!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants