Greg Anderson, Open Source Contributor Reading estimate: 5 minutes
Don’t Fear the 1.0: Rational Project Management for Libraries using SemVer
Semantic versioning is widely used, and, for the most part, well understood, even by those who have not read the reference documentation on semver.org. The most important characteristic of a SemVer version is that the major version number is always incremented whenever any breaking changes are introduced, signaling clients that code modifications may be needed when updating to this version. When the major version of a project is zero, though, that signifies that the project is in a pre-release stage, and breaking changes may occur in any release. It makes a lot of sense for early development projects to stick to zero-based version numbers; sometimes, though, there is a curious phenomenon that occurs in very mature projects, where the project maintainer avoids making a 1.0.0 release, in some cases for years. When a project reaches this state, it is often the case that many of the releases actually do preserve backwards compatibility with the prior release. Using “zero dot” releases obscures this information, making it harder on clients that are following the project. The solution to this problem is to begin making stable releases so that compatible releases are clearly identifiable, as SemVer intended.
Image
Six Common Myths about SemVer Major Releases
There are some common SemVer myths that keep a project from making their first stable release. Most of these are based on the assumption that a stable release must resolve all of the issues that one might expect to find as a matter of course in a pre-release. This conclusion seems natural, but it turns out not to be entirely the case—at least, not quite. Some examples:
Myth #1: A major release is “done”.
The concept of “stable” should not be conflated with “finished”. Software is never truly done; some projects avoid tagging a stable release because they are chasing an ever-elusive list of features. A stable release should have viable use cases, but it does not need to meet every need in its problem space.
Myth #2: A major release is bug-free.
While a stable release should be largely usable, it is not necessary to resolve every open bug report prior to tagging 1.0.0.
Myth #3: A major release is a promise to provide support.
Some projects avoid making a stable release because they feel that they do not have time to increase the support levels they offer on the project. While support is an important consideration, those who rely on open source projects must eventually face the reality that there is not an unlimited quantity of volunteer support time available for every project. A certain amount of self-service is required when using open source projects. This fact should not hold up a stable release.
Myth #4: A new major release is a promise to maintain multiple versions.
Some open source projects do active development on a development branch such as `master` or `8.2.x`, and back-port bugfixes to previous release branches for important issues. This workflow is actually not as difficult as some make it out to be, but all the same, it is never a requirement. Tagging the 1.0.0 release does not mean that a maintainer needs to continue to provide releases for the users of the 0.x branch.
Myth #5: A new major release is required to break backwards compatibility.
If a project has been making releases on the 0.x branch for a long time, there is no need to wait for a breaking change before moving to 1.0.0-alpha1. If some 0.x release is deemed to be stable, it can be tagged as the 1.0.0 release with no further changes—except, perhaps, for some documentation updates.
Myth #6: The first major release must be 1.0.0
The numbers in a version string are just numbers; there is no semantic meaning to the numbers, beyond the fact that they increase monotonically along any branch. If a project really feels that there is too much implied pressure with a "perfect" 1.0.0 release, you can always start with something larger. For example, if your project advanced to 0.11.2 during the pre-release phase, it would be okay to make the first stable release 12.0.0. There would be no special significance to doing this; a 12.0.0 release is really no different than a 1.0.0 release. If it seems less scarey that way, though, then go ahead and do it.
When to Make the First Stable Release
As previously mentioned, it is important that a project should meet some standards of usability prior to making its first stable release. How then should a maintainer decide when to take this step? Here are some things to consider.
The project should have a README.md file that is comprehensive enough to describe how to install, test and use the project.
For projects still under active development, the current viability level and near-term roadmap for the project should be clearly communicated, so users are aware of their odds of encountering problems, and the frequency at which new major versions will be released.
There should be unit tests covering at least the core functionality of the project.
There should be a GitHub issue template and a contributing file telling users how to report issues and contribute pull requests.
The project should be functional enough to satisfy a few well-defined use cases (or perhaps even only one).
The final consideration for making a stable release is the expected rate of change of the public API. Ideally, a project’s API will undergo some scrutiny prior to the first stable release, and any unnecessary complexity or unclear naming conventions should be cleaned up. However, it is known that the two fundamentally hard problems of Computer Science are “cache invalidation”, “naming things” and “off-by-one errors”, so it is likely that things will continue to change in the API after the initial release. What is the right frequency for rolling out breaking changes to the API? This question will vary from project to project. For more mature projects, no more often than every six to twelve months is a good guideline. If important changes are being made to a more rapidly-developing project, new major releases can be rolled out more frequently. The important thing to realize, though, is that there is no minimum required waiting time between major releases. It is helpful to try to plan ahead, and not expose clients to unnecessary change; however, the fear that some future unknown event might require rolling out another major release too soon should not not prevent a project from making a release. Make the best plan possible, but be aware that mistakes can happen; if something comes up, send out an advisory and make a new release.
Maintaining a cadence of regular stable releases, punctuated with occasional new major releases is very helpful and important for vibrant and successful projects. If your project is already making releases that maintain backwards compatibility, but has not tagged a 1.0.0 yet, take the time to review your project roadmap, and plan for stable release.