A GitHub Action that automatically marks a draft pull request as ready for review once all required checks pass.
- You open a draft PR and add a trigger label (default:
Mark Ready When Ready) - This action watches for all required checks to complete successfully
- It pauses briefly, then watches again to catch any late-arriving checks
- It verifies results via the GitHub GraphQL API (paginated, handles large check suites)
- It confirms the PR has no merge conflicts
- If everything looks good, it marks the PR as ready for review and removes the label
This is especially useful for repos with long CI suites — open your PR as a draft, slap on the label, and walk away. The PR will be marked ready for review only when CI is fully green.
name: Mark PR Ready When Ready
on:
pull_request:
types: [opened, edited, labeled, unlabeled, synchronize]
permissions:
checks: read
contents: write
pull-requests: write
statuses: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
mark-ready:
name: Mark as ready after successful checks
runs-on: ubuntu-latest
if: |
contains(github.event.pull_request.labels.*.name, 'Mark Ready When Ready') &&
github.event.pull_request.draft == true
steps:
- name: Mark ready when ready
uses: kenyonj/mark-ready-when-ready@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}Important: The workflow must include
contents: write— without it,GITHUB_TOKENcannot call themarkPullRequestReadyForReviewGraphQL mutation and will fail withResource not accessible by integration.
For organizations or repos where GITHUB_TOKEN permissions are restricted by
policy, you can use a GitHub App token instead:
steps:
- name: Generate token
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Mark ready when ready
uses: kenyonj/mark-ready-when-ready@v1
with:
github-token: ${{ steps.generate-token.outputs.token }}| Input | Required | Default | Description |
|---|---|---|---|
github-token |
Yes | — | Token with permission to read checks and write to pull requests |
label |
No | Mark Ready When Ready |
The label that triggers the action |
pause-seconds |
No | 20 |
Seconds to pause between verification rounds (catches late-arriving checks) |
remove-label |
No | true |
Whether to remove the trigger label after marking the PR ready |
| Output | Description |
|---|---|
result |
ready, failing-checks, conflicting, or skipped |
failing-checks |
Names of required checks that failed (empty string if all passed) |
The workflow calling this action needs these permissions for GITHUB_TOKEN:
permissions:
checks: read
contents: write # required for markPullRequestReadyForReview
pull-requests: write
statuses: readNote:
contents: writeis required even though the action doesn't modify repository contents. Without it,GITHUB_TOKENcannot call themarkPullRequestReadyForReviewGraphQL mutation.
The action uses a "trust but verify" approach:
gh pr checks --watchwatches for required checks to complete- A configurable pause catches checks that are re-triggered or start late
gh pr checks --watchruns again to confirm everything is still green- A GraphQL query independently verifies that no required check suites have
failing conclusions (
ACTION_REQUIRED,TIMED_OUT,CANCELLED,FAILURE,STARTUP_FAILURE) and no required commit statuses are in aFAILUREstate - The mergeable state is checked to ensure the PR doesn't have conflicts
This multi-layered approach prevents marking a PR as ready when there are transient or late-arriving failures.