This documents our versioning approach for Cirq and how we produce new Cirq releases.
Note that Cirq development takes place on the main
branch in GitHub. If you
want to use a more stable version of Cirq, you should use one of the
releases or install the package
from PyPI using pip install cirq
. The release from the latest commit to main
can be installed with pip install cirq~=1.0.dev
.
We follow the Semantic Versioning 2.0.0 approach for labeling Cirq releases. Each stable release is labeled with an identifier written in the form MAJOR.MINOR.PATCH, where MAJOR, MINOR, and PATCH are numbers. The following guarantees are provided:
-
All packages released at the same time from the Cirq repository will share the same semantic versioning version number. (If it ever becomes necessary to allow packages to have different version numbers, this policy will be updated.)
-
Libraries in the
cirq-core
directory (with the exception ofcirq-core/cirq/contrib
) adhere to the guarantees outlined in the Semantic Versioning specification. In summary:-
Bug fixes that do not affect the API will only involve incrementing the PATCH version.
-
Additions and/or changes that affect the API but do so in a backwards-compatible way will involve incrementing the MINOR version.
-
Additions and/or changes that affect the API in a backwards-incompatible way will increment the MAJOR version.
-
-
The contrib directory (at
cirq-core/cirq/contrib
) currently follows Semantic Versioning except for the MINOR version increment policy: releases with MINOR version increments may contain backward-incompatible functionality changes to its public API. (They may be changed to strictly follow Semantic Versioning in the future, at which point this policy will be updated.) -
Cirq vendor directories (
cirq-aqt
,cirq-google
,cirq-ionq
, etc.) follow Semantic Versioning except the MINOR version increment policy: each vendor directory has a separate policy on whether MINOR version increments provide backward-compatibility guarantees, as described inversion_policy.md
in the respective directory.-
If
version_policy.md
does not exist in a particular vendor directory, MINOR version increments may contain backward-incompatible functionality changes to its public API. -
For each vendor directory, version policies may be modified to strictly follow Semantic Versioning in the future.
-
-
Versions based on unreleased branches of
main
will be suffixed with.dev
.
The rules for version changes are:
-
Increment the PATCH version if all changes are bug fixes only.
-
Increment the MINOR version if changes contain functionalities which are backward-compatible, or if a vendor directory or
contrib
contains backward-incompatible changes and the policy for the directory allows backward-incompatible changes for a minor version increment.
At this time, a major version increment process has not been established. Until
then, backward-incompatible changes are not allowed for cirq-core
and vendor
directories that prohibit them for a minor version increment.
We use GitHub's release system for creating releases. Release are listed on the Cirq release page.
Our development process uses the branch named main
for development. This
branch will always use the next unreleased minor version number with the suffix
of .dev
. When a release is performed, the .dev
will be removed and tagged
in a release branch with a version tag (vX.X.X). Then, main
will be updated
to the next minor version. The version number of main
can always be found in
the version file.
Releases are made on an as-needed basis determined by Cirq maintainers. All Cirq
packages (including vendor packages such as cirq-aqt
) are released at the same
time.
Ensure that all the deprecations are removed that were meant to be deprecated
for the given release. E.g. if you want to release v0.11
, you can check with
git grep 'v0.11'
for all the lines containing this deadline. Make sure none
of those are released.
This procedure can be followed by authorized Cirq developers to perform a release.
System requirements: Linux, Python 3.10.
For MINOR/MAJOR releases: make sure you're on an up-to-date main
branch and
in Cirq's root directory.
git checkout main
git pull origin main # or upstream main
git status # should be no pending changes
For PATCH update: Make sure you checked out the version you want to patch.
Typically this will be something like ${MAJOR}.${MINOR}.${LAST_PATCH}
git fetch origin # or upstream - to fetch all tags
git checkout <desired tag to patch>
git status # should be no pending changes
Ensure you have PyPI and Test PyPI accounts with access to the Cirq distribution. This can be done by visiting https://test.pypi.org, logging in, and accessing the https://test.pypi.org/project/cirq page.
For the following script to work, you will need the following environment
variables defined: TEST_TWINE_USERNAME
, TEST_TWINE_PASSWORD
,
PROD_TWINE_USERNAME
, PROD_TWINE_PASSWORD
.
It is highly recommended to use different passwords for test and prod to avoid accidentally pushing to prod.
Also define these variables for the versions you are releasing:
VER=VERSION_YOU_WANT_TO_RELEASE # e.g. "0.7.0"
NEXT_VER=NEXT_VERSION # e.g. "0.8.0" (skip for PATCH releases)
Create a release branch called "v${VERSION}-dev":
git checkout -b "v${VER}-dev"
If you are doing a PATCH update, use git cherry-pick
to integrate the commits
for the fixes you want to include in your update, making sure to resolve all
merge conflicts carefully:
git cherry-pick <commit>
Bump the version number on the release branch:
python dev_tools/modules.py replace_version --old ${VER}.dev --new ${VER}
git add .
git commit -m "Removing ${VER}.dev -> ${VER}"
git push origin "v${VER}-dev"
WARNING: Only bump the main version for minor and major releases. For PATCH updates, leave it as it is.
git checkout main -b "version_bump_${NEXT_VER}"
python dev_tools/modules.py replace_version --old ${VER}.dev --new ${NEXT_VER}.dev
git add .
git commit -m "Bump cirq version to ${NEXT_VER}"
git push origin "version_bump_${NEXT_VER}"
The main branch should never see a non-dev version specifier.
From a release branch, create a binary distribution wheel. This is the package that will go to PyPI.
git checkout "v${VER}-dev"
./dev_tools/packaging/produce-package.sh dist
ls dist # should only contain one file, for each modules
The package server PyPI has a test server where packages can be uploaded to check that they work correctly before pushing the real version. This section illustrates how to upload the package to Test PyPI and verify that it works.
First, upload the package in the dist/
directory. (Ensure that this is the
only package in this directory, or modify the commands to upload only this
file).
twine upload --repository-url=https://test.pypi.org/legacy/ \
-u="$TEST_TWINE_USERNAME" -p="$TEST_TWINE_PASSWORD" "dist/*"
Next, run automated verification. Note: sometimes the first verification from Test PyPI will fail:
# NOTE: FIRST RUN MAY FAIL - PyPI might not have indexed the version yet
./dev_tools/packaging/verify-published-package.sh "${VER}" --test
Once this runs, you can create a virtual environment to perform manual verification as a sanity check and to check version number and any high-risk features that have changed this release.
mkvirtualenv "verify_test_${VER}" --python=/usr/bin/python3
pip install -r dev_tools/requirements/dev.env.txt
pip install --index-url=https://test.pypi.org/simple/ cirq=="${VER}"
python -c "import cirq; print(cirq.__version__)"
python # just do some stuff checking that latest features are present
Put together a release notes document that can be used as part of a release and for an announcement email.
You can model the release notes on the previous release from the Release page.
-
Fill out the new version in "Tag Version" and choose your release branch to create the tag from.
-
Attach the generated
.whl
file to the release.
Retrieve all commits since the last release with:
git log "--pretty=%h %s"
You can get the changes to the top-level objects and protocols by checking the history of the init files.
git diff <previous version>..HEAD cirq-core/cirq/__init__.py
You can get the contributing authors for the release by running:
git log <previous version>..HEAD --pretty="%an" | sort |\
uniq | sed ':a;N;$!ba;s/\n/, /g'
Add cirq-google
release notes to cirq-google/CHANGELOG.md
following the
changelog format.
Upload to prod PyPI using the following command:
twine upload --username="$PROD_TWINE_USERNAME" \
--password="$PROD_TWINE_PASSWORD" "dist/*"
Perform automated verification tests:
# NOTE: FIRST RUN WILL LIKELY FAIL - pypi might not have yet indexed the version
./dev_tools/packaging/verify-published-package.sh "${VER}" --prod
Next, create a Python virtual environment to perform manual verification of the release:
mkvirtualenv "verify_${VER}" --python=/usr/bin/python3
pip install cirq
python -c "import cirq; print(cirq.__version__)"
Using the information above, create the release on the
Release page.
Be sure to include the .whl
file as an attachment.
If there are unreleased notebooks that are under testing (meaning that
NOTEBOOKS_DEPENDING_ON_UNRELEASED_FEATURES
is not empty in the file
dev_tools/notebooks/isolated_notebook_test.py
),
then follow the steps in our notebooks guide.
Got to the Zenodo release page. Login using credentials stored in Google's internal password utility (or get someone from Google to do this). Click "New Version".
- Upload the new zip file (found in releases page under "assets").
- Remove old zip file.
- Update version.
- Double check all other fields.
- Click publish.
Lastly, email [email protected] with the release notes and an announcement of the new version.
Finally, congratulate yourself on a release well done!