Skip to content

Lists all the changed Go packages that need testing for a merge.

License

Notifications You must be signed in to change notification settings

hpidcock/gochanged

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gochanged

gochanged lists Go packages that have untested changes compared to a base git branch, tag, or commit. It is intended for use in CI pipelines and local development workflows where running the full test suite is expensive and only the affected packages need to be tested.

Installing

go install github.com/hpidcock/gochanged@latest

Usage

gochanged [flags] [packages...]

The packages argument accepts standard Go package patterns (e.g. ./..., ./cmd/...). If no packages are specified, it defaults to ./....

gochanged prints one import path per line to stdout, making it suitable for use as input to go test or other tools via command substitution.

Flags

Flag Description
-b, --branch Git ref (branch, tag, or commit SHA) to diff against. Required.
--why Print an explanation to stderr for each package describing why it was selected.
-v, --version Print version and exit.

Examples

Run tests for all packages that changed compared to main:

go test $(gochanged -b main ./...)

Run tests against a specific remote branch:

go test $(gochanged -b origin/main ./...)

Run tests for changes in the last 5 commits:

go test $(gochanged -b HEAD~5 ./...)

Scope to a subtree of the module:

go test $(gochanged -b main ./cmd/...)

See why each package was selected:

gochanged -b main -why ./...

How It Works

gochanged determines which packages need testing through the following steps:

  1. Resolve packages. The requested package patterns are expanded using go list to obtain the full set of packages and their import graphs.

  2. Check for workspace mode. If a go.work file is active, all requested packages are printed unconditionally because dependency information across workspace modules is not tracked.

  3. Compare go.mod. The current go.mod is compared against the version at the base ref. If the Go language version (go directive) changed, all packages are printed. Otherwise, individual require and replace directives are compared to detect changed module dependencies.

  4. Diff files with git. git diff --name-status is run against the base ref to obtain the list of added, modified, deleted, and renamed files. Each changed file is classified as either a source change or a test-only change (_test.go files and anything under a testdata directory).

  5. Map files to packages. Changed directories are matched to their corresponding Go packages.

  6. Walk the import graph. A directed acyclic graph of package imports is built. For every directly changed package, gochanged walks the graph in reverse (from dependency to dependents) to find all transitively affected packages. Packages whose test imports (TestGoFiles or XTestGoFiles) reference an affected package are also marked.

  7. Print results. The final set of packages that need testing is printed to stdout, one per line. When --why is specified, the reason each package was selected is printed to stderr.

What counts as a change

  • A file was added, modified, deleted, or renamed compared to the base ref.
  • A module dependency version changed in go.mod.
  • A replace directive was added, removed, or modified in go.mod.
  • The go directive version changed in go.mod (causes all packages to be selected).
  • The module did not exist at the base ref (causes all packages to be selected).

Sub-packages

gochanged is composed of two internal library packages:

  • git — Wraps git commands for finding the repository root, reading files at a given ref, and computing file-level diffs.
  • packages — Wraps go list and go env to enumerate Go packages, resolve their imports, and detect workspace mode. Also defines the Package struct that mirrors the output of go list -json.

Requirements

  • Go toolchain (for go list and optionally running tests)
  • Git (the working directory must be inside a git repository)
  • All requested packages must belong to the same Go module

License

MIT — see LICENSE.

About

Lists all the changed Go packages that need testing for a merge.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages