From 1150d179b4e31aec8de330b11478d278ad31b003 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 21 Apr 2025 06:40:20 -0500 Subject: [PATCH 1/5] INTPYTHON-589 Add automated release workflow --- .github/workflows/dist-python.yml | 74 ++++++++++++++ .github/workflows/release-python.yml | 148 +++++++++++++++------------ 2 files changed, 155 insertions(+), 67 deletions(-) create mode 100644 .github/workflows/dist-python.yml diff --git a/.github/workflows/dist-python.yml b/.github/workflows/dist-python.yml new file mode 100644 index 0000000..5077bbd --- /dev/null +++ b/.github/workflows/dist-python.yml @@ -0,0 +1,74 @@ +name: Python Dist + +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: + pull_request: + workflow_call: + inputs: + ref: + required: true + type: string + +concurrency: + group: dist-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash -eux {0} + +jobs: + make_dist: + name: Make Dist + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - uses: actions/setup-python@v5 + with: + # Build sdist on lowest supported Python + python-version: '3.9' + + - name: Install python requirements + run: | + python -m pip install uv rust-just build + + - name: Build Dist + run: | + python -m build . + + - name: Test SDist + run: | + python -m pip install dist/*.gz + cd .. + python -c "from flask_pymongo import PyMongo" + + - uses: actions/upload-artifact@v4 + with: + name: "dist" + path: ./bindings/python/dist/*.* + + collect_dist: + runs-on: ubuntu-latest + needs: [make_dist] + name: Download Dist + steps: + - name: Download all workflow run artifacts + uses: actions/download-artifact@v4 + - name: Flatten directory + working-directory: . + run: | + find . -mindepth 2 -type f -exec mv {} . \; + find . -type d -empty -delete + - uses: actions/upload-artifact@v4 + with: + name: all-dist-${{ github.run_id }} + path: "./*" diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index 519ef9d..8463db0 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -1,12 +1,25 @@ -name: Python Wheels +name: Release on: - push: - branches: ["main"] - tags: - - "**" - pull_request: workflow_dispatch: + inputs: + following_version: + description: "The post (dev) version to set" + dry_run: + description: "Dry Run?" + default: false + type: boolean + schedule: + - cron: '30 5 * * *' + +env: + # Changes per repo + PRODUCT_NAME: Flask-PyMongo + # Constant + # inputs will be empty on a scheduled run. so, we only set dry_run + # to 'false' when the input is set to 'false'. + DRY_RUN: ${{ ! contains(inputs.dry_run, 'false') }} + FOLLOWING_VERSION: ${{ inputs.following_version || '' }} concurrency: group: wheels-${{ github.ref }} @@ -17,83 +30,84 @@ defaults: shell: bash -eux {0} jobs: - - build_dist: - name: Build Distribution Files + pre-publish: + environment: release runs-on: ubuntu-latest + if: github.repository_owner == 'mongodb-labs' || github.event_name == 'workflow_dispatch' + permissions: + id-token: write + contents: write + outputs: + version: ${{ steps.pre-publish.outputs.version }} steps: - - uses: actions/checkout@v4 + - uses: mongodb-labs/drivers-github-tools/secure-checkout@v2 with: - fetch-depth: 0 - persist-credentials: false - - - uses: actions/setup-python@v5 + app_id: ${{ vars.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: mongodb-labs/drivers-github-tools/setup@v2 with: - # Build sdist on lowest supported Python - python-version: '3.9' - - - name: Install build - run: | - python -m pip install build - - - name: build the dist files - run: | - python -m build . - - - name: Upload the dist files - uses: actions/upload-artifact@v4 + aws_role_arn: ${{ secrets.AWS_ROLE_ARN }} + aws_region_name: ${{ vars.AWS_REGION_NAME }} + aws_secret_id: ${{ secrets.AWS_SECRET_ID }} + artifactory_username: ${{ vars.ARTIFACTORY_USERNAME }} + - uses: mongodb-labs/drivers-github-tools/python-labs/pre-publish@v2 + id: pre-publish with: - name: dist-${{ github.run_id }} - path: ./dist/*.* + dry_run: ${{ env.DRY_RUN }} - test_dist: - needs: [build_dist] - name: Test Distribution Files - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - persist-credentials: false - - - uses: actions/setup-python@v5 - with: - # Build sdist on lowest supported Python - python-version: '3.9' - - - name: Download the dists - uses: actions/download-artifact@v4 - with: - name: dist-${{ github.run_id }} - path: dist/ - - - name: Test the sdist - run: | - cd dist - pip install *.tar.gz - python -c "import flask_pymongo" - pip uninstall -y flask_pymongo - - - name: Test the wheel - run: | - cd dist - pip install *.whl - python -c "import flask_pymongo" - pip uninstall -y flask_pymongo + build-dist: + needs: [pre-publish] + uses: ./.github/workflows/dist-python.yml + with: + ref: ${{ needs.pre-publish.outputs.version }} publish: # https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#publishing-the-distribution-to-pypi - needs: [test_dist] - if: startsWith(github.ref, 'refs/tags/') + needs: [build-dist] + if: (github.repository_owner == 'mongodb-labs' && github.event_name != 'pull_request') || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest environment: release permissions: id-token: write steps: - - name: Download the dists + - name: Download all the dists uses: actions/download-artifact@v4 with: - name: dist-${{ github.run_id }} + name: all-dist-${{ github.run_id }} path: dist/ + - name: Publish package distributions to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + skip-existing: true + attestations: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Publish distribution 📦 to PyPI + if: startsWith(github.ref, 'refs/tags/') uses: pypa/gh-action-pypi-publish@release/v1 + + post-publish: + needs: [publish] + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write + contents: write + attestations: write + security-events: write + steps: + - uses: mongodb-labs/drivers-github-tools/secure-checkout@v2 + with: + app_id: ${{ vars.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: mongodb-labs/drivers-github-tools/setup@v2 + with: + aws_role_arn: ${{ secrets.AWS_ROLE_ARN }} + aws_region_name: ${{ vars.AWS_REGION_NAME }} + aws_secret_id: ${{ secrets.AWS_SECRET_ID }} + artifactory_username: ${{ vars.ARTIFACTORY_USERNAME }} + - uses: mongodb-labs/drivers-github-tools/python-labs/post-publish@v2 + with: + following_version: ${{ env.FOLLOWING_VERSION }} + product_name: ${{ env.PRODUCT_NAME }} + token: ${{ github.token }} + dry_run: ${{ env.DRY_RUN }} From e32926794e7e9bdb9b39dfc40dd18b9e3722aa5e Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 21 Apr 2025 06:45:37 -0500 Subject: [PATCH 2/5] fix path --- .github/workflows/dist-python.yml | 2 +- .github/workflows/release-python.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dist-python.yml b/.github/workflows/dist-python.yml index 5077bbd..b53f634 100644 --- a/.github/workflows/dist-python.yml +++ b/.github/workflows/dist-python.yml @@ -54,7 +54,7 @@ jobs: - uses: actions/upload-artifact@v4 with: name: "dist" - path: ./bindings/python/dist/*.* + path: ./dist/*.* collect_dist: runs-on: ubuntu-latest diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index 8463db0..c729470 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -22,7 +22,7 @@ env: FOLLOWING_VERSION: ${{ inputs.following_version || '' }} concurrency: - group: wheels-${{ github.ref }} + group: dist-${{ github.ref }} cancel-in-progress: true defaults: From da225b74dbeb230261429748b294a7358ffc8484 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 21 Apr 2025 06:47:37 -0500 Subject: [PATCH 3/5] fix concurrency --- .github/workflows/release-python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index c729470..15c42c1 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -22,7 +22,7 @@ env: FOLLOWING_VERSION: ${{ inputs.following_version || '' }} concurrency: - group: dist-${{ github.ref }} + group: release-${{ github.ref }} cancel-in-progress: true defaults: From 17bdfd1be7ad8e7768bb79f6b5aca750f979bd86 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 21 Apr 2025 07:00:11 -0500 Subject: [PATCH 4/5] skip test pypi --- .github/workflows/release-python.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index 15c42c1..31553b0 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -75,12 +75,6 @@ jobs: with: name: all-dist-${{ github.run_id }} path: dist/ - - name: Publish package distributions to TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: https://test.pypi.org/legacy/ - skip-existing: true - attestations: ${{ !startsWith(github.ref, 'refs/tags/') }} - name: Publish distribution 📦 to PyPI if: startsWith(github.ref, 'refs/tags/') uses: pypa/gh-action-pypi-publish@release/v1 From d34f7427b910e7cf01bd1ae5216a458bf6029208 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 21 Apr 2025 07:14:51 -0500 Subject: [PATCH 5/5] add twine check --- .github/workflows/dist-python.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dist-python.yml b/.github/workflows/dist-python.yml index b53f634..43668ee 100644 --- a/.github/workflows/dist-python.yml +++ b/.github/workflows/dist-python.yml @@ -39,7 +39,7 @@ jobs: - name: Install python requirements run: | - python -m pip install uv rust-just build + python -m pip install uv rust-just build twine - name: Build Dist run: | @@ -47,6 +47,7 @@ jobs: - name: Test SDist run: | + python -m twine check --strict dist/*.* python -m pip install dist/*.gz cd .. python -c "from flask_pymongo import PyMongo"