1. Our current two digit versioning scheme (e.g., 7.1, 7.2, ..., 7.22) doesn't make it clear how big/interesting/risky/urgent a particular update is. For example:
- Drupal 7.17 fixed some bugs, added new features, added new hooks, and more.
- 7.18, 7.19, and 7.20 were security only fixes.
- 7.21 fixed a regression introduced by 7.20, but was not itself a security fix.
- 7.22 fixed and added a bunch of stuff, including a BC break.
While this information is readily available in the release notes, it's not at all communicated in the version number itself.
2. Even with the loosened rules for what can be backported to an already released major version, we are still very conservative about backwards compatibility and non-trivial additions, which means many improvements that people would be excited to work on won't make their way into a Drupal version that people actually use until the next major version of core is released (and adopted). Up until Drupal 6, major releases were rarely if ever more than 1 year apart. But D7 took 3 years, and D8 is looking to be at least that long as well. One of the things discussed in DrupalCon Portland's Making core development sustainable core conversation was that a lot of employers/clients don't want to fund work that will take more than a year before it's usable by the business, and similarly, something that far out isn't always that attractive for people to work on in their free time either.
Semantic versioning specification
Switch to a three digit versioning scheme, following the Semantic versioning specification as closely as possible. The specification leaves a couple things open for the project to decide. Here's how we propose Drupal apply them:
Software using Semantic Versioning MUST declare a public API. This API could be declared in the code itself or exist strictly in documentation. However it is done, it should be precise and comprehensive...Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API.
What is public API
For purposes of this, we propose defining "the public API" as:
- Methods (and their signatures) that are defined in interfaces.
- Hooks (and their signatures).
- Theme hooks and their variables that are defined in the 'variables' or 'render element' entry of the corresponding hook_theme() implementation.
- Form and render element types and their properties that are defined in the corresponding hook_element_info() implementation.
What is not public API
While precise, it is not "comprehensive". Examples of things not included:
- Public methods of classes without interfaces. For example, most plugin managers, and other services intended more for internal rather than external use.
- Protected methods of base classes. However, we know that some base classes will be commonly extended by contrib modules.
- The complete detail of $form within hook_form_FORM_ID_alter() implementations.
- Additional variables (those not defined by the hook_theme() entry) added to $variables within a hook_preprocess_THEME_HOOK() implementation, even though later running preprocess functions might make use of those additional variables.
- The order in which hooks are executed.
- Database and configuration schema.
- Settings available in settings.php.
Changes to the above are all potential BC breaks, and we may want to consider carefully if and when to allow them, but for purposes of SemVer, we propose limiting the definition of "the public API" to the earlier list, so as to provide the most flexibility for what we later want to allow into 8.x. Note that the specification says "should be comprehensive", not "must be comprehensive".
API breaks to resolve critical issues
Also, if a change to even the limited public API is needed to resolve a critical issue, then we will allow it, as per our current policy, without necessarily raising the major version. That would be a clear violation of "Major version X MUST be incremented". However, given what's in the definition of the public API, it's unlikely for that to be needed.
Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced to the public API. It MUST be incremented if any public API functionality is marked as deprecated. It MAY be incremented if substantial new functionality or improvements are introduced within the private code. It MAY include patch level changes.
If we choose to follow the "MUST" portion of this, it means that if a security fix requires an API addition, then we still need to increment the Y version. Which means, the version number alone wouldn't convey meaning as to whether something includes a security fix. Similarly, a benefit to increasing Y is that you can (but don't have to) release small fixes to Y-1 via the Z number. However, if such a small fix is not itself a security fix (e.g., 7.21), then again, the version number alone doesn't tell you whether it's a security fix.
This would allow us to make a radical shift in the release cycle, starting with Drupal 8.0.0. Crell gave a talk on this at DrupalCon https://prague2013.drupal.org/session/future-friendly-evolution-and-drup...
This is catch's slightly different suggestion after lots of discussion both before and after the talk - so not a 1-1 summary of that talk but the principles are similar.
The primary change is that we would not open Drupal 9 immediately after Drupal 8 is released. Instead we would continue to add features and API additions to Drupal 8 - since semantic versioning would allow us the minor backwards compatibility breaks this requires. We'd then line up the changes that we really want to do in Drupal 9, and can only do there (a major refactor of form API is an example of a change that's been discussed for 9.x, and could not go into an 8.x.x release). Once those changes really need a 9.x core branch open (i.e. to commit an initial patch and start on conversions), then and only then, would we open the 9.x branch. 9.x primarily focuses on changes that actually require BC breaks, since new features/API additions can go into later 9.x.x releases anyway - doesn't matter if they miss the boat.
Another big change is that instead of supporting 3 major Drupal versions for security (i.e. direct security team support for 6.x and 7.x at the moment, then 8.x forward ports in the public queue), we'd support a particular x.y LTS for a fixed period. The security team supports LTS releases plus the latest stable, it does not support older, non-LTS releases at all.
A possible timeline might look like this, the exact time between releases, what exactly LTS and non-LTS releases mean and how long they're supported for is all up for discussion, but this particular schedule came up as one which might reduce the impact on the security team and core branch maintainer workload compared to some other possibilities.
Year 0 Month 0 - Drupal 8.0.0 (LTS) released.
Year 0 Month 6 - Drupal 8.1.0 released (with migrate upgrade path, this gives us a chance to refine it before the next LTS if we have to, without supporting that code forever).
Year 1 Month 0 - Drupal 8.2.0 (LTS) released.
Year 1 Month 6 - Drupal 8.3.0 released.
Year 1 Month X - Drupal 9 branch opens (NOTE COMPLETELY ARBITRARY DATE THIS COULD BE EARLIER OR LATER). Now Drupal 8 patches start getting committed to 9.x first).
Year 2 Month 0 - Drupal 8.4.0 LTS released
Year 2 Month 6 - Drupal 8.5.0 released
Year 3 Month x - Drupal 9.0.0 LTS released (when it's ready NOTE COMPLETELY arbitrary date again). Drupal 8 stays on 8.5.0 (not sure about this bit)
Year 3 Month 6 - Drupal 9.1.0
Year 4 Month 0 - Drupal 9.2.0 LTS is released, and Drupal 8.0.x is dropped. If you're still on 8.0.x, you can update to 8.2.x and have LTS support for another year - should be a relatively small upgrade that lots of other sites will already be running.
Year 5 Month X - Drupal 10 branch opens)
1 LTS release per year, each LTS release is usable for four years.
Implications for the security team
Security team supports a maximum of 5 branches at any time (up from 3).
However most of the time it only has to deal with two major API versions at a time - there'd be a shorter window when both 8.x.0 is supported and 10.x is under development compared to now with Drupal 6 and Drupal 8 when that window is 3+ years. Since 8.0.0, 8.2.0, 8.4.0 will have smaller changes, backporting security fixes, while it might not always be a cherry pick, ought to be more predictable than from 8.x to 7.x to 6.x
Implications for site owners
Actual sites know exactly how long they can stay on an LTS release - so there is no more guessing when support will be dropped since it doesn't depend on when the latest version comes out. Additionally the required upgrade will not be to 9.x, but to a later 8.x release - a much smaller jump - so in practice if you started on 8.0.0, you might get 5+ years on some kind of 8.x.x branch.
The only exception for this would be those sites which are built on the last x.y.z LTS release - since when that's dropped the next step is straight to the next major version, but you still get four years, unlike if you launched a Drupal 6.x site in 2014 when support would immediately be dropped.
Implications for contributed module authors
(fill me in)
Implications for core contributors
(fill me in)
Implications for core maintainers
(fill me in)
- Per above, this proposal doesn't achieve the goal of conveying how urgent an update is based on its version number. It might, however, help to convey how big/interesting/risky it is.
- The key benefit of the Y digit is that you can then support (release fixes for) multiple Y versions. That allows you to be less conservative about what you include in minor releases, which is one of this issue's key goals. However, our security team is currently stretched too thin already, and based on the comments in this issue, is unable to support security fixes for multiple minor versions (see #19, #22, #65). Without that benefit, there's concern that implementing this proposal would involve a lot of infrastructure work to d.o., project module, update manager, etc. with insufficient benefit.
- Decide if this switch is worth doing
- If so, figure out what would need to happen to get it done