The life of a pull request in the queue

The states of a pull request in a CIHub queue, what moves it from one state to the next, and what CIHub shows on GitHub at each step.

A pull request enters the queue of its base branch when someone submits it (Submit, cancel and restart a pull request). From there, CIHub tells it where it stands on the pull request itself: you never need to open the dashboard to know why a pull request waits.

What CIHub writes on a pull request

acme-cihubbotcommented

🧪 Testing · position 2 in the queue for main

Tested on top of #118, #119 in #130.

Open in CIHub

▸ History (3)

/cihub restart to test again · /cihub cancel to leave the queue

CIHub Merge Queue (main)Testing, position 2Details
CIHub Conditions (main)Ready for the queue
The comment of CIHub, edited at each change, and its two statuses in the checks of the pull request.
WhereWhat it says
One comment, edited in placeThe state and its reason, what blocks the pull request, the failing checks, the pull requests it is tested with, a link to its test (the draft pull request of the run, or the test commit), a link to its page in the dashboard, its history in the queue, and the commands that apply now
The commit status CIHub Merge Queue (<branch>)pending while the pull request waits or is tested, success once its tests passed, failure when it failed, error when it was cancelled. Its link opens the page of the pull request in the dashboard
The commit status CIHub Conditions (<branch>)On every open pull request of a branch with a queue, submitted or not: whether it would enter the queue now. success reads "Ready for the queue"; pending means that a required check still runs; failure gives the first reason
Labels, if you turn them oncihub:queued, cihub:testing and cihub:failed, with state_labels_enabled: true in .cihub.yaml

When a pull request is opened out of draft on a branch with a queue, the comment welcomes it with a checkbox that submits it. Do not make CIHub Conditions (<branch>) a required check: a pull request whose conditions pass would then merge outside the queue.

The states of a pull request

The comment shows a state line; the API, the command line and the webhooks use the code of the state.

Waitingnot_readyQueuedpendingTestingtestingTests passedtests_passedMergedmergedTests failedpending_failureFailedfailedCancelledcancelledmeets the rulesroom in the windowchecks passPRs ahead mergeda required check failsits own faulta PR ahead faileda push, a close, /cihub cancel…from any state before Merged
The usual path, left to right. A failed test waits for the pull requests ahead before it decides whose fault it is.
StateThe comment showsWhat happens
not_ready⏳ Waiting · not in the queue for main yetSubmitted, but it cannot enter the line yet: a review, a check or a condition is missing
pending🕓 Queued · position 3 in the queue for mainIn the line, it waits for room among the tests that run
testing🧪 Testing · position 2 in the queue for mainIts test runs, alone or in a batch, on top of the target branch and of every pull request ahead of it
pending_failure⚠️ Tests failed · waiting for the PRs ahead before it failsIts test failed; the queue waits for the pull requests ahead of it to know whether the cause is its own
tests_passed🚀 Tests passed · merging into mainIts test passed; it merges as soon as the pull requests ahead of it merged
merged✅ Merged into main by the queueThe queue merged it, as its own commit, with the merge_method of the queue
failed❌ Failed · the reasonIt left the queue; submit it again after a fix
cancelled⚪ Cancelled · the reasonIt left the queue without a fault of its tests

The status CIHub Merge Queue (<branch>) says the same in short: "Testing, position 2", "Failed: a required check failed".

merged, failed and cancelled are final: a pull request that left the queue enters it again only with a new submission.

Why a pull request waits to enter the line

A submitted pull request stays not_ready while GitHub would refuse to merge it, or while it does not meet the queue_conditions of the queue. The comment says what is missing:

The comment saysWhat to do
1 of 2 required approvalsGet the reviews that the rules of the branch require
a review asks for changesAddress the review, then ask for a new one
the required check build failedFix the pull request; the check runs again on its new commit
the required check build has not reportedThe check never ran on this commit: see Run your CI on the tests of the queue
the required check build is queued, or is runningNothing: the pull request enters the line when the check passes
the branch is behind its baseThe rules of the branch ask that a pull request be up to date: turn that rule off
the branch conflicts with its baseMerge or rebase the base branch into the pull request
the queue conditions labels: ready are not metMeet the queue_conditions of .cihub.yaml
the SCM does not say yet why the PR is blockedNothing: GitHub computes the mergeability later, and CIHub reads it again

The conditions count only before the pull request enters the line: a condition that becomes false later does not take it out. A pull request that stays not_ready for 7 days (not_ready_timeout_hours: 168) is cancelled.

How the test of a pull request decides

CIHub never merges what it did not test. For each test, it builds a commit that holds the head of the target branch, every pull request ahead in the line, and the pull requests of the test, on a branch named cihub-merge/pr-<number>/<run id>. Your CI tests that commit (Run your CI on the tests of the queue).

mainhead of mainahead in the line#118#119#121this PRtest commitcihub-merge/pr-121/run_…Your CIbuildtest
The test of #121 holds the head of main, the pull requests ahead of it in the line, and #121. What passes is exactly what lands.
  • The test passes when every required check concludes with success, neutral or skipped.
  • The test fails at the first required check that concludes otherwise.
  • The test times out after testing_timeout_minutes (300 by default), for example when a required check never reports.

When a test fails, the pull request moves to pending_failure and the queue waits for the pull requests ahead of it. If one of them fails, the cause was there: the pull request is tested again without it. If they all merge, the fault is the pull request's own: the queue first runs its test again, once by default (failure_budget.retries), because one failure can be a flaky test. A failed batch is split in two to find the pull request that broke it (Choose a strategy).

What tests a pull request again

A test is valid only while the commit that it tested is still the one that would land. The queue starts the test of a pull request again, and the comment gives the reason, when:

  • a push outside the queue changed the target branch;
  • a PR ahead in the queue failed, was cancelled, or was merged outside the queue;
  • a PR of the same batch left the queue;
  • an urgent PR went to the front of the queue;
  • a user restarted the tests (/cihub restart).

What takes a pull request out of the queue

The status saysCause
Cancelled: the PR received a new commit after its submissionA push on the pull request. With resubmit_on_push: true, the queue submits it again at the end of the line
Cancelled: the base branch of the PR changedThe pull request now targets another branch, which has its own queue
Cancelled: the PR became a draftMark it ready for review, then submit it again
Cancelled: the PR was closedReopen it, then submit it again
Cancelled: the label that submitted the PR was removedThe submission label was removed
Cancelled: a user asked for it/cihub cancel, the command line or the dashboard
Failed: a required check failedThe test failed after its retries, and the pull requests ahead of it merged
Failed: the PR conflicts with the target branch or with a PR ahead of itUpdate the pull request once the other one merged
Failed: the tests took longer than the time limitSee Troubleshooting
Failed: branch protection refused the mergeSee Troubleshooting
Failed: the PR changed between its tests and its mergeA push between the test and the merge; submit it again

The full list of reasons, with their codes, is the Reason schema of the API.

On this page

For agentsThis page as Markdown:/docs/pull-requests.md