Code Review with GitHub PRs
Pull requests are the integration gate for Go module repos.
Search across all documentation pages
Pull requests are the integration gate for Go module repos.
Effective review keeps changes small, calls out go.mod impact, and verifies tests - not just style opinions.
A good Go PR states behavior change, module/API impact, and how tests were run.
Reviewers scan exported API deltas, error handling, concurrency, and dependency diffs before approving.
Large PRs stall trunk; slice by package or feature flag when possible.
Quick-reference recipe card - copy-paste ready.
PR title: internal/parse: reject empty input in Decode
PR body template:
## Summary
- Reject empty input in `Decode` with `ErrEmptyInput`
## Module impact
- No new dependencies
- Exported error var is a compatible addition
## Test plan
- [ ] go test ./...
- [ ] go vet ./...
- [ ] go mod tidy (no diff)
## Screenshots / logs
N/AWhen to reach for this:
Contributor opens a PR adding gRPC health checks:
// internal/health/grpc.go (excerpt)
package health
import "google.golang.org/grpc/health/grpc_health_v1"
func Register(s *grpc.Server) {
srv := grpc_health_v1.NewHealthServer()
grpc_health_v1.RegisterHealthServer(s, srv)
}# go.mod excerpt
+ google.golang.org/grpc v1.68.0Reviewer checklist:
go test ./... green in CI.internal/ across module boundary.Approval after author documents opt-out flag and tidy check passes.
What this demonstrates:
go.mod diff as first-class, not noise.main.GitHub's merge queue (optional) serializes merges to keep trunk green under load.
| Size | Lines (approx) | Review outcome |
|---|---|---|
| Small | under 200 | Same-day merge likely |
| Medium | 200-400 | Needs focused review time |
| Large | 400+ | Split unless mechanical rename |
Mechanical changes (go fix, generated protobuf refresh) may exceed limits if isolated and labeled.
| Area | Question |
|---|---|
| Exported symbols | Does this promise compatibility for module consumers? |
go.mod | New transitive weight? Version justified? |
internal/ | Any illegal cross-module internal import? |
| Errors | Wrapped with %w? Sentinel vs dynamic errors documented? |
| Concurrency | Goroutine lifecycle, context cancellation, data races? |
| Tests | Table-driven? Covers error paths? -race worth it? |
/v2 path or major bump?benchstat summary.Request changes for correctness, module safety, or missing tests.
Nit comments should be optional (nit: prefix).
Approve when issues are minor and trust author follow-up issues for debt.
go.sum bulk - Could hide supply-chain swap. Fix: read go mod why -m for new modules.gh pr checkout or trust CI matrix.| Alternative | Use When | Don't Use When |
|---|---|---|
| Pair programming | Complex design spike | Async distributed team |
| Stacked PRs | Sequential dependent changes | Reviewers lack stack tooling |
| CODEOWNERS auto-request | Large monorepo ownership | Tiny two-person library |
| Maintainer merge without PR | Emergency hotfix | Normal feature flow |
Target one logical change reviewers can hold in working memory.
Split refactors from behavior changes across PRs.
For risky changes, yes: gh pr checkout <n> then go test ./....
CI green is necessary but not always sufficient.
Check changelog and security advisories for bumped modules.
Run tests and inspect go mod why for unexpected paths.
breaking, module-deps, needs-changelog, security.
Filter release notes and review priority.
Prefer mechanical rename PR separate from behavior changes.
Easier review and cleaner bisect.
Use draft PRs.
Convert to ready only when description, tests, and tidy are complete.
Comment on generator inputs or Makefile targets, not *.pb.go lines directly.
Regenerate in follow-up commit.
Trace call paths from HTTP/gRPC handlers to background work.
Missing ctx.Done() checks are release blockers.
Yes for exported API or behavior consumers rely on.
Apps may use release notes only at tag time.
Within one business day keeps trunk flow healthy.
Set team SLA and rotate review duty.
Fine when required checks are strong and PR size limits enforced.
Avoid for dependency bumps without human glance.
List every touched go.mod.
Confirm workspace or replace directives are not accidentally committed.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 19, 2026