blob: 8c2bd54fc753b2bb55f063a46d16f0e216a40195 [file] [log] [blame] [view]
# Versioning
[TOC]
This page covers Jetpack's usage of Semantic Versioning and pre-release cycles,
including the expectations at each cycle and criteria for moving to the next
cycle or SemVer revision.
## Semantic versioning and binary compatibility {#semver}
Artifacts follow strict [semantic versioning](http://semver.org) for binary
compatibility with an added inter-version sequence of pre-release revisions.
Versions for finalized release artifacts, which are available on
[Google Maven](https://maven.google.com) will follow the format
`<major>.<minor>.<bugfix>` with an optional `-<alpha|beta|rc><nn>` suffix.
Internal or nightly releases, which are available on
[androidx.dev](http://androidx.dev), use the `-SNAPSHOT` suffix.
### Behavioral and source compatibility {#compat}
Libraries are required to preserve *behavioral compatibility* -- APIs must
behave as described in their documentation -- across minor versions. Special
consideration must also be made for changes to undocumented behavior, as
developers may have made their own assumptions about API contracts based on
observed behavior.
Libraries are strongly encouraged to preserve *source compatibility* across
minor versions. Strictly requiring source compatibility would require major
version bumps when implementing quality-of-life improvements such as nullability
annotations or generics, which would be [disruptive](#major-implications) to the
library ecosystem.
### Notation {#notation}
Major (`x.0.0`)
: An artifact's major version indicates a guaranteed forward-compatibility
window. The number is incremented only when introducing breaking API or
behavioral changes.
Minor (`1.x.0`)
: Minor indicates compatible public API changes. This number is incremented
when APIs are added, including the addition of
[`@Deprecated` annotations](/docs/api_guidelines/index.md#deprecation-and-removal).
Binary compatibility must be preserved between minor version changes.
Bugfix (`1.0.x`)
: Bugfix indicates internal changes to address broken behavior. Care should be
taken to ensure that existing clients are not broken, including clients that
may have been working around long-standing broken behavior.
#### Pre-release cycles {#prerelease}
Alpha (`1.0.0-alphaXX`)
: Feature development and API stabilization phase.
Beta (`1.0.0-betaXX`)
: Functional stabilization phase. Suitable for production use.
RC (`1.0.0-rcXX`)
: Verification phase.
Stable (no-suffix)
: Recommended for production use.
In the past -- and only in rare cases -- libraries have used a `-devXX` suffix
to indicate that a public release does not yet meet the requirements for Alpha.
We **strongly discourage** libraries from using `-devXX`, as failing to meet the
requirements for Alpha indicates that a library should not be publicly released.
### Major (`x.0.0`) {#major}
An artifact's major version indicates a guaranteed forward-compatibility window.
For example, a developer could update an artifact versioned `2.0.0` to `2.7.3`
without taking any additional action; however, updating from `2.7.3` to `3.0.0`
may require a complete rewrite of their application or cause conflicts with
their dependencies. Major version bumps are
[strongly discouraged](#major-implications).
#### When to increment {#major-when}
An artifact *must* increment its major version number in response to breaking
changes in binary or behavioral compatibility within the library itself *or* in
response to breaking changes within a dependency.
For example, if an artifact updates a SemVer-type dependency from `1.0.0` to
`2.0.0` then the artifact must also bump its own major version number.
An artifact *may in rare cases* increment its major version number to indicate
an important but non-breaking change in the library. Note, however, that the
SemVer implications of incrementing the major version are the same as a breaking
change -- dependent projects *must* assume the major version change is breaking
and update their dependency specifications.
#### Ecosystem implications {#major-implications}
When an artifact increases its major version, *all* artifacts that depended on
the previous major version are no longer considered compatible and must
explicitly migrate to depend on the new major version.
As a result, if the library ecosystem is slow to adopt a new major version of an
artifact then developers may end up in a situation where they cannot update an
artifact because they depend on a library that has not yet adopted the new major
version.
For this reason, we *strongly* recommend against increasing the major version of
a “core” artifact that is depended upon by other libraries. “Leaf” artifacts --
those that apps depend upon directly and are not used by other libraries -- have
a much easier time increasing their major version.
#### Process requirements {#major-process}
If the artifact has dependencies within Jetpack, owners *must* complete an
assessment before implementing any breaking changes to binary or behavioral
compatibility.
Otherwise, owners are *strongly recommended* to complete the assessment before
implementing any breaking changes to binary or behavioral compatibility, as such
changes may negatively impact downstream clients in Android git or Google's
repository. These clients are not part of our pre-submit workflow, but filling
out the assessment will provide insight into how they will be affected by a
major version change.
### Minor (`1.x.0`) {#minor}
Minor indicates compatible public API changes. This number is incremented when
APIs are added -- including the addition of `@Deprecated` annotations -- and
libraries must go through a full [pre-release](#pre-release-suffix) cycle before
reaching stable. Binary compatibility must be preserved between minor version
changes.
#### Moving between minor versions:
* A change in the minor revision indicates the addition of binary-compatible
APIs. Libraries **must** increment their minor revision when adding APIs.
Dependent libraries are not required to update their minimum required
version unless they depend on newly-added APIs.
### Bugfix (`1.0.x`) {#bugfix}
Bugfix indicates internal changes to address broken behavior. Care should be
taken to ensure that existing clients are not broken, including clients that may
have been working around long-standing broken behavior. Bugfix releases *do not*
go through a pre-release cycle and are considered stable.
#### Moving between bugfix versions:
* A change in the bugfix revision indicates changes in behavior to fix bugs.
The API surface does not change. Changes to the bugfix version may *only*
occur in a release branch. The bugfix revision must always be `.0` in a
development branch.
### Pre-release suffixes {#pre-release-suffix}
The pre-release suffix indicates stability and feature completeness of a
release. A typical release will begin as alpha, move to beta after acting on
feedback from internal and external clients, move to release candidate for final
verification, and ultimately move to a finalized build.
Alpha, beta, and release candidate releases are versioned sequentially using a
leading zero (ex. alpha01, beta11, rc01) for compatibility with the
lexicographic ordering of versions used by SemVer.
### Snapshot {#snapshot}
Snapshot releases are whatever exists at tip-of-tree. They are only subject to
the constraints placed on the average commit. Depending on when it's cut, a
snapshot may even be binary-identical to an `alpha`, `beta`, or `RC` release.
### Tooling guarantees
Versioning policies are enforced by the following Gradle tasks:
- `checkApi`: ensures that changes to public API are intentional and tracked,
asking the developer to explicitly run `updateApi` (see below) if any
changes are detected
- `checkApiRelease`: verifies that API changes between previously released and
currently under-development versions conform to semantic versioning
guarantees
- `updateApi`: commits API changes to source control in such a way that they
can be reviewed in pre-submit via Gerrit `API+2` and reviewed in post-submit
by API Council
`SNAPSHOT` is automatically added to the version string for all builds that
occur outside the build server for release branches. Local release builds may be
forced by passing `-Prelease` to the Gradle command line.
## Picking the right version {#picking-the-right-version}
Libraries follow [semantic versioning](#semver), which means that the version
code is strongly tied to the API surface. A full version consists of revision
numbers for major, minor, and bugfix as well as a pre-release stage and
revision. Correct versioning is, for the most part, automatically enforced;
however, please check for the following:
### Initial version {#initial-version}
If your library is brand new, your version should start at 1.0.0, e.g.
`1.0.0-alpha01`.
The initial release within a new version always starts at `alpha01`. Note the
two-digit revision code, which allows us to do up to 99 revisions within a
pre-release stage.
### Pre-release stages
A single version will typically move through several revisions within each of
the pre-release stages: alpha, beta, rc, and stable. Subsequent revisions within
a stage (ex. alpha, beta) are incremented by 1, ex. `alpha01` is followed by
`alpha02` with no gaps.
### Moving between pre-release stages and revisions
Libraries are expected to go through a number of pre-release stages within a
version prior to release, with stricter requirements at each stage to ensure a
high-quality stable release. The owner for a library should typically submit a
CL to update the stage or revision when they are ready to perform a public
release.
Libraries are expected to allow >= 2 weeks per pre-release stage. This "soaking
period" gives developers time to try each version, find bugs, and ensure a
quality stable release. Therefore, at minimum:
- An `alpha` version must be publicly available for 2 weeks before releasing a
public `beta`
- A `beta` version must be publicly available for 2 weeks before releasing a
public `rc`
- A `rc` version must be publicly available for 2 weeks before releasing a
public stable version
Your library must meet the following criteria to move your public release to
each stage:
### Alpha {#alpha}
Alpha releases are expected to be functionally stable, but may have unstable API
surface or incomplete features. Changes in alpha do trigger API Council review,
but the feedback does not block an alpha release. Library owners are expected to
have performed a minimum level of validation.
#### Within the `alphaXX` cycle
* Workflow
* Development happens in `androidx-main` or `androidx-platform-dev`
* API surface
* Prior to `alpha01` release, API tracking **must** be enabled (either
`publish=true` or create an `api` directory) and remain enabled
* May add/remove APIs within `alpha` cycle, but deprecate/remove cycle is
strongly recommended.
* May use
[experimental APIs](/docs/api_guidelines/index.md#experimental-api)
across same-version group boundaries
* Testing
* Ensure the library is testable. Follow the guideline on
[go/androidx/testability](/docs/testability.md)
* All changes **should** be accompanied by a `Test:` stanza
* All pre-submit and post-submit tests are passing
* Flaky or failing tests **must** be suppressed or fixed within one day
(if affecting pre-submit) or three days (if affecting post-submit)
### Beta {#beta}
Beta releases are ready for production use but may contain bugs. They are
expected to be functionally stable and have highly-stable, feature-complete API
surface. All APIs should have been reviewed by API Council at this stage. Tests
should have 100% coverage of public API surface and translations must be 100%
complete.
While beta represents API Freeze, it does not necessarily mean APIs are locked
down permanently. A limited number of exceptions may be granted by API Council
in cases where ship-blocking mistakes or significant user experience issues can
be addressed with minimal changes to the API surface. Exceptions **will not** be
granted for new features, non-trivial API changes, significant refactorings, or
any changes likely to introduce additional functional instability. Requests for
exceptions **must** be accompanied by a justification explaining why the change
cannot be made in a future minor version. This policy does not apply to
additions of experimental `@RequiresOptIn` APIs or changes to `@RequiresOptIn`
APIs.
#### Checklist for moving to `beta01` {#beta-checklist}
* API surface
* Entire API surface has been reviewed by API Council
* All APIs from alpha undergoing deprecate/remove cycle must be removed
* The final removal of a `@Deprecated` API should occur in alpha, not
in beta
* Must not use
[experimental APIs](/docs/api_guidelines#experimental-api)
across same-version group boundaries
* Testing
* All public APIs are tested
* All pre-submit and post-submit tests are enabled (e.g. all suppressions
are removed) and passing
* Use of experimental Kotlin features (e.g. `@OptIn`) must be audited for
stability
* All dependencies are `beta`, `rc`, or stable
* Be able to answer the question "How will developers test their apps against
your library?"
* Ideally, this is an integration app with automated tests that cover the
main features of the library and/or a `-testing` artifact as seen in
other Jetpack libraries
#### Within the `betaXX` cycle
* Workflow
* Development happens in `androidx-main` or, in extremely limited cases,
changes are cherry-picked to a `-release` branch
* API surface
* May not add, remove, or change APIs unless granted an exception by API
Council following the beta API change exception request process
* Must go through the full `@Deprecate` and hard-removal cycle in
separate `beta` releases for any exception-approved API removals or
changes
* May not remove `@RequiresOptIn` annotations from experimental APIs, as
this would amount to an API addition
* **May** add new `@RequiresOptIn` APIs and change existing experimental
APIs
### RC {#rc}
Release candidates are expected to be nearly-identical to the final release, but
may contain critical last-minute fixes for issues found during integration
testing.
#### Checklist for moving to `rc01`
* All previous checklists still apply
* Release branch, e.g. `androidx-<group_id>-release`, is created
* API surface
* Any API changes from `beta` cycle are reviewed by API Council
* No **known** `P0` or `P1` (ship-blocking) issues
* All dependencies are `rc` or stable
#### Within the `rcXX` cycle
* Changes are cherry-picked to a `-release` branch
* Ship-blocking bug fixes only
* All changes must have corresponding tests
* No API changes allowed
### Stable {#stable}
Final releases are well-tested, both by internal tests and external clients, and
their API surface is reviewed and finalized. While APIs may be deprecated and
removed in future versions, any APIs added at this stage must remain for at
least a year.
#### Checklist for moving to stable
* Identical to a previously released `rcXX` (note that this means any bugs
that result in a new release candidate will necessarily delay your stable
release by a minimum of two weeks)
* No changes of any kind allowed
* All dependencies are stable
## Updating your version {#update}
A few notes about version updates:
- The version of your library listed in `androidx-main` should *always* be
higher than the version publicly available on Google Maven. This allows us
to do proper version tracking and API tracking.
- Version increments must be done before the CL cutoff date (aka the build cut
date).
- **Increments to the next stability suffix** (like `alpha` to `beta`) should
be handled by the library owner
- Version increments in release branches will need to follow the guide
[How to update your version on a release branch](/docs/release_branches.md#update-your-version)
- When you're ready for `rc01`, the increment to `rc01` should be done in
`androidx-main` and then your release branch should be snapped to that
build. See the guide
[Snap your release branch](/docs/release_branches.md#snap)
on how to do this. After the release branch is snapped to that build, you
will need to update your version in `androidx-main` to `alpha01` of the next
minor (or major) version.
### How to update your version
1. Update the version listed in `libraryversions.toml`
1. If your library is a `beta` or `rc01` version, run `./gradlew
<your-lib>:updateApi`. This will create an API txt file for the new version
of your library. For other versions, this step is not required
1. Verify changes with `./gradlew checkApi verifyDependencyVersions`.
1. Commit these change as one commit.
1. Upload these changes to Gerrit for review.
An example of a version bump can be found here:
[aosp/833800](https://android-review.googlesource.com/c/platform/frameworks/support/+/833800)
## `-ktx` Modules {#ktx}
[Kotlin extension libraries](/docs/api_guidelines/index.md#module-ktx)
(`-ktx`) follow the same versioning requirements as other libraries, but with
one exception: they must match the version of the Java libraries that they
extend.
For example, let's say you are developing a Java library
`androidx.foo:foo-bar:1.1.0-alpha01` and you want to add a Kotlin extension
library `androidx.foo:foo-bar-ktx`. Your new `androidx.foo:foo-bar-ktx` library
will start at version `1.1.0-alpha01` instead of `1.0.0-alpha01`.
If your `androidx.foo:foo-bar` module was in version `1.0.0-alpha06`, then the
Kotlin extension module would start in version `1.0.0-alpha06`.
## FAQ
### When does an alpha ship?
For public releases, an alpha ships when the library lead believes it is ready.
Generally, these occur during the batched bi-weekly (every 2 weeks) release
because all tip-of-tree dependencies will need to be released too.
### Can alpha work (ex. for the next Minor release) occur in the primary development branch during beta API lockdown?
Generally, no. This is by design. Focus should be spent on improving the Beta
version and adding documentation/samples/blog posts for usage!
In limited cases, the
[`@RequiresOptIn`](/docs/api_guidelines/index.md#experimental-api)
meta-annotation may be used to extend development of a feature beyond the alpha
cycle. When doing so, extreme care must be taken to avoid destabilizing the rest
of the library.
### Is there an API freeze window between alpha and beta while API surface is reviewed and tests are added, but before the beta is released?
Yes. If any new APIs are added in this window, the beta release will be blocked
until API review is complete and addressed.
### How often can a beta release?
As often as needed; however, releases outside of the bi-weekly (every 2 weeks)
release will need to get approval from the TPM (natnaelbelay@).