Skip to content

Commit 42d5a50

Browse files
committed
Refactor Contribution Check workflow documentation and streamline PR evaluation process
1 parent 52d345e commit 42d5a50

1 file changed

Lines changed: 21 additions & 122 deletions

File tree

workflows/contribution-check.md

Lines changed: 21 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
---
22
name: "Contribution Check"
3-
description: |
4-
Reviews a batch of open pull requests against the repository's contribution guidelines,
5-
delegating evaluation to a subagent and compiling results into a structured report issue.
6-
Helps maintainers efficiently prioritize community contributions by highlighting PRs that
7-
are ready for review, need work, or fall outside contribution guidelines.
8-
93
on:
104
schedule: "every 4 hours"
115
workflow_dispatch:
@@ -15,118 +9,13 @@ permissions:
159
issues: read
1610
pull-requests: read
1711

12+
env:
13+
TARGET_REPOSITORY: ${{ vars.TARGET_REPOSITORY || github.repository }}
14+
1815
tools:
1916
github:
2017
toolsets: [default]
2118
lockdown: false
22-
23-
steps:
24-
- name: Fetch and filter PRs
25-
uses: actions/github-script@v8
26-
with:
27-
script: |
28-
const fs = require('fs');
29-
const [targetOwner, targetRepo] = process.env.GITHUB_REPOSITORY.split('/');
30-
31-
const TARGET = 10;
32-
const MAX_PAGES = 3;
33-
const PER_PAGE = 20;
34-
35-
const SKIP_LABELS = new Set(['maintainer', 'trusted-contributor']);
36-
const SMALL_LABELS = new Set(['size: XS', 'size: S']);
37-
38-
const skipReason = (pr) => {
39-
if (pr.author_association === 'MEMBER' || pr.author_association === 'OWNER') return 'maintainer';
40-
const labels = pr.labels.map(l => l.name);
41-
if (labels.some(l => SKIP_LABELS.has(l))) return 'maintainer';
42-
if (labels.some(l => SMALL_LABELS.has(l))) return 'small';
43-
if (labels.some(l => l.startsWith('close:') || l.startsWith('r: '))) return 'triaged';
44-
return null;
45-
};
46-
47-
const accepted = [];
48-
const allPRs = [];
49-
50-
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
51-
52-
for (let page = 1; page <= MAX_PAGES && accepted.length < TARGET; page++) {
53-
if (page > 1) await sleep(1000);
54-
core.startGroup(`Page ${page}/${MAX_PAGES} (accepted ${accepted.length}/${TARGET} so far)`);
55-
56-
const batch = await github.rest.pulls.list({
57-
owner: targetOwner,
58-
repo: targetRepo,
59-
state: 'open',
60-
sort: 'created',
61-
direction: 'desc',
62-
per_page: PER_PAGE,
63-
page,
64-
});
65-
66-
const prs = batch.data;
67-
core.info(`Fetched ${prs.length} PRs`);
68-
69-
if (prs.length === 0) {
70-
core.info('No more PRs to fetch');
71-
core.endGroup();
72-
break;
73-
}
74-
75-
for (const pr of prs) {
76-
const labels = pr.labels.map(l => l.name).join(', ');
77-
core.info(` #${pr.number} association=${pr.author_association} labels=[${labels}]`);
78-
}
79-
80-
allPRs.push(...prs);
81-
82-
for (const pr of prs) {
83-
if (accepted.length >= TARGET) break;
84-
if (!skipReason(pr)) accepted.push(pr.number);
85-
}
86-
87-
core.info(`Accepted: ${accepted.length}/${TARGET} | Skipped so far: ${allPRs.length - accepted.length}`);
88-
core.endGroup();
89-
}
90-
91-
const prList = accepted.slice(0, TARGET);
92-
const skipped = allPRs.length - accepted.length;
93-
94-
core.startGroup('Final results');
95-
core.info(`Fetched: ${allPRs.length} | Evaluated: ${accepted.length} | Skipped: ${skipped}`);
96-
core.info(`PR list: ${prList.join(',')}`);
97-
core.endGroup();
98-
99-
// Step summary
100-
const rows = allPRs.map(pr => {
101-
const num = pr.number;
102-
const assoc = pr.author_association;
103-
const labels = pr.labels.map(l => l.name).join(', ');
104-
const reason = skipReason(pr) ?? 'evaluate';
105-
const icon = reason === 'evaluate' ? '✅' : '⏭️';
106-
return `| #${num} | \`${assoc}\` | ${labels} | ${icon} ${reason} |`;
107-
});
108-
109-
const summary = [
110-
'### 🔍 PR Pre-filter Results',
111-
'',
112-
`**Fetched:** ${allPRs.length} | **Evaluated:** ${accepted.length} | **Skipped:** ${skipped}`,
113-
'',
114-
'| PR | Association | Labels | Status |',
115-
'|---|---|---|---|',
116-
...rows,
117-
].join('\n');
118-
119-
await core.summary.addRaw(summary).write();
120-
121-
// Write results to a file the agent can read
122-
const result = {
123-
pr_numbers: prList,
124-
skipped_count: skipped,
125-
evaluated_count: accepted.length,
126-
};
127-
fs.writeFileSync('pr-filter-results.json', JSON.stringify(result, null, 2));
128-
core.info(`Wrote pr-filter-results.json: ${JSON.stringify(result)}`);
129-
13019
safe-outputs:
13120
create-issue:
13221
title-prefix: "[Contribution Check Report]"
@@ -137,21 +26,27 @@ safe-outputs:
13726
allowed: [spam, needs-work, outdated, lgtm]
13827
max: 4
13928
target: "*"
29+
target-repo: ${{ vars.TARGET_REPOSITORY }}
14030
add-comment:
14131
max: 10
14232
target: "*"
33+
target-repo: ${{ vars.TARGET_REPOSITORY }}
14334
hide-older-comments: true
14435
---
14536

