Files
Julien BiscontiandClaude Opus 5 1a39b59def
Deploy to GitHub Pages / build (push) Failing after 38s
Deploy to GitHub Pages / deploy (push) Skipped
docs: add triage-prs skill (#1527)
Capture the PR triage workflow: merge each PR onto master in a scratch
worktree before linting, judge the project against the "for Docker, not
just using Docker" rule with GitHub maturity signals, then merge, review,
label, or close it.

Records the two blockers found in practice: branch protection needs an
approval plus an up-to-date branch, and a token without `workflow` scope
cannot merge PRs that touch .github/workflows.

Un-ignore .claude/skills so the skill is shared; settings.local.json
stays ignored.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 22:54:03 +02:00

5.5 KiB

name, description
name description
triage-prs Triage the open pull requests of this curated list — validate each one with the repo CLI, sort it into merge / changes-requested / hold / reject, then merge, review, label, or close it with a friendly comment. Use when asked to triage, sweep, or clean up the open PRs.

Triage the PR queue

Almost every PR here adds one line to README.md. Triage is therefore two questions per PR — is the entry mechanically correct? (the CLI answers it) and does the project belong on the list? (you answer it from GitHub signals) — followed by exactly one outward action.

Ground rule for the second question, from CLAUDE.md: the project has to be for Docker, not just using Docker.

1. Collect the queue

gh pr list --limit 50 --json number,title,author,createdAt,mergeable \
  --jq '.[] | "\(.number)\t\(.author.login)\t\(.createdAt[0:10])\t\(.mergeable)\t\(.title)"'
gh pr diff <N> | grep -E '^\+\+\+|^\+[^+]'   # the proposed entry

Read the added line, not the title. Dependabot PRs skip to step 4.

2. Machine check — merge onto master, then lint

Never lint the PR branch alone: it was written against a stale base, so gh pr diff hunk headers name the wrong section, and ordering errors appear only after newer entries have landed. Merge each PR onto current master in a scratch worktree instead.

WT=<scratchpad>/wt
git worktree add -f "$WT" master && cp awesome-docker "$WT/"
for n in <PRs>; do git fetch -q origin "pull/$n/head:pr-$n" -f; done
for n in <PRs>; do
  git -C "$WT" reset -q --hard origin/master; git -C "$WT" clean -qfd
  if git -C "$WT" merge -q --no-edit "pr-$n" >/dev/null 2>&1; then
    echo "== PR $n $( (cd "$WT" && ./awesome-docker lint 2>&1 | head -3) )"
  else
    git -C "$WT" merge --abort; echo "== PR $n CONFLICT"
  fi
done
git worktree remove --force "$WT"; for n in <PRs>; do git branch -qD pr-$n; done

From the merged file, read the real target section (nearest ##/### heading above the added line) and check the whole diff for changes beyond the one entry. Two problems hide there: author attribution added to a neighbour's description, and an entry that a past commit removed on purpose — git log --oneline -S <name> -- README.md exposes the second.

3. Judge the project

gh api repos/<owner>/<repo> --jq '[.stargazers_count,.created_at[0:10],.pushed_at[0:10],(.license.spdx_id//"none"),(.archived|tostring)]|join(" ")'
gh api repos/<owner>/<repo>/contributors --jq length
gh api repos/<owner>/<repo>/releases --jq length
gh api "repos/<owner>/<repo>/commits?per_page=1" -i | grep -i '^link:'   # last page number = commit count

Stars alone decide nothing — commit count, contributors, and releases separate a real young project from a weekend demo. Check non-GitHub links with curl -s -o /dev/null -w '%{http_code}' -L.

Sort into exactly one bucket:

Bucket Signals
Merge for Docker, lint clean, maintained, some traction; :yen: present if and only if the service is commercial
Changes requested good entry, mechanical fault: order error, stray edits, conflict with master
Hold for Docker and real work, but days old, no users, or a large open-issue backlog
Reject uses Docker rather than serving it; demonstration or template repository; a handful of commits with no license

4. Act — one action per PR

Merge. Branch protection wants 1 approval and an up-to-date branch (strict: true), so gh pr merge alone fails with "the base branch policy prohibits the merge".

gh pr comment <N> --body "Thank you for your contribution! <one line on why it fits>"
gh pr review <N> --approve --body "Correct section, alphabetical order kept, lint passes."
gh pr update-branch <N>          # when mergeStateStatus is not CLEAN
gh pr merge <N> --squash --delete-branch

Merge one at a time and confirm with gh pr view <N> --json state; each merge can push the next PR out of date. A PR that touches .github/workflows/ fails on a token without workflow scope, for both update and merge — leave it approved and tell the human to merge it or to run gh auth refresh -h github.com -s workflow.

Changes requested. gh pr review <N> --request-changes --body "..." — quote the exact linter error and name the fix (make lint-fix for ordering, rebase for a conflict).

Hold. Comment with the reason and keep it open.

Reject. gh pr close <N> --comment "..." — name the rule it misses.

Then label every PR that stays open, so its state is visible at a glance:

Label For
pending-evaluation hold
pending-fix small fix requested
pending-rebase conflicts with master
pending-submitter-response waiting on the author for anything else

5. Tone

Every comment, on a merge or a rejection, is written to a volunteer who did unpaid work:

  • Thank them first, and name the thing you liked.
  • Give the concrete reason, quoting the rule or the linter error.
  • Close by inviting correction — "if we have judged this wrongly, reply and we will look again" — and encourage a future contribution.
  • Reject the fit, never the project's quality; point rejected projects at a list where they belong.

6. Verify and report

gh pr list --limit 50 --json number,labels,title --jq '.[] | "\(.number)\t[\([.labels[].name]|join(", "))]\t\(.title)"'
git pull --ff-only && ./awesome-docker lint

Done when every open PR is merged, closed, or open with a state label; master lints clean; and the report names each PR's bucket plus anything that needs the human.