Life of a PR#
pw_ghish: GitHub CLI-like interface for Gerrit code reviews and CI checks
This guide walks through the end-to-end lifecycle of a Gerrit change in Pigweed
using ./gh: creating a change, running LUCI presubmits, iterating on review
feedback, and landing the change through the Commit Queue.
How Gerrit + LUCI differs from GitHub#
If you are used to GitHub pull requests, keep three differences in mind:
One commit per CL: A Gerrit Change List (CL) is a single Git commit identified by a
Change-Id: I...trailer in its commit message. To update a CL after review feedback, you amend your commit (git commit --amend) and run./gh pr pushto upload a new patchset.Tryjobs run on demand (
--cq): Pushing a patchset does not always run the full presubmit suite automatically. Passing--cq(Commit-Queue+1) starts a LUCI presubmit dry run.Changes land via Commit-Queue or Auto-Submit: Rather than clicking a direct merge button, changes land when they have
Code-Review+2approval and pass aCommit-Queue+2verification run (triggered automatically via--autoor explicitly via./gh pr merge --cq).
Step 1: Commit locally and link a bug ID#
Create a branch (or allocate an isolated worktree slot with
./gh wt use <name>), make your edits, and create a Git commit:
$ git checkout -b fix-ring-buffer
$ git commit -am "pw_ring_buffer: Fix off-by-one in Peek()"
If you need to file a new Buganizer issue and add its Bug: b/<id> trailer
to your commit in one step:
$ ./gh issue create \
--title "pw_ring_buffer: Off-by-one in Peek()" \
--body "Peek() drops the final byte when buffer is full." \
--amend
Or, if an issue already exists, include Bug: b/<id> in your commit message
(or add it later with ./gh pr edit --bug b/123456).
Step 2: Create the CL and start a CQ dry run#
Upload your commit to Gerrit as a new CL, request a reviewer, start a
Commit-Queue dry run (--cq), and enable auto-submit (--auto):
$ ./gh pr create -r "reviewer@google.com" --cq --auto
What this command does:
Installs the Gerrit
commit-msghook and adds aChange-Id:footer if your commit does not have one yet.Pushes
HEADtorefs/for/mainto create Patchset 1.Adds
reviewer@google.comas a reviewer.Votes
Commit-Queue+1(--cq) to start LUCI presubmit tryjobs.Votes
Pigweed-Auto-Submit+1(--auto) so the CL will automatically land once a reviewer approves it withCode-Review+2and tryjobs pass.
Step 3: Watch tryjobs and fix CI failures#
Monitor the presubmit dry run from your terminal:
$ ./gh pr checks --watch --fail-fast
If a blocking builder fails, --fail-fast exits immediately and prints the
failing step summary and log snippet. You can also inspect any builder on
demand:
# Inspect the step execution tree for a specific builder:
$ ./gh run view -j pigweed-lintformat
# Print failure summaries and step log excerpts for all failed builders:
$ ./gh run view --log-failed
To fix a CI failure and upload Patchset 2:
# 1. Fix the issue and amend your local commit:
$ ./pw format --fix
$ git commit -a --amend --no-edit
# 2. Upload the new patchset and restart the CQ dry run:
$ ./gh pr push --cq
Step 4: Respond to inline reviewer feedback#
Check your review dashboard or read inline reviewer comments on your branch’s active CL:
$ ./gh pr status
$ ./gh pr view --comments
./gh pr view --comments prints each review thread with its file path, line
number, and resolution state.
As you address each comment:
Stage inline replies and mark threads resolved: Pass
--pathand--lineto reply directly inside the existing thread. Use--draftto stage replies privately while you work:$ ./gh pr comment --path pw_ring_buffer/ring_buffer.cc --line 84 \ -m "Switched to pw::Result<ConstByteSpan>." --resolved --draft
Amend your commit and push the new patchset: Pass
--publishto publish all your staged draft replies together with the new patchset, and--cqto start a fresh dry run:$ git commit -a --amend --no-edit $ ./gh pr push --publish --cq
Step 5: Land (merge) the change#
Once a reviewer grants Code-Review+2, there are two ways the CL lands:
Automatic submission (if you enabled
--auto): BecausePigweed-Auto-Submit+1is set, LUCI automatically triggersCommit-Queue+2as soon asCode-Review+2is applied, rebases your CL onto the tip ofmain, runs any remaining verification, and merges it.Explicit submission (via
pr merge): If you did not set--autoearlier, enable it or triggerCommit-Queue+2directly:# Option A: Enable auto-submit (lands as soon as CR+2 and CQ pass): $ ./gh pr merge --auto # Option B: Vote Commit-Queue+2 directly (requires CR+2 to be present): $ ./gh pr merge --cq
Quick lookup: --cq, --auto, & merge#
Because Gerrit separates code upload from Commit-Queue voting, the same labels
can be set either while uploading a patchset (pr create / pr push)
or on an already-uploaded CL (pr review / pr merge):
Goal |
While uploading code |
Without uploading code |
|---|---|---|
Run presubmit tryjobs (dry run) |
|
|
Arm auto-submit ( |
|
|
Submit via Commit Queue ( |
|
|
Immediate REST submit (all gates green) |
(n/a) |
|