tools/RELEASE.md
The release process starts with one or more tagged release candidates, when no more blocking issues needs to be fixed a final tag is created and the final release is rolled.
confluent-kafka-python uses semver versioning and loosely follows librdkafka's version, e.g. v0.11.4 for the final release and v0.11.4rc3 for the 3rd v0.11.4 release candidate.
With the addition of prebuilt binary wheels we make use of Semaphore CI to build OSX, Linux and Windows binaries which are uploaded to build's artifact directory. These artifacts are downloaded and then uploaded manually to PyPi.
Note: Python package versions use a lowercase rcN suffix to indicate
release candidates while librdkafka uses -RCN. The Python format
must be used for confluent-kafka-python releases.
That is to say that while the librdkafka RC is named v0.11.4-RC3
a Python client RC with the same version is named v0.11.4rc3.
The following guide uses v0.11.4rc1 as version for a release candidate,
replace as necessary with your version or remove rc.. suffix for the
final release.
To give you an idea what this process looks like we have this fabricated time line:
During the release process no PRs must be merged, unless they're fixing something that needs to go into the release. If that's the case the rc branch needs to be rebased on latest master, or master merged into it, to pick up the new changes.
Make sure your local git clone is up to date and clean:
$ git checkout master
$ git pull --rebase --tags origin master
Create an RC branch
$ git checkout -b v0.11.4rc
Make sure the top of CHANGELOG.md has a section for the upcoming release. See previous releases in CHANGELOG.md for how to structure and format the release notes.
For our fix and enhancement PRs we typically write the corresponding changelog entry as part of that PR, but for PRs that have been submitted from the community we typically need to add changelog entries afterwards.
To find all changes since the last release, do:
$ git log v0.11.3.. # the last release
Go through the printed git history and identify and changes that are not already in the changelog and that are relevant to the end-users of the client. For example, a bug fix for a bug that users would be seeing should have a corresponding changelog entry, but a fix to the build system is typically not interesting and can be skipped.
For commits provided by the community we need to provide proper attribution
by looking up the GitHub username for each such change and then @-mention
the user from the changelog entry, e.g.:
* Producer flush() now raises Authenticator errors (@someghuser, #pr-or-issue-number)
The changelog must also say which librdkafka version is bundled, a link to the librdkafka release notes, and should also mention some of the most important changes to librdkafka in that release.
Note: CHANGELOG.md is in MarkDown format.
Prebuilt librdkafka library (with all its dependencies included) is bundled with the Python client in the Python wheels, one wheel for each arch and platform we support.
The Python release process is usually coupled with the librdkafka release process, so while building and trying out the Python release candidates it is likely that a release candidate version of librdkafka will be used. When all release testing has been done librdkafka will be released first, and then the Python release branch will be updated to use the final librdkafka release tag (e.g., v0.11.4) rather than the release candidate tag (e.g., v0.11.4-RC5).
Change to the latest librdkafka version in the following files:
.semaphore/semaphore.ymlexamples/docker/Dockerfile.alpineChange to the latest version of the confluent-librdkafka-plugins in (this step is usually not necessary):
tools/install-interceptors.shCommit these changes as necessary:
$ git commit -m "librdkafka version v0.11.4-RC5" .semaphore/semaphore.yml examples/docker/Dockerfile.alpine
$ git commit -m "confluent-librdkafka-plugins version v0.11.0" tools/install-interceptors.sh
There are a couple of source files that needs to be updated with the new version number. The version should be set to the final release version, even when doing RCs, so it only needs to be set once for each release.
src/confluent_kafka/src/confluent_kafka.h
update both CFL_VERSION. (TODO make this read from toml file)pyproject.toml - change version field to match.tests/soak/setup_all_versions.py - add the new version to both
LIBRDKAFKA_VERSIONS and PYTHON_VERSIONS lists.Commit these changes with a commit-message containing the version:
$ git commit -m "Version v0.11.4rc1" src/confluent_kafka/src/confluent_kafka.h pyproject.toml tests/soak/setup_all_versions.py
The following sections are performed in multiple iterations:
Repeat the following chapters' TEST ITERATIONs, then submit a PR, get it reviewed by team mates, perform one or more CANDIDATE ITERATION, and then do a final RELEASE ITERATION.
Push your branch: $ git push origin v0.11.4rc
Packaging is fragile and is only triggered when a tag is pushed. To avoid finding out about packaging problems on the RC tag, it is strongly recommended to first push a test tag to trigger the packaging builds. This tag should be removed after the build passes.
Note: Python package versions use a lowercase rcN suffix to indicate
release candidates while librdkafka uses -RCN. The Python format
must be used for confluent-kafka-python releases.
That is to say that while the librdkafka RC is named v0.11.4-RC3
a Python client RC with the same version is named v0.11.4rc3.
Use the Semaphore CI tag-release task to create tags. Set the parameter accordingly:
v0.11.4rc in this tutorial)v0.11.4rc1-dev1, for example)Monitor Semaphore CI builds by looking at the tag build at Semaphore CI
CI jobs are flaky and may fail temporarily. If you see a temporary build error, e.g., a timeout, restart the specific job.
If there are permanent errors, fix them and then go back to 5.1. to create and push a new test tag. Don't forget to delete your previous test tag.
When all CI builds are successful it is time to download all the resulting
artifacts (wheels) from build's artifacts directory (located in the Artifacts tab in the build).
Create a new folder tools\dl-<tag> under the repository root, and unzip all artifacts from the downloaded .tgz files there. You should have many artifacts (with .whl suffix) under tools\dl-<tag> as we support different operating systems and Python versions.
The wheels will have been verified on CI, but it doesn't hurt to verify them locally (this should be run on OSX with Docker installed):
$ tools/test-wheels.sh tools/dl-v0.11.4rc1
When all things are looking good it is time to clean up the git history to look tidy, remove any test tags, and then go back to 5.1 and perform the CANDIDATE ITERATION.
CANDIDATE ITERATION:
Once all test and RC builds are successful and have been verified and you're ready to go ahead with the release, it is time create a PR to have the release changes reviewed.
If librdkafka has had a new RC or the final release it is time to update the librdkafka versions now. Follow the steps in chapter 3.
Do not squash/rebase the RC branch since that would invalidate the RC tags, so try to keep the commit history tidy from the start in the RC branch.
Create a PR for the RC branch and add team mates as reviewers and wait for review approval.
RELEASE ITERATION:
Same as the CANDIDATE ITERATION.
Once the PR has been approved and there are no further changes for the release, merge the PR to master.
Make sure to Merge the PR - don't squash, don't rebase - we need the commit history to stay intact for the RC tags to stay relevant.
With the PR merged to master, check out and update master:
$ git checkout master
$ git pull --rebase --tags origin master
# Make sure your master is clean and identical to origin/master
$ git status
Now go back to 5.1 and start the final RELEASE ITERATION.
When creating the source packages make sure to have checked out the correct tag
and that you do not have any uncommited modifications and that the dist/
directory is empty.
$ python -m build -s
The above command will create the necessary source distribution. Move this
generated sdist file to correct tools\dl-<tag> folder
$ mv dist/confluent-kafka-0.11.4rc1.tar.gz tools/dl-v0.11.4rc1/
CANDIDATE ITERATION: To upload binary packages to test.pypi.org, use:
$ twine upload -r test tools/dl-v0.11.4rc1/*
RELEASE ITERATION: To upload binary packages to the proper pypi.org (WARNING!), use:
$ twine upload tools/dl-v0.11.4rc1/*
In the same virtualenv as created above:
# Repeat until all versions are uninstalled
$ pip uninstall confluent_kafka # repeat until all are removed
CANDIDATE ITERATION:
# For release-candidates specify --pre argument and version-pinning.
# Ensure you veriy installation of both pre-built wheel and building from source:
$ pip install --pre -i https://test.pypi.org/simple/ "confluent-kafka==0.11.4rc1"
$ C_INCLUDE_PATH=/opt/homebrew/Cellar/librdkafka/0.11.4/include LIBRARY_PATH=/opt/homebrew/Cellar/librdkafka/0.11.4/lib pip install --pre --no-binary "confluent-kafka" -i https://test.pypi.org/simple/ "confluent-kafka==0.11.4rc1" # On OSX, need to provide paths for librdkafka
RELEASE ITERATION:
# For final releases no --pre or version-pinning, pay
# attention to the version being picked up, should be the
# final v0.11.4 release.
# Ensure you veriy installation of both pre-built wheel and building from source:
$ pip install -i https://test.pypi.org/simple/ "confluent-kafka==0.11.4"
$ C_INCLUDE_PATH=/opt/homebrew/Cellar/librdkafka/0.11.4/include LIBRARY_PATH=/opt/homebrew/Cellar/librdkafka/0.11.4/lib pip install --no-binary "confluent-kafka" -i https://test.pypi.org/simple/ "confluent-kafka==0.11.4" # On OSX, need to provide paths for librdkafka
Verify that the package works and prints the expected version:
$ python -c 'import confluent_kafka as ck ; print("py:", ck.version(), "c:", ck.libversion())'
py: ('0.11.4', 721920) c: ('0.11.4-RC1', 722121)
When the final release is tagged, built and uploaded, go to
github releases
and create a new release with the same name as the final release tag (v0.11.4).
Copy the section for this release from CHANGELOG.md to the GitHub release.
Use Preview to check that links work as expected.
Create the release.
Create a PR to update the confluent-kafka-python version tag for the Python API docs on docs.confluent.io.
# Update the Python API docs to the latest version: https://github.com/confluentinc/docs-platform.
That's it, back to the coal mine.