I managed to break one of my codebase (the
master branch) without even
If you think about, the “issue” I ran into is trivial. It really is. Though, I want to write about it because often, these things get too little attention in my opinion.
So what did I do?
I maintain this project task-hookrs. The project itself depends on a few other crates. I updated these dependencies and then released a new version of my crate.
The rewrite included some lines which I had to change, not a big deal
One of my dependencies, namingly serde had
a breaking change from
0.8.0 which resulted in a small rewrite of a
portion of my code.
No functionality was changed, though.
0.2.2 after the dependencies were upgraded. The last version
before that version was
And despite me not changing any functionality, the micro-release was a
Not because API changes (which I didn’t have) but because of link-time
My other project, imag dependes on task-hookrs, but
the dependency specification states
task-hookrs = "0.2" (note the missing
.1 at the end).
master of imag got rebuild, it failed because imag itself depends
uuid = "0.2", whereas task-hookrs now depended on
uuid = "0.3" - the
linker failed because the types I passed from imag to task-hookrs were
What did I do? Well, I updated
uuid in imag as well, everything solved.
But that really got me thinking.
What I should have done: Updating the
minor version (
0.2.1 -> 0.3.0).
We talk a lot about breaking changes in APIs and such, in fact this is why we introduced semantic versioning in the Rust community. What we do not talk about is that dependencies are also relevant when updating. Even the semantic versioning website states:
Given a version number MAJOR.MINOR.PATCH, increment the:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards-compatible manner, and
- PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
Which clearly states that
MAJOR version when you make incompatible API
changes - though nobody tells you that updating a dependency of your library
might also be a incompatible API change!
After all I’m (kinda) safe here, because the semantic versioning spec also contains the following:
Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.
So nobody can blame me. Although this really bugs me and it really shouldn’t have happened.