Before you start
Merge queues are GitHub-only. Install the Trunk GitHub App on the repository, and create a merge queue for the branch you merge into. See Install and create your queue, or create the queue with the API.Concepts
- Queue entry: a pull request’s place in a merge queue, under
queueEntryon a pull request. Itsiddiffers from the pull request’sid. Endpoints under/v2/pull-requests/{id}take the pull request’sid. - Queue entry state:
notReady(submitted, but waiting on a requirement such as passing checks or impacted targets),pending(ready, waiting to test),testing,testsPassed, andpendingFailure. The final states aremerged,failed, andcancelled.queueEntry.readinessexplains anotReadyentry. ApendingFailureentry’s tests failed, and the queue holds it to learn whether the failure is its own, for example while the pull requests ahead of it finish. See Pending failure depth. - Verification run: one CI run the queue started to test a pull request, or a batch of them. When a batch fails, the queue splits it to find the culprit (bisection). Each split is its own verification run.
- Mode:
queuemode (Single in the app) puts pull requests in one line, each tested on top of the ones ahead of it, several at a time.graphmode (Parallel in the app) gives unrelated pull requests separate lines, based on the impacted targets CI uploads for each. - Priority: lower
priorityValuenumbers test first. The names areurgent(0),high(10),medium(100), andlow(200). Send a number aspriorityValueor a name aspriorityName. Without either, a pull request getsmedium(100).urgent(orpriorityValue: 0) restarts lower-priority pull requests that are already testing, so reserve it for emergencies. See Priority merging. - Direct to queue:
direct: truesends a pull request to the queue before its branch protection is satisfied. See Direct-to-Queue.
Authentication
Send an API key asAuthorization: Bearer <key>. A key with no permissions can read merge queues but can’t change them. Writes need the Merge Queue permissions listed on each step below.
A GitHub Actions job that uploads impacted targets can authenticate without a key.
Finding IDs
Endpoints address resources byid. Look IDs up once and store them:
- Queue:
GET /v2/merge-queueslists your organization’s queues, each with itsid,repositoryId,repositoryUrl, andtargetBranch. To list one repository’s queues, get its ID fromGET /v2/repositories?providerUrl=https://github.com/<owner>/<repo>(.data[0].id), then callGET /v2/merge-queues?repositoryId=<id>&targetBranch=<branch>. - Pull request:
GET /v2/pull-requests?repositoryId=…&number=…resolves up to 50 comma-separated pull request numbers at once (setlimit=50, since the default page is 25), or one headbranch. It finds only pull requests Trunk’s GitHub App has already seen. If you just opened one, retry shortly.
Submit and wait for a merge
Submitting needs a key with the Merge and cancel PRs permission. Submit takes the pull request’snumber in the body, so it needs only the queue’s ID and has no lookup delay:
201 response is the pull request; keep its id for polling.
- If the pull request is already queued here (not yet merged, failed, or cancelled), submit returns
409 PR_ALREADY_ENQUEUEDand changes nothing. Look up itsidinstead, using the queue’srepositoryIdfromGET /v2/merge-queues/{id}. - If Trunk can’t enqueue it, submit returns
422 PR_NOT_ENQUEUEABLEwith the reason inmessage. For example:- The pull request doesn’t exist.
- It targets a different branch from the queue’s. A stacked pull request may target another pull request’s branch, as long as the stack ends at the queue’s branch.
- A repository ruleset can block it.
- It’s still in another of the repository’s queues. Look up the pull request, read
queueEntry.mergeQueueId, and dequeue it there first.
- A closed pull request is accepted but stays
notReady.
GET /v2/pull-requests/{id} every 30 to 60 seconds until queueEntry.state is merged, failed, or cancelled, or subscribe to Merge Queue webhooks. The API itself has no webhooks.
- Read
queueEntry.state, not the top-levelstate, which is the pull request’s state on GitHub. queueEntry.statecan go back tonotReadybefore the entry ends. A push to the pull request sends a queued entry back tonotReadyto wait on the new commit, and a resubmitted pull request reuses its entry and starts again atnotReady. Keep polling.- Stop if
queueEntrydisappears or itsmergeQueueIdchanges, and report the outcome as unknown. This happens when a failed or cancelled pull request is submitted to another queue, or its queue is deleted. - Send the last response’s
ETaginIf-None-Match. If nothing changed, you get304with no body. - Set a deadline of your own. A pull request can stay
notReadyfor a long time; the queue cancels it only if itsnotReadyTimeoutMinutessetting is set. - Don’t stop when
ci.pollAfterSecondsisnull. It describes CI on the pull request’s own head commit, not its place in the queue.
direction=newest). The failure reason reference explains each reason. When a required check failed, failed.failureCausingChecks names the checks, and verificationRunId leads to the verification run and its checks.
Queue order
List order is not queue order. A queue’s pull request list is ordered by when each pull request was first submitted to the queue, newest first, and a resubmission doesn’t move it. For the order the queue will test pull requests in, useGET /v2/merge-queues/{id}/order. Its lists carry only each pull request’s id, number, title, sha, and url. For state or priority, match by id against GET /v2/merge-queues/{id}/pull-requests?state=pending,testing,testsPassed,pendingFailure.
Retrying
Writes don’t honorIdempotency-Key yet. A write that times out or returns a 5xx has an unknown outcome, so read the resource back before you retry it. A blind retry can, for example, restart a pull request’s tests twice. Some writes, such as PATCH …/config and PUT /v2/impacted-targets, set a value and are safe to repeat. See Status codes and errors.