Problem
Outside contributions are the items on the Org Triage board that most need a timely human response — they often arrive without an accompanying issue, and a drive-by PR is frequently how a bug reaches us at all. They are also, measurably, the items the board is worst at surfacing.
Of the 48 PRs on the board (checked 2026-08-27), 8 are outside contributions and 5 are from first-time contributors. The rot is concentrated in exactly that group:
| PR |
Author |
author_association |
Board status |
Days since update |
| pupmod-simp-simplib#233 |
jcpunk |
CONTRIBUTOR |
No Status |
2170 |
| pupmod-simp-simplib#234 |
jcpunk |
CONTRIBUTOR |
No Status |
1826 |
| pupmod-simp-rsync#90 |
greatflyingsteve |
FIRST_TIME_CONTRIBUTOR |
In Progress |
1470 |
| pupmod-simp-rsync#91 |
greatflyingsteve |
FIRST_TIME_CONTRIBUTOR |
In Progress |
1470 |
| pupmod-simp-rsyslog#162 |
dforste |
FIRST_TIME_CONTRIBUTOR |
— |
— |
| pupmod-simp-at#99 |
janbrono |
FIRST_TIME_CONTRIBUTOR |
— |
— |
| pupmod-simp-sssd#198 |
seriv |
FIRST_TIME_CONTRIBUTOR |
— |
— |
| pupmod-simp-simplib#290 |
dforste |
CONTRIBUTOR |
— |
— |
The two oldest no-status items on the entire board are outside PRs (~5 and ~6 years), and the longest-stalled pair in "In Progress" is a first-time contributor's. Nothing on the board distinguishes them from the 40 MEMBER-authored PRs they're filed among, so there is no way to sweep for "outside work waiting on us."
Proposed change
Have the triage workflow label outside contributions on arrival, so the board's existing Labels field surfaces them and they can be filtered into a saved view.
- name: Flag outside contributions
if: >-
github.event_name == 'pull_request_target' &&
contains(fromJSON('["FIRST_TIME_CONTRIBUTOR","CONTRIBUTOR","NONE"]'),
github.event.pull_request.author_association)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr edit "${{ github.event.pull_request.number }}" --add-label external-contributor
Then add an External view on the board filtered to that label, and make "has an outside contributor waiting" a thing that can be answered at a glance rather than by querying the API.
Prerequisite: the label does not exist yet
Sampled repos (simplib, rsync, at) carry only GitHub's defaults — bug, duplicate, enhancement, help wanted, invalid, question, wontfix. There is no external-contributor label anywhere, and gh pr edit --add-label fails if the label is absent, so this needs a fleet-wide label creation first — which is itself a puppetsync-shaped task (labels aren't currently part of the managed baseline at all).
Options, roughly in order of preference:
- Create the label fleet-wide as part of this change, and consider whether a managed label set belongs in the baseline generally.
- Create-if-missing in the workflow (
gh label create external-contributor --force) — self-healing, at the cost of an extra API call on every outside PR.
- Skip labels, and set a board field via the GraphQL API instead. Avoids the label problem but needs the project item ID and a token with project scope; more moving parts.
Notes
author_association values worth catching are FIRST_TIME_CONTRIBUTOR, CONTRIBUTOR, and NONE. MEMBER, OWNER, and COLLABORATOR are the internal cases. (CONTRIBUTOR means they've had a PR merged before but aren't org members — still outside, and the two 5-year-old simplib PRs above are exactly that.)
- The existing workflow does not check out any code, which is what makes its use of
pull_request_target safe. This addition must preserve that — it only reads event metadata and calls the API. Do not add a checkout of the PR head.
- Labeling needs
pull-requests: write; the default GITHUB_TOKEN under pull_request_target has it, so AUTO_TRIAGE_TOKEN isn't required for this step.
- A follow-on worth considering separately: a scheduled staleness sweep that pings when anything labeled
external-contributor goes untouched for N days. The table above is the argument for it.
Related
Problem
Outside contributions are the items on the Org Triage board that most need a timely human response — they often arrive without an accompanying issue, and a drive-by PR is frequently how a bug reaches us at all. They are also, measurably, the items the board is worst at surfacing.
Of the 48 PRs on the board (checked 2026-08-27), 8 are outside contributions and 5 are from first-time contributors. The rot is concentrated in exactly that group:
author_associationThe two oldest no-status items on the entire board are outside PRs (~5 and ~6 years), and the longest-stalled pair in "In Progress" is a first-time contributor's. Nothing on the board distinguishes them from the 40 MEMBER-authored PRs they're filed among, so there is no way to sweep for "outside work waiting on us."
Proposed change
Have the triage workflow label outside contributions on arrival, so the board's existing Labels field surfaces them and they can be filtered into a saved view.
Then add an External view on the board filtered to that label, and make "has an outside contributor waiting" a thing that can be answered at a glance rather than by querying the API.
Prerequisite: the label does not exist yet
Sampled repos (
simplib,rsync,at) carry only GitHub's defaults —bug,duplicate,enhancement,help wanted,invalid,question,wontfix. There is noexternal-contributorlabel anywhere, andgh pr edit --add-labelfails if the label is absent, so this needs a fleet-wide label creation first — which is itself a puppetsync-shaped task (labels aren't currently part of the managed baseline at all).Options, roughly in order of preference:
gh label create external-contributor --force) — self-healing, at the cost of an extra API call on every outside PR.Notes
author_associationvalues worth catching areFIRST_TIME_CONTRIBUTOR,CONTRIBUTOR, andNONE.MEMBER,OWNER, andCOLLABORATORare the internal cases. (CONTRIBUTORmeans they've had a PR merged before but aren't org members — still outside, and the two 5-year-old simplib PRs above are exactly that.)pull_request_targetsafe. This addition must preserve that — it only reads event metadata and calls the API. Do not add a checkout of the PR head.pull-requests: write; the defaultGITHUB_TOKENunderpull_request_targethas it, soAUTO_TRIAGE_TOKENisn't required for this step.external-contributorgoes untouched for N days. The table above is the argument for it.Related
[puppetsync]PRs (sibling issue) — the noise those create is a large part of why these get lost.