Labsco
github logo

pr-finisher

โœ“ Officialโ˜… 105

by github ยท part of github/gh-aw-firewall

Prepare an open pull request for merge from a GitHub Copilot cloud agent. Drives Reviews, local validation, and Mergeable to a ready state. Does not merge, and cannot trigger CI.

๐Ÿ”’ Repo-maintenance skill. It exists to help maintain github/gh-aw-firewall itself โ€” it's only useful if you contribute code to that project.

This is the playbook your agent receives when the skill activates โ€” you don't need to read it to use the skill, but it's here to audit before installing.

PR Finisher

Drive an open PR for the current branch to a merge-ready state from a GitHub Copilot cloud agent. Do not merge. When everything you can act on is done, report ready-for-human-merge and stop.

Execution context

This skill runs inside a GitHub Copilot cloud agent, not on a developer's machine.

  • The agent's pushes do not trigger CI. Workflows on the PR will not re-run after the agent commits. Any existing statusCheckRollup reflects an earlier HEAD and goes stale the moment the agent pushes.
  • Commit and push on every iteration that changes files. Changes that are not pushed are not available to the user.
  • Local validation is the agent's authoritative correctness signal before push. CI is observational only.
  • Re-running CI is a hand-off to a human (close/reopen the PR, workflow_dispatch, or a push from a maintainer). The agent must surface this in its summary.
  • No watch / no sleep loops. The agent has no async wait state; one pass + summary + stop.

Three merge-ready conditions

A PR is merge-ready when all three are satisfied. Work them concurrently.

ConditionDefinitionAgent's signal
ReviewsEvery unresolved in-scope review thread is addressed on its merits, replied to, and resolved, including GitHub Actions bot threads/comments (github-actions[bot]). Code changes alone do not satisfy this.copilot-review skill + GraphQL reviewThreads
ChecksLocal npm run build / npm run lint / npm test pass. Last-known CI runs reviewed at log level.npm scripts locally; gh pr checks / gh run view --log-failed for prior runs
MergeablePR is OPEN, not draft, mergeable: MERGEABLE, not BEHIND if the repo requires up-to-date branches.gh pr view --json mergeable,mergeStateStatus,state,isDraft

Because the agent cannot re-trigger CI, "Checks" is satisfied at the agent's level when local validation passes and prior CI failures have been root-caused and fixed in the pushed commits. Final green CI requires a human to re-trigger after the agent stops.

Top-level PR comments and review bodies are useful feedback but not a merge gate. Read and action useful ones; do not block on them.

Hard rules

  • Do not merge. Never run gh pr merge, enable auto-merge, or enqueue. This skill stops at "ready for merge."
  • Do not post stand-alone PR comments. Only reply on existing review threads / comments that need a response. Do not ping reviewers or CODEOWNERS.
  • Always disable pagers for gh: prefix with GH_PAGER="" or pipe through cat. Without this, commands hang in non-interactive shells.
  • Never wait for CI to re-run. No bash sleep, no gh run watch, no gh pr checks --watch, no re-check loop after push. The agent's pushes will not trigger workflows; waiting is futile.
  • Local validation is non-negotiable before each push. Because CI will not re-run, the only correctness gate the agent gets is npm run build && npm run lint && npm test locally. Treat a green local run as the bar.
  • Commit and push every iteration that produces file changes. Unpushed changes are not visible to the user.
  • Reviews are not done until reply + resolve both succeed. Code change alone โ‰  thread handled.
  • Smallest fix that works. Don't change unrelated code. Fix lint before tests.
  • Pre-existing unrelated failures โ†’ identify explicitly in the summary; do not guess-fix.

CI-fix anti-patterns (do not do these)

A failing CI step is a signal, not a nuisance. Even though the agent cannot re-run CI to confirm, the following are forbidden and should trigger ask_user instead:

  • Disabling, skipping, or neutering shared tooling (build caches, lint rules, type checks, env vars, required checks) to make a failure go away.
  • "Temporary" disables with a TODO to re-enable later. They outlive the PR and become permanent.
  • Lowering coverage thresholds, removing assertions, or loosening a test until it passes. If the test is wrong about product behavior, fix its logic (assertions, fixtures, setup); don't relax it.
  • Bundling a workaround with a real fix ("belt and suspenders"). Ship one real fix or escalate. Never both.
  • Special-casing one OS/runner to hide a failure on that platform.

Anti-pattern test: if the change would make the failure invisible on future PRs without solving it, stop and escalate.

Before declaring a tool broken on a platform: reproduce locally, check version/config, look for transient causes (timeouts, network, runner state). Most "X is broken on macOS/Windows" reports are transient flakes on healthy tooling.

For flaky infra (caches, registries, runners): prefer narrow fixes โ€” targeted retry, higher timeout, pre-flight health check. If a narrow fix doesn't land in one or two attempts, escalate via ask_user.

Workflow

The agent runs this once. There is no monitoring loop.

1. Triage

