Skip to content

feat(ci): add PR readiness helper bot#16231

Draft
Joibel wants to merge 6 commits into
argoproj:mainfrom
Joibel:pr-readiness-helper
Draft

feat(ci): add PR readiness helper bot#16231
Joibel wants to merge 6 commits into
argoproj:mainfrom
Joibel:pr-readiness-helper

Conversation

@Joibel

@Joibel Joibel commented Jun 5, 2026

Copy link
Copy Markdown
Member

Motivation

Maintainer burden is high partly because PRs sit in a not-ready-for-review state for reasons the contributor could fix themselves — lint/codegen/docs failures, non-conventional titles, missing DCO sign-off, missing .features/ files, and unfilled PR descriptions. Unit/E2E tests are too flaky to be a readiness signal, but the other checks are deterministic and have documented fixes. This bot turns those signals into one actionable comment for the contributor, so maintainers only see PRs once they're genuinely reviewable.

Modifications

Adds a standalone workflow_run-triggered workflow (pr-readiness.yaml) that fires when CI / Docs / PR Title Check / PR Feature Check complete on a PR, plus its logic under .github/pr-readiness/:

  • Maintains one sticky comment per PR listing only the contributor-fixable failures, each with the fix command (make pre-commit -B etc.) and a log link; edits to a ✅ all-clear when resolved; never posts on PRs that never had an issue.
  • Judges PR template compliance via GitHub Models (actions/ai-inference, models: read) — advisory, schema-validated, fail-closed on errors/rate limits, output sanitised (mentions neutralised, issue-closing keywords redacted).
  • Converts blocking PRs to draft (never undrafts — that stays human), at most once per head SHA so a maintainer re-marking ready is respected.
  • Skips PRs from anyone in OWNERS and from bots. Ignores unit/E2E results entirely.
  • Security: runs only the default-branch definition, never checks out PR code, permissions: {} with minimal job grants, PR-controlled strings handled as data, actions SHA-pinned. Fork PRs are matched by head SHA (workflow_run.pull_requests is empty for forks).
  • Ships with DRY_RUN: "true" — decisions render to the job step summary only, for a observation period before going live.

Maintainers tune guidance/coverage in checks.config.json (pure data); design and rollout notes in .github/pr-readiness/README.md.

Verification

  • 39 unit tests, no dependencies: node --test '.github/pr-readiness/test/*.test.js'
  • actionlint clean; all actions pinned to full commit SHAs.
  • Test flight in the Joibel fork with seeded PRs (bad title + empty description, lint failure, clean control): PR resolution, author gating, event-guard for non-PR runs, and the title-failure + empty-description → comment+draft decision all verified from run logs; remaining cases under observation.

Documentation

.github/pr-readiness/README.md documents behaviour, the security model, dry-run rollout, and maintenance (check-name drift detection, workflow-name coupling). Not user-facing, so no docs/ changes.

AI

This PR was developed with Claude Code (design research, implementation, tests, and this description), reviewed and directed by a human maintainer.

Joibel and others added 3 commits June 5, 2026 15:26
Adds a standalone workflow_run-triggered bot that maintains a single
sticky comment on PRs guiding contributors through contributor-fixable
CI failures (lint, codegen, UI, build, docs, title, feature files, DCO)
and PR template compliance (judged via GitHub Models, advisory and
fail-closed). Blocking issues also move the PR to draft; the bot never
undrafts. PRs from OWNERS members and bots are skipped, and unit/E2E
test results are deliberately ignored as too flaky to be a readiness
signal.

Runs entirely from the default branch with minimal permissions, never
executes PR-head code, and treats PR-controlled strings as data only.
Ships with DRY_RUN=true: decisions render to the job step summary until
the comment behaviour has been validated on real PRs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alan Clucas <alan@clucas.org>
Step summaries are only visible in the Actions UI; emit the signal
states, AI verdict and comment/draft decision (and the rendered comment
when applicable) to the job log as well so runs can be inspected via
the API.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alan Clucas <alan@clucas.org>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alan Clucas <alan@clucas.org>
@Joibel Joibel changed the title ci: add PR readiness helper bot feat(ci): add PR readiness helper bot Jun 5, 2026
@Joibel Joibel added the area/contributing Contributing docs, ownership, etc. Also devtools like devcontainer and Nix label Jun 5, 2026
Joibel and others added 3 commits June 5, 2026 16:08
Fork test flight showed gpt-4o-mini hallucinating template violations
on compliant PRs: claiming "#TODO" was present in descriptions with no
Fixes line at all, and rejecting AI sections that genuinely declared
tool use because they did not say "None". Since the verdict gates draft
conversion, false non-compliance is the expensive direction.

Rewrite the prompt to be compliant-by-default, require verbatim
evidence before flagging, and spell out the Fixes-line-absent and
AI-declared-use cases explicitly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alan Clucas <alan@clucas.org>
All bot PRs (dependabot, renovate, the cherry-pick app) bypass the
readiness helper entirely — the author gate runs before any GitHub
Models call, so bot PRs never spend inference quota. Add the actual
bot logins to the exemption test so this cannot regress silently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alan Clucas <alan@clucas.org>
Live fork testing confirmed the default Actions token cannot run
convertPullRequestToDraft ("Resource not accessible by integration").
Mint an app installation token (same create-github-app-token pattern
as the cherry-pick bot) when PR_READINESS_APP_ID /
PR_READINESS_APP_PRIVATE_KEY secrets are configured, and use it only
for the draft mutation. Without the secrets the bot still comments and
logs a warning instead of drafting. The app needs only Pull requests:
Read & write.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alan Clucas <alan@clucas.org>
@Joibel Joibel marked this pull request as ready for review June 7, 2026 17:36
@Joibel Joibel requested review from a team as code owners June 7, 2026 17:36
@Joibel Joibel marked this pull request as draft June 9, 2026 16:40
@Joibel

Joibel commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

I should convert this to ts rather than js


- name: Resolve PR and classify checks
id: prepare
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0

@MasonM MasonM Jun 9, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: You can shell out to node to run TypeScript, since it natively supports running TypeScript via type stripping now: https://nodejs.org/learn/typescript/run-natively

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/contributing Contributing docs, ownership, etc. Also devtools like devcontainer and Nix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants