Skip to content

Commit 1eda6c7

Browse files
authored
INTPYTHON-589 Add automated release support for MongoDB-Labs Projects (#78)
1 parent 9ad9393 commit 1eda6c7

File tree

6 files changed

+283
-0
lines changed

6 files changed

+283
-0
lines changed

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,4 +355,79 @@ post-publish:
355355
product_name: winkerberos
356356
token: ${{ github.token }}
357357
dry_run: ${{ inputs.dry_run }}
358+
```
359+
360+
## Python Labs Helper Scripts
361+
362+
These scripts are opinionated helper scripts for Python releases in MongoDB Labs.
363+
In contrast to the regulare Python scripts, it does not generate the
364+
SSDLC compliance assets or upload anything to S3.
365+
366+
### Pre-Publish
367+
368+
Create a new tag. Verify the tag.
369+
Push the commit and tag to the source branch unless `dry_run` is set.
370+
371+
```yaml
372+
- name: Setup
373+
uses: mongodb-labs/drivers-github-tools/setup@v2
374+
with:
375+
...
376+
377+
- uses: mongodb-labs/drivers-github-tools/python-labs/pre-publishv2
378+
with:
379+
version_bump_script: ./.github/scripts/bump-version.sh
380+
dry_run: ${{ inputs.dry_run }}
381+
```
382+
383+
### Post-publish
384+
385+
To be run after separately publishing the [Python package](https://github.com/pypa/gh-action-pypi-publish#trusted-publishing).
386+
Handles follow-up tasks related to publishing Python packages.
387+
It will push the following (dev) version to the source branch.
388+
It will create a draft GitHub release with generated release notes.
389+
If `dry_run` is set, nothing will be pushed.
390+
391+
The jobs should look something like:
392+
393+
```yaml
394+
publish:
395+
name: Upload release to PyPI
396+
runs-on: ubuntu-latest
397+
environment: release
398+
permissions:
399+
id-token: write
400+
steps:
401+
- name: Download all the dists
402+
uses: actions/download-artifact@v4
403+
with:
404+
name: all-dist-${{ github.run_id }}
405+
path: dist/
406+
- name: Publish package distributions to PyPI
407+
if: inputs.dry_run == 'false'
408+
uses: pypa/gh-action-pypi-publish@release/v1
409+
410+
post-publish:
411+
needs: [publish]
412+
name: Handle post-publish actions
413+
runs-on: ubuntu-latest
414+
environment: release
415+
permissions:
416+
id-token: write
417+
contents: write
418+
attestations: write
419+
security-events: write
420+
steps:
421+
- name: Setup
422+
uses: mongodb-labs/drivers-github-tools/setup@v2
423+
with:
424+
...
425+
426+
- uses: mongodb-labs/drivers-github-tools/python-labs/post-publish@v2
427+
with:
428+
following_version: ${{ inputs.following_version }}
429+
version_bump_script: ./.github/scripts/bump-version.sh
430+
product_name: python-bsonjs
431+
token: ${{ github.token }}
432+
dry_run: ${{ inputs.dry_run }}
358433
```
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
2+
name: Python Labs Post-Publish
3+
description: Perform post-release operations for Python Libraries in MongoDB Labs
4+
inputs:
5+
following_version:
6+
description: The following (dev) version
7+
required: false
8+
product_name:
9+
description: The name of the product
10+
required: true
11+
version_bump_script:
12+
description: The version bump script
13+
default: hatch version
14+
working_directory:
15+
description: The working directory for the action
16+
default: "."
17+
tag_template:
18+
description: The template for the git tag
19+
default: "${VERSION}"
20+
repository-url:
21+
description: The PyPI repository URL to use
22+
default: https://upload.pypi.org/legacy/
23+
token:
24+
description: The GitHub access token
25+
dry_run:
26+
description: Whether this is a dry run
27+
required: true
28+
29+
runs:
30+
using: composite
31+
steps:
32+
- uses: actions/setup-python@v5
33+
with:
34+
python-version: '3.11'
35+
- name: Install hatch
36+
shell: bash
37+
run: pipx install hatch
38+
- name: Download all the dists
39+
uses: actions/download-artifact@v4
40+
with:
41+
name: all-dist-${{ github.run_id }}
42+
path: dist/
43+
- name: Get the package version
44+
shell: bash
45+
run: |
46+
# Handle version already bumped
47+
if [ -z "$VERSION" ]; then
48+
# Extract the version from the sdist name, which must be of the form
49+
# {name}-{version}.tar.gz according to PEP 625.
50+
VERSION=$(ls dist/*.tar.gz | rev | cut -d'-' -f 1 | rev | sed 's/.tar.gz//g')
51+
echo "VERSION=$VERSION" >> $GITHUB_ENV
52+
else
53+
echo "VERSION=$VERSION" >> $GITHUB_ENV
54+
fi
55+
- name: Run GitHub Publish script
56+
shell: bash
57+
id: publish-script
58+
run: ${{ github.action_path }}/post-publish.sh
59+
env:
60+
GH_TOKEN: ${{ inputs.token }}
61+
VERSION: ${{ env.VERSION }}
62+
TAG_TEMPLATE: ${{ inputs.tag_template }}
63+
PRODUCT_NAME: ${{ inputs.product_name }}
64+
DRY_RUN: ${{ inputs.dry_run }}
65+
FOLLOWING_VERSION: ${{ inputs.following_version }}
66+
- name: Ensure a clean repo
67+
shell: bash
68+
run: |
69+
git clean -dffx
70+
git pull origin ${GITHUB_REF}
71+
- name: Set following version
72+
uses: mongodb-labs/drivers-github-tools/bump-version@v2
73+
if: inputs.dry_run == 'false'
74+
with:
75+
version: ${{ steps.publish-script.outputs.following_version }}
76+
version_bump_script: ${{ inputs.version_bump_script }}
77+
working_directory: ${{ inputs.working_directory }}
78+
- name: Skip Setting following version
79+
shell: bash
80+
if: inputs.dry_run == 'true'
81+
run: |
82+
echo "Dry run, not setting the following version: ${{ steps.publish-script.outputs.following_version }}" >> $GITHUB_STEP_SUMMARY
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import sys
2+
from packaging.version import Version
3+
4+
version = Version(sys.argv[1])
5+
new_version = None
6+
7+
if version.is_devrelease:
8+
# For dev releases, increment the dev release number.
9+
new_version = f"{version.major}.{version.minor}.{version.micro}.dev{version.dev + 1}"
10+
elif version.is_prerelease:
11+
# For pre releases, go back to dev release.
12+
rel_type, rel_num = version.pre
13+
new_version = f"{version.major}.{version.minor}.{version.micro}.{rel_type}{rel_num + 1}"
14+
elif version.micro == 0:
15+
# For minor releases, go to next minor release.
16+
new_version = f"{version.major}.{version.minor + 1}.0.dev0"
17+
else:
18+
# For patch releases, go to the next patch release.
19+
new_version = f"{version.major}.{version.minor}.{version.micro + 1}.dev0"
20+
21+
print(str(new_version))
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
3+
set -eux
4+
5+
# Handle the following version.
6+
if [ -z "${FOLLOWING_VERSION}" ]; then
7+
pip install packaging
8+
pushd $GITHUB_ACTION_PATH
9+
FOLLOWING_VERSION=$(python handle_following_version.py $VERSION)
10+
popd
11+
fi
12+
echo "following_version=$FOLLOWING_VERSION" >> $GITHUB_OUTPUT
13+
14+
if [ "$DRY_RUN" == "false" ]; then
15+
PUSH_CHANGES=true
16+
echo "Creating draft release with attached files"
17+
TITLE="${PRODUCT_NAME} ${VERSION}"
18+
TAG=$(echo "${TAG_TEMPLATE}" | envsubst)
19+
gh release create ${TAG} --draft --verify-tag --title "${TITLE}" --generate-notes
20+
gh release upload ${TAG} $RELEASE_ASSETS/*.*
21+
JSON="url,tagName,assets,author,createdAt"
22+
JQ='.url,.tagName,.author.login,.createdAt,.assets[].name'
23+
echo "\## $TITLE" >> $GITHUB_STEP_SUMMARY
24+
gh release view --json $JSON --jq $JQ ${TAG} >> $GITHUB_STEP_SUMMARY
25+
else
26+
echo "Dry run, not creating GitHub Release" >> $GITHUB_STEP_SUMMARY
27+
ls -ltr $RELEASE_ASSETS
28+
PUSH_CHANGES=false
29+
fi
30+
31+
# Handle push_changes output.
32+
echo "push_changes=$PUSH_CHANGES" >> $GITHUB_OUTPUT

python-labs/pre-publish/action.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Python Labs Pre-Publish
2+
description: Perform pre-release operations for Python Libraries in MongoDB Labs
3+
inputs:
4+
tag_template:
5+
description: The template for the git tag
6+
default: "${VERSION}"
7+
tag_message_template:
8+
description: The template for the git tag message
9+
default: "Release ${VERSION}"
10+
working_directory:
11+
description: The working directory for the action
12+
default: "."
13+
dry_run:
14+
description: Whether this is a dry run
15+
required: true
16+
17+
outputs:
18+
version:
19+
description: The output version to use
20+
value: ${{ steps.version.outputs.version }}
21+
22+
runs:
23+
using: composite
24+
steps:
25+
- uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.11'
28+
- name: Install hatch
29+
shell: bash
30+
working-directory: ${{ inputs.working_directory }}
31+
run: |
32+
pipx install hatch
33+
pip install build
34+
- name: Handle inputs
35+
shell: bash
36+
working-directory: ${{ inputs.working_directory }}
37+
env:
38+
DRY_RUN: "${{ inputs.dry_run }}"
39+
run: |
40+
set -eux
41+
# Handle DRY_RUN
42+
if [ "$DRY_RUN" != "true" ]; then
43+
export PUSH_CHANGES=true
44+
else
45+
export PUSH_CHANGES=false
46+
fi
47+
echo "PUSH_CHANGES=$PUSH_CHANGES" >> $GITHUB_ENV
48+
# Handle version
49+
# Extract the version from the sdist name, which must be of the form
50+
# {name}-{version}.tar.gz according to PEP 625.
51+
python -m build --sdist .
52+
VERSION=$(ls dist/*.tar.gz | rev | cut -d'-' -f 1 | rev | sed 's/.tar.gz//g')
53+
echo "VERSION=$VERSION" >> $GITHUB_ENV
54+
rm -rf dist
55+
- name: Tag version
56+
uses: mongodb-labs/drivers-github-tools/tag-version@v2
57+
with:
58+
version: ${{ env.VERSION }}
59+
tag_template: ${{ inputs.tag_template }}
60+
tag_message_template: ${{ inputs.tag_message_template }}
61+
push_tag: ${{ env.PUSH_CHANGES }}
62+
- name: Handle version output
63+
shell: bash
64+
id: version
65+
run: |
66+
if [ "${{ inputs.dry_run}}" == 'true' ]; then
67+
echo "version=${{ github.ref }}" >> $GITHUB_OUTPUT
68+
else
69+
export VERSION=${{ env.VERSION }}
70+
export TAG=$(echo "${{ inputs.tag_template }}" | envsubst)
71+
echo "version=$TAG" >> $GITHUB_OUTPUT
72+
fi

python/pre-publish/action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ runs:
3838
pip install build
3939
- name: Handle inputs
4040
shell: bash
41+
working-directory: ${{ inputs.working_directory }}
4142
env:
4243
VERSION: "${{ inputs.version }}"
4344
DRY_RUN: "${{ inputs.dry_run }}"

0 commit comments

Comments
 (0)