Skip to content

Releases: CAOShurong/willitbreak

v0.1.3

Choose a tag to compare

@github-actions github-actions released this 12 Aug 15:42
600ec93

What's Changed

  • Make --ascii escape Unicode report content by @CAOShurong in #5

Full Changelog: v0.1.2...v0.1.3

v0.1.2

Choose a tag to compare

@github-actions github-actions released this 11 Aug 09:11
89528af

What's Changed

  • Move GitHub Actions to Node 24 runtimes by @CAOShurong in #2
  • Confine cache paths and harden the v0.1.2 release by @CAOShurong in #3

Full Changelog: v0.1.1...v0.1.2

v0.1.1

Choose a tag to compare

@github-actions github-actions released this 09 Aug 02:44
1d541f4

What's Changed

New Contributors

Full Changelog: v0.1.0...v0.1.1

willitbreak 0.1.0 — does this upgrade break YOUR code?

Choose a tag to compare

@github-actions github-actions released this 03 Aug 11:48

Will this dependency upgrade break code you actually wrote?

Dependabot opens eleven pull requests. The changelog for one lists forty breaking changes. Thirty-nine are about parts of the library you have never imported, and the fortieth is on line 218 of a file you forgot existed.

pip install willitbreak
willitbreak urllib3 --to 2.2.1

report

284 API changes in that release. Two of them touch this code. Those two come with file and line numbers; the rest are a number you can ignore.

their API diff          your source            what you get
──────────────────      ─────────────────      ─────────────────────
284 things changed  ×   217 call sites     =   2 problems, with line numbers

Why this isn't just a changelog

Every other tool in this space is built for the people publishing a library, so it can tell you what changed but not whether you used any of it. griffe — the most capable of them — puts it plainly in its own documentation: users must review the reported breakages and assess their own codebase for impacts.

That assessment is the work. This does it.


What it takes seriously

Never guessing

A checker that cries wolf gets uninstalled after the second false alarm, and then catches nothing at all. Resolution stops the moment it would have to assume:

client = pkg.Client()
client.get(timeout=5)   # resolved: pkg.Client.get

thing = make_it()
thing.get(timeout=5)    # not reported — origin unprovable

c = pkg.Client()
c = something_else()
c.get(timeout=5)        # not reported — the name was rebound

The same applies to arguments. f(**options) might be passing the removed parameter, or might not, so it is never claimed as a break.

The condition attached to every change

A removed keyword only matters to code that passes it. A parameter that lost its default only matters to code that omits it — pass it positionally and you are fine. A parameter that became keyword-only only breaks callers who passed it positionally. Each condition is checked against the actual call site.

Where libraries really live

Almost every package implements in pkg/_client.py and exposes in pkg/__init__.py. A tool that only looked at where a class was defined would report pkg._client.Client and never match the pkg.Client everyone writes, so re-export chains are followed to a fixed point.

Not importing anything

Both versions are downloaded and read as source. Importing a package to inspect it means executing it — and the version you are asking about is by definition not the one installed. It may not even import on your interpreter.


In CI

- run: pip install willitbreak
- run: willitbreak urllib3 --to ${{ matrix.candidate }} src/

Exit 2 means this upgrade breaks something you wrote. Exit 1 is reserved for the tool itself failing, so a pipeline can act differently on each. Exit 0 means the changes do not reach your code.


Isn't this what mypy does?

Partly, and the overlap is worth being honest about. If a package ships type information, you install the new version, and your code is annotated, mypy will flag a removed attribute. The differences that matter:

  • You have to install the upgrade first — which is the thing you were trying to evaluate, and on a conflict it may not install at all.
  • It reports everything, not what changed. A pre-existing error and one introduced by this upgrade look identical.
  • It needs types. Untyped packages and **kwargs-heavy APIs are exactly where signature changes hide.

This answers a narrower question — what does this specific version bump do to me — without touching your environment.


88 tests. No dependencies. Python 3.9+, tested on Linux, Windows and macOS across 3.9–3.13.

Full documentation: https://github.com/CAOShurong/willitbreak

Full Changelog: https://github.com/CAOShurong/willitbreak/commits/v0.1.0