diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml new file mode 100644 index 000000000..334a4039b --- /dev/null +++ b/.github/workflows/release-python.yml @@ -0,0 +1,152 @@ +name: Python Wheels + +on: + push: + tags: + - "[0-9]+.[0-9]+.[0-9]+" + - "[0-9]+.[0-9]+.[0-9]+.post[0-9]+" + - "[0-9]+.[0-9]+.[0-9]+[a-b][0-9]+" + - "[0-9]+.[0-9]+.[0-9]+rc[0-9]+" + workflow_dispatch: + +concurrency: + group: wheels-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash -eux {0} + +jobs: + build_wheels: + name: Build wheel for ${{ matrix.python }}-${{ matrix.buildplat[1] }} + runs-on: ${{ matrix.buildplat[0] }} + strategy: + # Ensure that a wheel builder finishes even if another fails + fail-fast: false + matrix: + # Github Actions doesn't support pairing matrix values together, let's improvise + # https://github.com/github/feedback/discussions/7835#discussioncomment-1769026 + buildplat: + - [ubuntu-20.04, manylinux_x86_64] + - [ubuntu-20.04, manylinux_aarch64] + - [ubuntu-20.04, manylinux_ppc64le] + - [ubuntu-20.04, manylinux_s390x] + - [ubuntu-20.04, manylinux_i686] + - [macos-11, macosx_*] + - [windows-2019, win_amd64] + - [windows-2019, win32] + python: ["cp37", "cp38", "cp39", "cp310", "cp311", "cp312"] + + steps: + - name: Checkout pymongo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up python version + run: | + export PYTHON_VERSION=$(sed 's/^cp3/3./' <<< ${{ matrix.python }} ) + echo "PYTHON_VERSION=$PYTHON_VERSION" >> $GITHUB_ENV + + - uses: actions/setup-python@v4 + with: + python-version: ${{env.PYTHON_VERSION}} + cache: 'pip' + cache-dependency-path: 'pyproject.toml' + allow-prereleases: true + + - name: Set up QEMU + if: runner.os == 'Linux' + uses: docker/setup-qemu-action@v2 + with: + platforms: all + + - name: Install cibuildwheel + run: python -m pip install "cibuildwheel>=2.4,<3" + + - name: Build MacOS Py37 Wheel + # Universal wheels are not supported with Python 3.7, so we explicitly + # produce an x86_64 wheel for Python 3.7 on MacOS. + if: ${{ matrix.python == 'cp37' && matrix.buildplat[0] == 'macos-11' }} + env: + CIBW_BUILD: cp37-macosx_x86_64 + CIBW_ARCHS: x86_64 + CIBW_TEST_COMMAND: "python {project}/tools/fail_if_no_c.py" + run: python -m cibuildwheel --output-dir wheelhouse + + - name: Build wheels + if: ${{ matrix.python != 'cp37' || matrix.buildplat[0] != 'macos-11' }} + env: + CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }} + run: python -m cibuildwheel --output-dir wheelhouse + + - uses: actions/upload-artifact@v3 + with: + name: wheel-${{ matrix.python }}-${{ startsWith(matrix.buildplat[1], 'macosx') && 'macosx' || matrix.buildplat[1] }} + path: ./wheelhouse/*.whl + if-no-files-found: error + + make_sdist: + name: Make SDist + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v4 + with: + # Build sdist on lowest supported Python + python-version: '3.7' + + - name: Build SDist + run: | + set -ex + python -m pip install -U pip build + python -m build --sdist . + + - name: Test SDist + run: | + python -m pip install dist/*.gz + cd .. + python -c "from pymongo import has_c; assert has_c()" + + - uses: actions/upload-artifact@v3 + with: + name: "sdist" + path: ./dist/*.tar.gz + + collect_dist: + runs-on: ubuntu-latest + needs: [build_wheels, make_sdist] + name: Download Wheels + steps: + - name: Download all workflow run artifacts + uses: actions/download-artifact@v3 + - name: Flatten directory + working-directory: . + run: | + find . -mindepth 2 -type f -exec mv {} . \; + find . -type d -empty -delete + - uses: actions/upload-artifact@v3 + with: + name: all-dist-${{ github.head_ref || github.ref_name }} + path: "./*" + + publish: + # https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#publishing-the-distribution-to-pypi + needs: [collect_dist] + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write + steps: + - name: Download all the dists + uses: actions/download-artifact@v3 + with: + name: all-dist-${{ github.head_ref || github.ref_name }} + path: dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/RELEASE.md b/RELEASE.md index 05d7c8d63..3c2990df0 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -28,52 +28,41 @@ be removed in a release that changes the major version number. ## Doing a Release -1. PyMongo is tested on Evergreen. Ensure the latest commit are passing +1. PyMongo is tested on Evergreen. Ensure the latest commit are passing [CI](https://spruce.mongodb.com/commits/mongo-python-driver) as expected. -2. Check Jira to ensure all the tickets in this version have been +2. Check Jira to ensure all the tickets in this version have been completed. -3. Add release notes to `doc/changelog.rst`. Generally just +3. Make a PR that adds the release notes to `doc/changelog.rst`. Generally just summarize/clarify the git log, but you might add some more long form notes for big changes. -4. Make sure version number is updated in `pymongo/_version.py` +4. Merge the PR. -5. Commit with a BUMP version_number message, eg - `git commit -m 'BUMP 3.11.0'`. +5. Clone the source repository in a temporary directory and check out the + release branch. -6. Tag w/ version_number, eg, - `git tag -a '3.11.0' -m 'BUMP 3.11.0' `. +6. Update the version number in `pymongo/_version.py`. -7. Bump the version number to `.dev0` in +7. Commit the change, e.g. `git add . && git commit -m "BUMP "` + +7. Tag w/ version_number, eg, + `git tag -a '4.1.0' -m 'BUMP 4.1.0'`. + +8. Bump the version number to `.dev0` in `pymongo/_version.py`, commit, push. -8. Push commit / tag, eg `git push && git push --tags`. +9. Push commit / tag, eg `git push && git push --tags`. -9. Pushing a tag will trigger a release process in Evergreen which - builds wheels for manylinux, macOS, and Windows. Wait for the - "release-combine" task to complete and then download the "Release - files all" archive. See https://spruce.mongodb.com/commits/mongo-python-driver?buildVariants=release&view=ALL - - The contents should look like this: - - $ ls path/to/archive - pymongo--cp310-cp310-macosx_10_9_universal2.whl - ... - pymongo--cp38-cp38-manylinux2014_x86_64.whl - ... - pymongo--cp38-cp38-win_amd64.whl - ... - pymongo-.tar.gz - -10. Upload all the release packages to PyPI with twine: - - $ python3 -m twine upload path/to/archive/* +10. Pushing a tag will trigger the release process on GitHub Actions + that will require a member of the team to authorize the deployment. + Navigate to https://github.com/mongodb/mongo-python-driver/actions/workflows/release-python.yml + and wait for the publish to complete. 11. Make sure the new version appears on `https://pymongo.readthedocs.io/en/stable/`. If the new version does not show - up automatically, trigger a rebuild of "latest" on https://readthedocs.org/projects/pymongo/builds/. + up automatically, trigger a rebuild of "stable" on https://readthedocs.org/projects/pymongo/builds/. 12. Publish the release version in Jira and add a description of the release, such as a the reason or the main feature. @@ -87,3 +76,34 @@ be removed in a release that changes the major version number. The title should be "PyMongo X.Y.Z", and the description should contain a link to the release notes on the the community forum, e.g. "Release notes: mongodb.com/community/forums/t/pymongo-4-0-2-released/150457" + +16. Wait for automated update PR on conda-forge, e.g.: https://github.com/conda-forge/pymongo-feedstock/pull/81 + Update dependencies if needed. + + +## Doing a Bug Fix Release + +1. If it is a new branch, first create the release branch and Evergreen project. + +- Clone the source repository in a temporary location. + +- Create a branch from the tag, e.g. `git checkout -b v4.1 4.1.0`. + +- Push the branch, e.g.: `git push origin v4.6`. + +- Create a new project in Evergreen for the branch by duplicating the "Mongo Python Driver" project. + Select the option to create a JIRA ticket for S3 bucket permissions. + +- Update the "Display Name", "Branch Name", and "Identifier". + +- Attach the project to the repository. + +- Wait for the JIRA ticket to be resolved and verify S3 upload capability with a patch release on the + new project. + +2. Create a PR against the release branch. + +3. Create a release using the "Doing a Release" checklist above, ensuring that you + check out the appropriate release branch in the source checkout. + +4. Cherry-pick the changelog PR onto the `master` branch. diff --git a/pyproject.toml b/pyproject.toml index db2c95669..5f75f2733 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -224,3 +224,17 @@ partial_branches = ["if (.*and +)*not _use_c( and.*)*:"] [tool.coverage.html] directory = "htmlcov" + +[tool.cibuildwheel] +skip = "pp* *-musllinux*" +build-frontend = "build" +test-command = "python {project}/tools/fail_if_no_c.py" + +[tool.cibuildwheel.linux] +archs = "x86_64 aarch64 ppc64le s390x i686" +manylinux-x86_64-image = "manylinux_2_28" + +[tool.cibuildwheel.macos] +archs = "universal2" +test-command = "ENSURE_UNIVERSAL2=1 python {project}/tools/fail_if_no_c.py" +test-skip = "*-macosx_universal2:arm64"