Every Go release has one question that matters more than the diff itself:
Did we break something users compile against?
A pull request can look harmless. A few files changed, a type moved, a method now returns an error, a struct field disappeared. The commit history may look clean. The changelog may sound reasonable.
But users do not depend on your commit messages.
They depend on your public Go API.
That is the purpose of relimpact: a small, fast tool that compares two Git refs and reports what changed in the exported Go API.
Not every file.
Not every commit.
Not every line.
Only the public API surface that users can import, call, implement, or compile against.
Why another report?
A raw git diff is great when you want to inspect implementation details.
A changelog is great when you want to explain a release to humans.
But neither of them is the best tool for answering:
Which public Go symbols changed between these two refs?
That question needs a different view.
For example, this is what matters before a release:
- func Load(path string) *Config
+ func Load(path string) (*Config, error)
That is not just “one line changed”.
That is a breaking API change.
And this is useful, but not breaking:
+ func FromEnv(prefix string) (*Config, error)
That is a new public API.
relimpact separates those two ideas clearly:
- Breaking changes: changed or removed public API.
- New API: compatible additions.
The result is a report that is easier to review in a pull request and easier to attach to a release.
It is not a diff tool
relimpact is intentionally narrow.
It does not try to replace git diff.
It does not generate a raw changelog.
It does not summarize commits.
It does not care how many commits happened between two refs.
Instead, it snapshots the exported Go API at one ref, snapshots it again at another ref, and compares the API surface.
That means the report is based on API changes between refs, not on commit messages.
This distinction matters.
A messy commit history can still produce a clean API report.
A small commit can still produce a breaking public API change.
That is the whole point.
What the report looks like
A Markdown report is designed for pull request comments.
It starts with a small compatibility summary, then puts breaking changes first:
There is also an HTML report for CI artifacts and release review, but Markdown is usually the best format for pull requests.
Add it to a GitHub pull request
Here is a simple GitHub Actions workflow that runs relimpact, generates a Markdown report, and posts it as a sticky pull request comment.
name: API compatibility
on:
pull_request:
branches: [ master ]
permissions:
contents: read
pull-requests: write
jobs:
relimpact:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: "1.25"
- name: Install relimpact
run: |
go install github.com/hashmap-kz/relimpact@latest
- name: Generate Markdown API report
run: |
relimpact \
--old="${{ github.event.pull_request.base.sha }}" \
--new="${{ github.event.pull_request.head.sha }}" \
--format=markdown \
--output api-report.md
- name: Comment API report on PR
uses: marocchino/sticky-pull-request-comment@v2
with:
header: relimpact-api-report
recreate: true
path: api-report.md
That is all.
Every pull request gets a public API compatibility report.
If nothing public has changed, the report stays quiet.
If a method signature changed, a field disappeared, or a new exported type appeared, reviewers see it without digging through implementation diffs.
HTML as a CI artifact
For release review, you may also want a browser-friendly report:
- name: Generate HTML API report
run: |
relimpact \
--old="${{ github.event.pull_request.base.sha }}" \
--new="${{ github.event.pull_request.head.sha }}" \
--format=html \
--output api-report.html
- name: Upload HTML API report
uses: actions/upload-artifact@v4
with:
name: api-report
path: api-report.html
The HTML report keeps the same structure as Markdown:
- verdict
- summary
- breaking changes
- new API
The difference is presentation: package navigation, cleaner grouping, and a better browser view.
Why this matters
Go makes public API changes feel deceptively simple.
Changing a return value is easy.
Removing a field is easy.
Renaming a method is easy.
But for users, those changes may mean failed builds, broken imports, or migration work.
relimpact makes that visible before the release.
It helps reviewers focus on the question that actually matters:
Are we changing the contract?
Easy to try
relimpact is a single binary.
No server.
No database.
No external service.
No AI.
It works from your Git repository and compares two refs:
relimpact --old=v1.0.0 --new=HEAD
Generate HTML:
relimpact --old=v1.0.0 --new=HEAD --format=html --output api-report.html
Install with Go:
go install github.com/hashmap-kz/relimpact@latest
The project is here:
https://github.com/hashmap-kz/relimpact
If the idea feels useful, starring the repository is always motivating. It helps show that small, focused Go tools still matter.



Top comments (0)