gofasta verify
Runs every quality gate that CI runs, in order, and fails fast on the first failure. Acts as the single “am I done?” check for both humans and AI coding agents — one command, structured JSON output, non-zero exit on any check failure.
Usage
gofasta verify [flags]Run this command from the root directory of your Gofasta project.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--no-lint | bool | false | Skip golangci-lint (use if not installed or to speed up) |
--no-race | bool | false | Skip the race detector in go test |
--keep-going | bool | false | Continue after the first failure and report every result |
--since | string | (none) | Scope gofmt, go vet, golangci-lint, go test, and go build to only the packages affected by files changed since <git-ref> (e.g. HEAD~1, main, a SHA). Wire drift + routes always run full-project — they’re whole-project invariants. |
--changed | bool | false | Shortcut for “scope to working-tree + staged + untracked changes” (no committed comparison). Same scoping as --since but no ref needed. |
Inherits the global --json flag to emit one JSON object per check, suitable for agent consumption and CI automation.
Scoped verify (--since / --changed)
By default gofasta verify runs every step against ./.... Pass --since=<ref> or --changed to scope the per-package steps (fmt, vet, lint, test, build) to only the packages touched by your changeset — and the packages that transitively depend on them via the reverse-import graph. This is the per-PR fast path that drops a 90-second full preflight to ~10 seconds on a small change.
How it picks the package set:
git diff --name-only <ref>(or working-tree state for--changed) → changed files- Filter to
.gofiles → derive unique directories →go list ./<dir>→ root package set go list -deps ./...→ build the reverse-import graph → expand to every package that imports any of the roots
The test set is the expanded reverse-dep set; the build/vet/lint set is just the root packages. Files outside Go (.sql, .yaml, etc.) make scope.NonGoOnly=true and the per-package Go steps short-circuit as skip — only wire drift and routes still run.
Linter scope uses golangci-lint --new-from-rev=<ref> natively, so existing lint debt outside your change doesn’t fail the run.
Steps, in order
gofmt -s -l .— formattinggo vet ./...— compiler static checksgolangci-lint run— aggregate linter (skipped if not on$PATH)go test -race ./...— tests with the race detectorgo build ./...— every package compiles- Wire drift —
app/di/wire_gen.gois in sync with its inputs - Routes —
app/rest/routes/parses and has at least one entry
Each step blocks the next; fail-fast is the default. Pass --keep-going to run every step regardless of failures.
Examples
Full preflight, text output:
$ gofasta verify
✓ gofmt (12ms)
✓ go vet (240ms)
✓ golangci-lint (3421ms)
✓ go test (8920ms)
✓ go build (1810ms)
✓ wire drift (4ms)
✓ routes (6ms)
7 passed · 0 failed · 0 skipped · 14413msStructured JSON for agent consumption:
$ gofasta verify --json | jq '.checks[] | select(.status == "fail")'Skip the linter on a machine without golangci-lint installed:
gofasta verify --no-lintRun every check and report every result (useful for diagnosing multiple issues at once):
gofasta verify --keep-goingOutput shape (JSON)
{
"checks": [
{ "name": "gofmt", "status": "pass", "duration_ms": 12 },
{ "name": "go vet", "status": "pass", "duration_ms": 240 },
{ "name": "go test", "status": "fail",
"message": "tests failed",
"output": "--- FAIL: TestFoo ...",
"duration_ms": 3200 }
],
"passed": 2,
"failed": 1,
"skipped": 0,
"duration_ms": 3452
}Fields are stable API — AI agents and CI pipelines consume them.
Why this exists
Agents and humans commonly finish a task having run only one of the quality gates (usually go test). gofasta verify collapses every gate into one invocation, so the pre-commit check is always complete. Mirrors the make preflight target in the CLI and library repos — same contract, same mental model.