GH_PAGER="" gh pr view <number> --json state,isDraft,reviewDecision,mergeable,mergeStateStatus,statusCheckRollup,headRefOid
GH_PAGER="" gh pr checks <number>

If merged/closed, report and stop. Otherwise classify each condition as โœ… / โŒ / โณ / โ“. The CI snapshot here is your only view of CI for this run โ€” capture which checks failed and why before changing anything, because after you push it will be stale.

2. Address Reviews

Delegate to the copilot-review skill and treat that delegation as mandatory, not optional. Insist on full handling of each unresolved in-scope thread (including github-actions[bot]): make change โ†’ run relevant local validation โ†’ commit โ†’ push โ†’ reply โ†’ resolve. A thread is not handled until reply + resolve both succeed.

Before editing, gather the full review surface with explicit GH queries:

GH_PAGER="" gh pr view <number> --json reviews,reviewThreads,comments
GH_PAGER="" gh pr view <number> --json reviewThreads --jq '.reviewThreads[] | select(.isResolved==false)'

When reviewing collected feedback, apply reviewer scoping from copilot-review: trusted automation and team/collaborator reviewers only. Ignore non-team-member feedback.

3. Address Mergeable

GH_PAGER="" gh pr view <number> --json mergeable,mergeStateStatus
  • CONFLICTING โ†’ resolve conflicts using the repo's conventions. If you cannot determine the correct resolution, ask_user.
  • mergeStateStatus: BEHIND โ†’ update branch from base. After updating, scan the new commits for tooling drift (lockfiles, toolchains, lint configs); re-run npm install if package.json or package-lock.json changed, and flag drift in the summary so any new errors read as drift, not regressions.

4. Address Checks (local + prior CI)

Local validation โ€” the agent's only correctness signal. Run in order; fix at each step before moving on:

npm run build
npm run lint
npm test

If workflow lock files need regeneration (e.g., after a gh-aw version bump or .md workflow source change):

gh aw compile
npx ts-node scripts/ci/postprocess-smoke-workflows.ts

Then re-run npm test to verify.

Prior CI failures โ€” for each failure captured during triage, pull logs and fix the root cause:

GH_PAGER="" gh run view <run_id> --log-failed

Classify as: real product/test bug, infra flake, or third-party flake. Apply the fix in the agent's commits and, where possible, reproduce the fix locally via the matching npm script. If the failure can't be reproduced locally (infra-only), state that in the summary so the human re-triggers CI with eyes open. Per anti-pattern rules: 1โ€“2 narrow attempts, then ask_user.

5. Commit, push, and stop

After each iteration that changes files, commit and push immediately. Before stopping, ensure there are no uncommitted or unpushed changes left. Do not re-check gh pr checks expecting a new run. Print the summary and stop.

Summary format

At the stopping point, print:

- โœ… Reviews โ€” <plain language>
- โœ… Checks (local) โ€” <plain language>
- <status> Checks (CI) โ€” stale after agent push; needs human re-trigger. Prior failures: <fixed | open | not reproducible locally>
- โœ… Mergeable โ€” <plain language>

Actions taken: <what changed in this run>
Hand-off: CI must be re-triggered by a maintainer (close/reopen PR, workflow_dispatch, or push) before merge.
Still needed: <human review, anything not actionable from the agent>

Status vocabulary:

  • โœ… satisfied โ€” checked and passing
  • โŒ failing โ€” checked and failing
  • โณ pending โ€” running, waiting for signal (rare for the agent; never use for the post-push CI state)
  • โ“ unknown โ€” could not be checked (API error, indeterminate, or CI stale after agent push). Never use โŒ for this.

Translate status into plain language. Don't write bare labels. Always state explicitly that CI on the agent's HEAD is unverified until a human re-triggers it.

Stopping conditions

  • Ready for merge (pending human CI re-trigger) โ€” local validation green, Reviews resolved, Mergeable clean. Summarize and stop.
  • Nothing actionable remains โ€” non-actionable blocker (human approval, external service). Summarize and stop.
  • Truly stuck โ€” unresolvable conflicts, ambiguous feedback, irreproducible failures. ask_user with context.

Completion standard

The task is complete only when all are true:

  • npm run build, npm run lint, npm test all pass (or unrelated pre-existing failures explicitly identified).
  • The copilot-review skill addressed all in-scope review threads, including GitHub Actions bot review comments/threads (github-actions[bot]) (reply + resolve succeeded for each).
  • Mergeable condition was checked; conflicts resolved and BEHIND updated when present.
  • Prior CI failures were inspected at the log level and either fixed at the root cause (with a local reproduction where possible) or explicitly flagged as not locally reproducible / escalated.
  • Every iteration that changed files was committed and pushed, and no local changes were left unpushed at stop. No post-push re-check loop.
  • A structured โœ…/โŒ/โณ/โ“ summary was printed, including an explicit hand-off line for the human CI re-trigger.
  • No gh pr merge was run.