Skip to content

Commit b92632e

Browse files
1ucian0mtreinish
andauthored
Qiskit release cycle and versioning (#34)
Co-authored-by: Matthew Treinish <mtreinish@kortar.org> --------- Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
1 parent 395f8e4 commit b92632e

File tree

1 file changed

+353
-0
lines changed

1 file changed

+353
-0
lines changed

####-release_cycle.md

+353
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
# Qiskit release cycle and versioning
2+
3+
| **Status** | **Proposed/Accepted/Deprecated** |
4+
|:------------------|:---------------------------------------------|
5+
| **RFC #** | #### |
6+
| **Authors** | [Luciano Bello](https://github.com/1ucian0/) and the Qiskit development team |
7+
| **Submitted** | 2023-11-21 |
8+
9+
## Summary
10+
11+
Balancing stable backward compatibility with the rapid pace of technology is a crucial consideration for Qiskit. This RFC is a public discussion that aims to find a harmonious solution that offers users a clear and transparent support contract while minimizing the burden on developers and users. Ideally, we are in the search for an approach that also maximizes flexibility to accommodate new hardware and services, which often necessitate the development of new features.
12+
13+
14+
## Motivation
15+
16+
Qiskit is known for its dynamic nature and frequent deprecation of features. However, the [deprecation policy](https://qiskit.org/documentation/deprecation_policy.html) places a strong emphasis on stability and guarantees a relatively lengthy transition period (usually longer than six months from the first notification point on) when removing a feature. For the past several years Qiskit has also had planned releases on a regular schedule for mitigating the impact of coming changes, as well as pre-releases to enable testing prior to a final release.
17+
18+
However, there is a demand for a more transparent release cycle with longer periods of backwards compatibility support. In order to get ready for a "beyond Qiskit 0.x", a discussion on how that cycle would like is key to understand the trade-offs among:
19+
20+
* developer effort: Supporting several stable versions requires significant development resources. At the same time, rolling releases tend to create technical debt and fewer chances to enable re-architecting features or interfaces for better maintainability or changing needs.
21+
* user support: users tend to demand longer support periods to avoid regular updates in their code and software.
22+
* new feature support for coming technology: the quantum computing field and hardware is constantly changing and scaling up. This can require changes in Qiskit, which are not always compatible with previous approaches.
23+
24+
The outcome of the RFC is an agreement for release cycle and a versioning schema that would provide users with the tools for planning and stability while reduce the impact in the development workflow.
25+
26+
## User Benefit
27+
28+
The RFC aims to benefit users and Qiskit ecosystem developers, because they will have guaranties that their software will run for a defined period of time and they could plan the transition period.
29+
30+
## Design Proposal
31+
<!--
32+
> This is the focus of the document. Explain the proposal from the perspective of
33+
> educating another user on the proposed features.
34+
>
35+
> This generally means:
36+
>
37+
> - Introducing new concepts and nomenclature
38+
> - Using examples to introduce new features
39+
> - Implementation and Migration path with associated concerns
40+
> - Communication of features and changes to users
41+
>
42+
> Focus on giving an overview of impact of the proposed changes to the target
43+
> audience.
44+
>
45+
> Factors to consider:
46+
>
47+
> - Performance
48+
> - Dependencies
49+
> - Maintenance
50+
> - Compatibility
51+
-->
52+
53+
The current `0.*`-release cycle increases the minor version in approximate periods of 3 months on a scheduled basis and, with the exception of the pre-release period (from one to two weeks) does not support more than one stable version at the time, i.e. the support of `0.X` finishes with the release of `0.X+1`.
54+
55+
```mermaid
56+
gantt
57+
dateFormat YYYY-MM-DD
58+
tickInterval 3month
59+
todayMarker off
60+
axisFormat %b-%Y
61+
0.17 :r017, 2021-04-01, 2021-07-12
62+
0.18 :r018, after r017, 2021-12-06
63+
0.19 :r019, after r018, 2022-03-31
64+
0.20 :r020, after r019, 2022-06-30
65+
0.21rc :r021rc, 2022-06-23, 2022-06-30
66+
0.21 :r021, after r020, 2022-10-13
67+
0.22rc :r022rc, 2022-10-07, 2022-10-13
68+
0.22 :r022, after r021, 2023-01-26
69+
0.23rc :r023rc, 2023-01-16, 2023-01-26
70+
0.23 :r024, after r022, 2023-05-04
71+
0.24rc :r024rc, 2023-04-20, 2023-05-04
72+
0.24 :milestone, 2023-05-04
73+
```
74+
75+
The `0.*`-release branch scheme is like this:
76+
77+
```mermaid
78+
gitGraph
79+
commit id:"feature/0"
80+
commit id: "ready_for_release" type:HIGHLIGHT
81+
branch stable/0.X
82+
commit id: "tag_0.X.0rc1" tag: "v0.X.0rc1"
83+
checkout main
84+
commit id:"bugfix/1"
85+
checkout stable/0.X
86+
cherry-pick id:"bugfix/1"
87+
commit id: "tag_0.X.0" tag: "v0.X.0"
88+
checkout main
89+
commit id:"feature/1"
90+
commit id:"feature/2"
91+
commit id:"bugfix/2"
92+
checkout stable/0.X
93+
cherry-pick id:"bugfix/2"
94+
checkout main
95+
commit id:"feature/3"
96+
commit id:"bugfix/3"
97+
checkout stable/0.X
98+
cherry-pick id:"bugfix/3"
99+
checkout main
100+
commit id:"feature/4"
101+
checkout stable/0.X
102+
commit id: "tag_0.X.1" tag: "v0.X.1"
103+
```
104+
105+
The main branch is a single development branch from which some bugfixes are backported to the stable branch, from which releases are done.
106+
107+
108+
The new release cycle will include:
109+
110+
* [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html)
111+
* Critical bugfix support for at least one year
112+
* 6-month transition period for updating to a new major while having support.
113+
* Non-breaking new features releases in a 3-month cycle (as currently)
114+
115+
116+
```mermaid
117+
gantt
118+
dateFormat YYYY-MM-DD
119+
tickInterval 3month
120+
todayMarker off
121+
axisFormat %b
122+
section X.*
123+
X.0 :rX0Y0, 2024-01-31, 91d
124+
X.1 :rX0Y1, after rX0Y0, 91d
125+
X.2 :rX0Y2, after rX0Y1, 91d
126+
X.3 :rX0Y3, after rX0Y2, 91d
127+
X.4, :done, rX0Y4, after rX0Y3, 183d
128+
section X+1.*
129+
X+1.0 :rX1Y0, 2025-01-31, 91d
130+
X+1.1 :rX1Y1, after rX1Y0, 91d
131+
X+1.2 :rX1Y2, after rX1Y1, 91d
132+
X+1.3 :rX1Y3, after rX1Y2, 91d
133+
X+1.4, :done, rX1Y4, after rX1Y3, 183d
134+
section X+2.*
135+
X+2.0 :rX2Y0, 2026-01-31, 91d
136+
X+2.1 :rX2Y1, after rX2Y0, 91d
137+
X+2.2 :rX2Y2, after rX2Y1, 91d
138+
X+2.3 :rX2Y3s, after rX2Y2, 91d
139+
X+2.4, :done, rX2Y4, after rX2Y3s, 183d
140+
```
141+
142+
```mermaid
143+
%%{init: {'theme': 'default', 'gitGraph': {'mainBranchOrder': 1}} }%%
144+
gitGraph
145+
commit id:"feature/0"
146+
commit id: "ready_for_X" type:HIGHLIGHT
147+
branch "next/X+1" order: 0
148+
149+
commit id:"breaking/0"
150+
checkout main
151+
152+
branch stable/X.0 order: 2
153+
commit id: "tag_X.0.0" tag: "vX.0.0"
154+
checkout main
155+
commit id:"bugfix/1"
156+
checkout stable/X.0
157+
cherry-pick id:"bugfix/1"
158+
159+
checkout "next/X+1"
160+
commit id:"breaking/2"
161+
commit id:"breaking/3"
162+
163+
checkout main
164+
commit id:"feature/1"
165+
checkout stable/X.0
166+
commit id: "tag_X.0.1" tag: "vX.0.1"
167+
168+
checkout main
169+
commit id: "ready_for_1" type:HIGHLIGHT
170+
171+
checkout "next/X+1"
172+
merge "main"
173+
checkout main
174+
175+
branch "stable/X.1" order: 2
176+
commit id: "tag_X.1" tag: "vX.1"
177+
checkout main
178+
commit id: "ready_for_2" type:HIGHLIGHT
179+
180+
checkout "next/X+1"
181+
merge "main"
182+
checkout main
183+
184+
branch "stable/X.2" order: 2
185+
commit id: "tag_X.2" tag: "vX.2"
186+
checkout main
187+
commit id: "ready_for_3" type:HIGHLIGHT
188+
189+
checkout "next/X+1"
190+
merge "main"
191+
checkout main
192+
193+
branch "stable/X.3" order: 2
194+
commit id: "tag_X.3.0" tag: "vX.3.0"
195+
checkout main
196+
commit id:"feature/2"
197+
commit id:"bugfix/2"
198+
checkout "stable/X.3"
199+
cherry-pick id:"bugfix/2"
200+
checkout main
201+
commit id:"breaking/1"
202+
203+
checkout stable/X.3
204+
commit id: "tag_X.3.1" tag: "vX.3.1"
205+
206+
checkout "next/X+1"
207+
commit id:"breaking/4"
208+
commit id:"breaking/5"
209+
210+
checkout main
211+
merge "next/X+1"
212+
213+
commit id: "ready_for_X+1" type:HIGHLIGHT
214+
branch "stable/X+1.0" order: 2
215+
commit id: "tag_X+1.0.0" tag: "vX+1.0.0"
216+
217+
checkout main
218+
commit id:"bugfix/3"
219+
checkout "stable/X.3"
220+
cherry-pick id:"bugfix/3"
221+
checkout "stable/X+1.0"
222+
cherry-pick id:"bugfix/3"
223+
checkout "stable/X.3"
224+
commit id: "tag_X.3.2" tag: "vX.3.2"
225+
checkout "stable/X+1.0"
226+
commit id: "tag_X+1.0.1" tag: "vX+1.0.1"
227+
```
228+
229+
Similarly to the current branching model, non-breaking features (`feature/*`) and bug fixes (`bugfix/*`) can be merged into `main` at any point. Non-breaking features (`feature/*`) are released in minor releases, when branched out of `main` for `tag_X.*`. Bug fixes are cherry-picked from main into the respective `stable/X.*` branch.
230+
231+
The main difference with the `0.*`-release schema is that breaking changes cannot be introduced at any point, but only between major releases (for example, from `X.Y.Z` to `X+1.0.0`.
232+
233+
## Detailed Design
234+
235+
All the stability guarantees on this RFC are on *public APIs*. Users and developers are encourage to only use public API and do not hook on internal interfaces.
236+
237+
### Definition of *public API*
238+
239+
The Qiskit public API is considered any documented module, class, function, or method that is not marked as private (with a `_` prefix).
240+
241+
**Exceptions**:
242+
243+
- Experimental interfaces: If module, class, function, or method is documented as experimental that is not marked as private (with a `_` prefix). Experimental interfaces have to raise a user visible [Warning](https://docs.python.org/3/library/warnings.html) (exact Warning type to be define).
244+
- Abstract interface definitions: These APIs are created to define an interface to be implemented by a subclass. Methods and properties defined as private in these Abstract classes are part of the public API.
245+
- Low-level methods for advanced usage: There are private methods that have stable interfaces but are not considered safe to use
246+
as the burden is on the user to uphold the class/safety invariants themselves
247+
(the canonical example of this is the `QuantumCircuit._append` method).
248+
249+
250+
### Versioning Model
251+
252+
The proposed versioning model for Qiskit aligns with [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html), providing a clear and standardized approach to version numbering. This model aims to communicate the nature of changes on the public API in each release, helping users and developers understand the impact of an update at a glance.
253+
254+
Semantic Versioning consists of three version components: *Major*, *Minor*, and *Patch* versions, represented as `X.Y.Z`. Each component has a specific meaning in the context of Qiskit:
255+
256+
**Major Version (X):** Increments for backward-incompatible changes, indicating potential breaking changes that may require modifications in user code using the public API.
257+
258+
- A major version `X` release has a minimum of 18 month period for support with critical bug fixes.
259+
- New major release `X` can introduce breaking changes with respect to previous major release `X-1`.
260+
- During the `X` release series, there might include non-breaking new features during that period.
261+
- After the release of a major release `X`, `X+1` can be released after, at least, 12 months.
262+
- After the release of `X+1`, `X` wont have new features and only critical bugfixes are provided for, at least, 6 months.
263+
- The features deprecated during the period of support with `X` will be removed in `X+1`
264+
265+
**Minor Version (Y):** Increases for backward-compatible features or enhancements a new `X.Y` release:
266+
267+
- Minor releases are planned for every 3 months, on a best effort basis.
268+
- Users can expect new functionalities without breaking existing code (with the exception of Experimental APIs.
269+
- Significant refactorings of internals without changes in the public API are possible in minor releases.
270+
- Bugfixing without changes in the public API are possible in minor releases.
271+
- Deprecation of previous functionality might be introduced (with a `DeprecationWarning` and documentation), pointing to the new prefer way or alternative, if there is one.
272+
- The support of `X.Y` finishes with the release of `X.Y+1` in most of the cases (exception might apply)
273+
- The minor release before the next major (aka, *final minor release*) has support for 6 months after the next major. That is, if `X.Y` is the last feature release before `X+1.0`, then `X.Y+1` is the final minor release.
274+
- The final minor release `X.Y+1` should not have new features but might include `DeprecationWarning`s that will be removed in the next major, `X+1.0`.
275+
276+
**Patch Version (Z):** Bumps for backward-compatible bug fixes.
277+
278+
- New `Z` releases have no scheduled and they are done on a *need-base* considering:
279+
- The *backportability* of the patch
280+
- The severity of the bug to fix
281+
- The criticality of the affected use-case
282+
- Cannot be introduced in patch releases:
283+
- new deprecation warnings
284+
- new features of any kind
285+
- raise minimum requirements for using or building Qiskit (including adding new dependencies)
286+
- any kind of changes in any kind of public API (including Experimental APIs), including its removal or expansion.
287+
- It may include:
288+
- expansive support for new versions of Python, Rust, or run/build environment
289+
- support for new versions of other existing dependencies
290+
- The support of `X.Y.Z` finishes with the release of `X.Y.Z+1` (or `X.Y+1.0`) in most of the cases (exception might apply)
291+
- After the release of `X+1`, bugfixing is provided via `X.Y.Z+N` in undetermined regularity for 6 months.
292+
293+
### Git branching model
294+
295+
Before the release of a major `X.0`, the last minor `X-1.Y` should be tagged in the `stable/X-1.Y`. Two weeks before the release `X.0` the branch `next/X` should be merged into `main` (probably not necessary the first time). Then `stable/X.0` is branched from `main`, as well as `next/X+1`. In `stable/X.0`, `X.0.0rc1` is tagged and release. Two week later, at stable release time, `X.0.0` is tagged on `stable/X.0` and released.
296+
297+
Similarly, two week before the release of `Y` minor, a `stable/X.Y` branch from `main` is created, from where `X.Y.0rc1` is tagged. When stable `X.Y.0` will be released (two weeks later), the label is on `stable/X.Y`.
298+
299+
All changes, including bug fixes, with backward compatibility are PRed with `main` as base. Bugfix PRs that are possible to port to stable should be tagged as `stable-backport-potential` and a bot ports them to `stable/X.Y` (where `Y` is the last minor).
300+
At undefined time, a new patch release `X.Y.Z` is tagged on `stable/X.Y` and released.
301+
302+
Non-backward compatible changes, including removal of deprecated code, can be PRed at any point against `next/X+1` branch.
303+
304+
Regularly, `main` should be merge into `next/X+1` to keep it up-to-date. The suggestion is for every minor release, at least.
305+
306+
### QPY support
307+
308+
The QPY serialization format is backwards compatible so that a new Qiskit can release can always load a QPY
309+
file generated with an earlier release of Qiskit. However, the format isn't forward compatible, so it's not possible
310+
to load QPY files generated with newer version of Qiskit using an older release. To support compatibility across major version releases, the `qiskit.qpy.dump()` function has an optional argument `version` that lets a user specify a back version of the QPY format emitted by the `dump()` function. There are two constants exposed by
311+
the `qpy` module, `qiskit.qpy.QPY_VERSION` which documents the default format version emitted by `dump()` and
312+
also the maximum version that `load()` supports, and `qiskit.qpy.QPY_COMPATIBILITY_VERSION` which documents the minimum version that `dump()` can emit (while `load()` can load any version <= `QPY_VERSION`).
313+
314+
To facilitate user migration across major version releases the `qiskit.qpy.dump()` function will always support at least one overlapping version between the `X.0.0` and the `X-1.Y.0` release (where Y is the last minor version of
315+
that series). This will enable saving QPY format files that can be loaded by both major versions from the newer
316+
release. For example, in Qiskit 1.0.0 the `QPY_VERSION` was `11`, and in Qiskit 0.46.0 the `QPY_VERSION` constant was `10`. For qiskit 1.0.0 the minimum version supported by `dump()`'s `version` argument, and exposed by
317+
`qiskit.qpy.QPY_COMPATIBILITY_VERSION` was 10. This enabled Qiskit 1.0.0 to generate qpy payloads that could
318+
be loaded by Qiskit 0.46.0.
319+
320+
### Pre-releases
321+
322+
The pre-release model from the `0.*`-release cycle will continue in the same way. Two weeks before the release of a minor `X.Y`, a release candidate `X.Yrc0` will be released as a pre-release. The final minor release might be except for that release candidate release, as it does not include new features.
323+
324+
### Feature, deprecation, and removal proposal deadline
325+
326+
Two weeks before the pre-release or a minor release, what ever is before, there will be a feature, deprecation, and removal proposal deadline. That means that any PR with addition, removal, or modification on the public API needs to be ready for review in the Qiskit repository before that date. Exceptions might apply at consideration of the Qiskit core team.
327+
328+
329+
### Suggested upgrade path
330+
331+
Users should upgrade minors and patch versions as soon as the next stable release happens in every case, except when there is a new major release.
332+
Major releases allow for 6 months to transition from `X` to `X+1`.
333+
Users and downstreamers should depend on `<X+1` until the end of the transition time.
334+
The last minor on `X` is will contain all the `DeprecationWarning`s users should solve before moving on `X+1`.
335+
336+
If there is a dependency on a feature introduced in `Y`, users should depend on `>=X.Y,<X+1` (or `~=X.Y`). `DeprecationWarning`s introduced on `X.Y` will have an alternative path in `X.Y` and can be migrated then, when possible.
337+
338+
<!--
339+
## Alternative Approaches
340+
> Discuss other approaches to solving this problem and why these were not
341+
> selected.
342+
343+
## Questions
344+
> Open questions for discussion and an opening for feedback.
345+
346+
## Future Extensions
347+
> Consider what extensions might spawn from this RFC. Discuss the roadmap of
348+
> related projects and how these might interact. This section is also an opening
349+
> for discussions and a great place to dump ideas.
350+
>
351+
> If you do not have any future extensions in mind, state that you cannot think
352+
> of anything. This section should not be left blank.
353+
-->

0 commit comments

Comments
 (0)