37+
## Target Repository
38+
39+
The target repository is `${{ env.TARGET_REPOSITORY }}`. All PR fetching and subagent dispatch use this value.
40+
14641
## Overview
14742

148-
You are an **orchestrator**. Your job is to dispatch PRs to the `contribution-checker` subagent for evaluation and compile the results into a single report issue.
43+
You are an **orchestrator**. Your job is to dispatch PRs to the `contribution-checker` subagent for evaluation and compile the results into a single report issue in THIS repository (`${{ github.repository }}`).
14944

15045
You do NOT evaluate PRs yourself. You delegate each evaluation to `.github/agents/contribution-checker.agent.md`.
15146

15247
## Pre-filtered PR List
15348

154-
A `pre-agent` step has already queried and filtered PRs. The results are in `pr-filter-results.json` at the workspace root. Read this file first. It contains:
49+
A `pre-agent` step has already queried and filtered PRs from `${{ env.TARGET_REPOSITORY }}`. The results are in `pr-filter-results.json` at the workspace root. Read this file first. It contains:
15550

15651
```json
15752
{
@@ -165,16 +60,18 @@ If `pr_numbers` is empty, create a report stating no PRs matched the filters and
16560

16661
## Step 1: Dispatch to Subagent
16762

168-
For each PR number in the list, delegate evaluation to the **contribution-checker** subagent (`.github/agents/contribution-checker.agent.md`).
63+
For each PR number in the comma-separated list, delegate evaluation to the **contribution-checker** subagent (`.github/agents/contribution-checker.agent.md`).
16964

17065
### How to dispatch
17166

17267
Call the contribution-checker subagent for each PR with this prompt:
17368

17469
```
175-
Evaluate PR ${{ github.repository }}#<number> against the contribution guidelines.
70+
Evaluate PR ${{ env.TARGET_REPOSITORY }}#<number> against the contribution guidelines.
17671
```
17772

73+
The subagent accepts any `owner/repo#number` reference — the target repo is not hardcoded.
74+
17875
The subagent will return a single JSON object with the verdict and a comment for the contributor.
17976

18077
### Parallelism
@@ -188,13 +85,13 @@ Gather all returned JSON objects. If a subagent call fails, record the PR with v
18885

18986
### Posting comments
19087

191-
For each PR where the subagent returned a non-empty `comment` field and the quality is NOT `lgtm`, call the `add_comment` safe output tool to post the comment to the PR. Pass the PR number and the comment body from the subagent result.
88+
For each PR where the subagent returned a non-empty `comment` field and the quality is NOT `lgtm`, call the `add_comment` safe output tool to post the comment to the PR in the target repository. Pass the PR number and the comment body from the subagent result. The `add_comment` tool is pre-configured with `target-repo` pointing to the target repository — you do NOT need to specify the repo yourself.
19289

19390
Do NOT post comments to PRs with `lgtm` quality — those are ready for maintainer review and don't need additional feedback.
19491

19592
## Step 2: Compile Report
19693

197-
Create a single issue in this repository. Use the `skipped_count` from `pr-filter-results.json`. Build the report tables from the JSON objects returned by the subagent (use `number`, `title`, `author`, `lines`, and `quality` fields).
94+
Create a single issue in THIS repository. Use the `skipped_count` from `pr-filter-results.json`. Build the report tables from the JSON objects returned by the subagent (use `number`, `title`, `author`, `lines`, and `quality` fields).
19895

19996
Follow the **report layout rules** below — they apply to every report this workflow produces.
20097

@@ -258,7 +155,7 @@ Evaluated: 4 · Skipped: 10
258155

259156
## Step 3: Label the Report Issue
260157

261-
After creating the report issue, call the `add_labels` safe output tool to apply labels based on the quality signals reported by the subagent. Collect the distinct `quality` values from all returned rows and add each as a label.
158+
After creating the report issue, call the `add_labels` safe output tool to apply labels based on the quality signals reported by the subagent. Collect the distinct `quality` values from all returned rows and add each as a label. The `add_labels` tool is pre-configured with `target-repo` pointing to the target repository.
262159

263160
For example, if the batch contains rows with `lgtm`, `spam`, and `needs-work` quality values, apply all three labels: `lgtm`, `spam`, `needs-work`.
264161

@@ -269,6 +166,8 @@ If any subagent call failed (❓), also apply `outdated`.
269166
- **You are the orchestrator** — you dispatch and compile. You do NOT run the checklist yourself.
270167
- **PR fetching and filtering is pre-computed** — a `pre-agent` step writes `pr-filter-results.json`. Read it at the start.
271168
- **Subagent does the analysis**`.github/agents/contribution-checker.agent.md` handles all per-PR evaluation logic.
272-
- **Use safe output tools** — use `add-comment` and `add-labels` safe output tools to post comments and labels to PRs.
169+
- **Read from `${{ env.TARGET_REPOSITORY }}`** — read-only access via GitHub MCP tools.
170+
- **Write to `${{ github.repository }}`** — reports go here as issues.
171+
- **Use safe output tools for target repository interactions** — use `add-comment` and `add-labels` safe output tools to post comments and labels to PRs in the target repository `${{ env.TARGET_REPOSITORY }}`. Never use `gh` CLI or direct API calls for writes.
273172
- Close the previous report issue when creating a new one (`close-older-issues: true`).
274173
- Be constructive in assessments — these reports help maintainers prioritize, not gatekeep.

0 commit comments

Comments
 (0)