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:
- Time to prepare for a release.
- A librdkafka release candidate is available.
- Check if any open PRs needs merging, do that.
- Feature freeze - don't merge any more PRs.
- Create a release candidate branch.
- Update versions, dependencies (librdkafka), etc.
- Create test tag to trigger CI builds, test.
- Work out any release build issues.
- librdkafka is released, update librdkafka version.
- Create release candidate tag, wait for CI builds, deploy to test-PyPi.
- Create PR, get it reviewed.
- When it is time for final release, merge the PR.
- On master, create release tag, wait for CI builds, deploy to PyPi.
- Update confluent.io docs.
- Announce release.
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.yml
examples/docker/Dockerfile.alpine
Change to the latest version of the confluent-librdkafka-plugins in (this step is usually not necessary):
tools/install-interceptors.sh
Commit 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 bothCFL_VERSION
andCFL_VERSION_STR
.docs/conf.py
- changeversion
variable.setup.py
- changeversion
argument tosetup()
.
Commit these changes with a commit-message containing the version:
$ git commit -m "Version v0.11.4rc1" src/confluent_kafka/src/confluent_kafka.c docs/conf.py setup.py
The following sections are performed in multiple iterations:
- TEST ITERATION - a number of test/release-candidate iterations where test tags are used to trigger CI builds. As many of these as required to get fully functional and verified.
- CANDIDATE ITERATION - when the builds test reliable, a release candidate RC tag is pushed. The resulting artifacts should be uploaded and tested with test.pypi.org.
- RELEASE ITERATION - a release tag is created on master after the rc branch has been merged. The resulting artifacts are uploaded to official pypi.org.
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.
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
.
TEST ITERATION:
# Repeat with new tags until all build issues are solved.
$ git tag v0.11.4rc1-dev2
# Delete any previous test tag you've created.
$ git tag tag -d v0.11.4rc1-dev1
CANDIDATE ITERATION:
$ git tag v0.11.4rc1
RELEASE ITERATION:
$ git tag v0.11.4
Perform a dry-run push first to make sure the correct branch and only our tag is pushed.
$ git push --dry-run --tags origin v0.11.4rc # tags and branch
An alternative is to push branch and tags separately:
$ git push --dry-run origin v0.11.4rc # the branch
$ git push --dry-run origin v0.11.4rc1 # the tag
Verify that the output corresponds to what you actually wanted to push; the correct branch and tag, etc.
Remove --dry-run
when you're happy with the results.
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 the resulting artifacts from build's Artifact directory located in another tab in the build:
Note: The artifacts should be extracted in the folder tools\dl-<tag>
for
subsequent steps to work properly.
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.
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.
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.
CANDIDATE ITERATION: To upload binary packages to test.pypi.org, use:
$ twine upload -r test dl-v0.11.4rc1/*
RELEASE ITERATION: To upload binary packages to the proper pypi.org (WARNING!), use:
$ twine upload dl-v0.11.4rc1/*
When uploading source packages make sure to have checked out the correct tag
and that you do not have any uncommited modifications and that the build/
directory is empty.
CANDIDATE ITERATION: Upload source packages to test.pypi.org:
$ python setup.py sdist upload -r test
RELEASE ITERATION: Upload source packages to the proper pypi.org (WARNING!):
$ python setup.py sdist upload
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:
$ pip install --pre confluent_kafka==0.11.4rc1
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:
$ pip install confluent_kafka
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.
Write a tweet to announce the new release, something like:
#Apache #Kafka #Python client confluent-kafka-python v0.11.4 released!
Adds support for <mainline feature> or something about maintenance release.
<link-to-release-notes-on-github>
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: includes
https://github.com/confluentinc/docs and
https://github.com/confluentinc/docs-platform.
# Update docs.confluent.io: cut the docs release branch of
https://github.com/confluentinc/docs-clients-confluent-kafka-python,
refers to https://confluentinc.atlassian.net/wiki/spaces/TOOLS/pages/2044330444/Create+a+new+version+of+a+documentation+repo#Create-new-release-branches.
That's it, back to the coal mine.