Project setup#
pw_ghish: GitHub CLI-like interface for Gerrit code reviews and CI checks
Warning
NOT READY FOR EXTERNAL PROJECTS: pw_ghish is currently
experimental for upstream Pigweed and is not ready for adoption
outside Pigweed yet. Several Pigweed-specific assumptions still exist in
the codebase while multi-project abstractions are being completed. See
Status & roadmap for current status and planned work to
decouple project policies.
This page documents the build targets, repository wrapper pattern, and
ProjectProfile architecture used to configure gh-ish for Gerrit and
LUCI repositories.
Note
Looking to configure your personal AI coding assistant (Antigravity/Jetski, Claude Code, Codex, Cursor, or OpenCode) or install local pre-run tool hooks? See Agent setup.
Building and distributing gh-ish#
gh-ish is written in standard Go without external C library dependencies.
It can be built and distributed using Bazel, Go toolchains, or pre-built binary
packages.
Building with Bazel#
If your project uses Bazel, compile the binary target directly:
$ bazelisk build //pw_ghish:gh-ish
The compiled executable is placed in bazel-bin/pw_ghish/gh-ish_/gh-ish.
Building with standard Go#
You can compile and install gh-ish using the Go toolchain:
# Compile binary from source:
$ go build -o gh-ish ./pw_ghish/cmd/main.go
# Or install directly into $GOPATH/bin:
$ go install pigweed.dev/pw_ghish/cmd@latest
Distributing via CIPD or package managers#
For large multi-repo projects (such as Fuchsia or Chromium), gh-ish can be
packaged as a CIPD (Chrome Infrastructure Package Deployer) package or added to
host toolchains so developers and CI bots have it pre-installed on their
$PATH.
Creating a repository wrapper#
Rather than requiring every developer and AI coding agent to manually install
and update a global binary, we recommend placing a wrapper script named gh
at the root of your repository (e.g. ./gh).
Why use a repository wrapper?#
No global installation step: Contributors and coding agents can run
./gh pr listor./gh pr statusdirectly from a fresh checkout.Commit-pinned consistency: The wrapper builds or downloads the version of the tool matching the repository’s current commit.
Local binary caching: The wrapper builds the binary once per commit and caches it in a local output directory (e.g.
out/gh/) for subsequent runs.Standard CLI entry point: Coding agents can invoke
./ghfrom the checkout root using standard GitHub CLI subcommands.
Example wrapper implementation#
Here is an example wrapper script that builds and caches the binary:
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CACHE_DIR="${REPO_ROOT}/out/gh"
COMMIT_HASH="$(git -C "${REPO_ROOT}" rev-parse HEAD 2>/dev/null || echo "latest")"
CACHED_BIN="${CACHE_DIR}/gh-ish-${COMMIT_HASH}"
if [[ ! -x "${CACHED_BIN}" ]]; then
mkdir -p "${CACHE_DIR}"
# Build using Bazel or Go:
bazelisk build --noshow_progress //pw_ghish:gh-ish
cp -f "${REPO_ROOT}/bazel-bin/pw_ghish/gh-ish_/gh-ish" "${CACHED_BIN}"
chmod +x "${CACHED_BIN}"
fi
exec "${CACHED_BIN}" "$@"
Project Profile Architecture#
Every Gerrit project has unique review conventions: differing label names
(such as Code-Review vs. Commit-Queue vs. Auto-Submit), varying
presubmit gates, and dedicated LUCI build buckets.
pw_ghish abstracts these differences through Project Profiles.
Built-in profiles#
pw_ghish includes built-in profiles for common Google open-source projects:
Profile |
Gerrit Host Match |
Commit-Queue |
Code-Review |
Try Bucket |
|---|---|---|---|---|
pigweed |
|
|
|
|
fuchsia |
|
|
|
|
generic |
(fallback) |
(none) |
|
(custom) |
Auto-submit labels (such as Pigweed-Auto-Submit or Auto-Submit) do not
need to be configured in a profile: --auto queries Gerrit for the change’s
or project’s labels and votes the matching auto-submit label automatically.
Automatic profile detection#
pw_ghish automatically selects the appropriate profile by inspecting:
The Git remote URL (e.g.
origin) for the repository.The Gerrit review host hostname.
The Git config setting
ghish.profile.
Explicit profile override#
You can force a specific profile on any command using the --profile flag:
$ gh-ish pr list --profile fuchsia
$ gh-ish pr status --profile pigweed
Profile names are strictly validated. Passing an invalid profile name halts with an error listing all available profiles.
Adding a new project profile#
To add a profile for your project, implement the ProjectProfile interface in
pw_ghish/profile.go (or embed genericProfile for default behavior) and
register it with RegisterProfile:
type myProjectProfile struct {
genericProfile
}
func (p *myProjectProfile) Name() string {
return "myproject"
}
func (p *myProjectProfile) DefaultGerritHost() string {
return "https://myproject-review.googlesource.com/a"
}
func (p *myProjectProfile) CQLabel() (LabelVote, bool) {
return LabelVote{Name: "Commit-Queue", Value: 2}, true
}
func (p *myProjectProfile) BuildbucketProject() string {
return "myproject"
}
func init() {
RegisterProfile(&myProjectProfile{})
}
Add a test case in pw_ghish/profile_test.go verifying detection and behavior.
Authentication and Credential Setup#
./gh auth status checks credentials across Gerrit, LUCI Buildbucket, and
Google Issue Tracker (Buganizer), supporting both googler (internal +
public builders required) and community (public builders + .gitcookies
or anonymous reads) authentication modes.
For full details on authentication modes, credential lookup order, and
environment variables (GH_ISH_AUTH_MODE, GH_ISH_AUTH_METHOD,
GERRIT_TOKEN, LUCI_TOKEN), see Authentication (gh auth).
LUCI CI and Buildbucket Integration#
Projects using LUCI (such as Chromium, Fuchsia, Pigweed, and Android) can use Buildbucket integration for check inspection and reruns:
pRPC checks querying#
pw_ghish pr checks queries cr-buildbucket.appspot.com via pRPC to fetch
builder statuses, durations, and build URLs.
Terminal log inspection#
gh-ish run view --log-failed queries Buildbucket step summaries and step
log URLs to retrieve the tail of failed build steps in the terminal:
# Inspect step execution tree for a specific builder:
$ gh-ish run view -j myproject-linux-dbg
# Print failure summaries and step log snippets for failed builders:
$ gh-ish run view --log-failed
Builder reruns#
gh-ish run rerun automatically constructs and executes bb add commands
targeting your profile’s try bucket:
# Rerun all failed builders on the current change:
$ gh-ish run rerun --failed
# Rerun a specific builder:
$ gh-ish run rerun -j myproject-linux-dbg
# Preview the generated bb command without executing:
$ gh-ish run rerun --failed --dry-run