Skip to content

Create and Publish Release #2

Create and Publish Release

Create and Publish Release #2

Workflow file for this run

name: "Create and Publish Release"
on:
workflow_dispatch:
inputs:
release_pr_number:
description: "The pull request number to merge that contains the package version bumps and changelog updates."
required: true
type: number
release_version:
description: "The tag name for the release (e.g., v1.2.3)"
required: true
type: string
dry_run:
description: "Set to true to 'dry-run'/not actually publish to PyPI."
default: "true"
required: true
type: boolean
python_version:
description: 'The Python version to build with.'
default: '3.10'
required: true
type: 'string'
jobs:
release_and_publish:
runs-on: ubuntu-24.04
permissions:
contents: write # Needed for creating releases and tags, and deleting branches
pull-requests: write # Needed for merging the PR
steps:
- name: Get Pull Request Info (Base Branch, Release Notes)
id: get_pr_info
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = parseInt(process.env.RELEASE_PR_NUMBER, 10);
const result = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
core.setOutput('RELEASE_NOTES', result.data.body);
core.setOutput('RELEASE_TAG', process.env.RELEASE_VERSION);
core.setOutput('BASE_BRANCH', result.data.base.ref); // Capture base branch
env:
RELEASE_PR_NUMBER: ${{ github.event.inputs.release_pr_number }}
RELEASE_VERSION: ${{ github.event.inputs.release_version }}
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ steps.get_pr_info.outputs.BASE_BRANCH }}
fetch-depth: 0
- name: Set up Git
run: |
git config --local user.name "GitHub Actions"
git config --local user.email "actions@github.com"
- name: Merge Pull Request
uses: actions/github-script@v7
id: merge_pr
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = parseInt('${{ github.event.inputs.release_pr_number }}', 10);
const result = await github.rest.pulls.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
core.setOutput('merged', result.data.merged);
- name: Ensure latest changes from merged PR
run: |
git fetch origin ${{ steps.get_pr_info.outputs.BASE_BRANCH }}
git reset --hard origin/${{ steps.get_pr_info.outputs.BASE_BRANCH }}
- name: Create Release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.event.inputs.release_version }}
name: ${{ github.event.inputs.release_version }}
body: ${{ steps.get_pr_info.outputs.RELEASE_NOTES }}
generate_release_notes: false
# Set up Python environment
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: ${{ inputs.python_version }}
# Install required tools for building and publishing the package
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
# Build the package
- name: Build the package
run: python -m build
# Publish to PyPI
- name: Publish to PyPI
run: |
echo 'DRY_RUN: '$DRY_RUN
if [ "$DRY_RUN" == "false" ]; then
twine upload dist/*
else
twine upload --repository testpypi dist/*
fi
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
DRY_RUN: ${{ inputs.dry_run }}
- name: Delete branch after merge
if: steps.merge_pr.outputs.merged == 'true' # Only delete if merge was successful
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const branchName = `release/${{ github.event.inputs.release_version }}`;
try {
await github.rest.git.deleteRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `heads/${branchName}`,
});
console.log(`Successfully deleted branch: ${branchName}`);
} catch (error) {
console.error(`Failed to delete branch ${branchName}:`, error);
}
- name: Notify Slack - Release Completed
id: slack-release
uses: slackapi/slack-github-action@v1.27.1
env:
SDK: ${{ github.event.repository.name }}
RELEASE_TAG: ${{ steps.get_pr_info.outputs.RELEASE_TAG }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_RELEASE_NOTIFICATIONS_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
with:
payload: |
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*${{ env.SDK }} ${{ env.RELEASE_TAG }}* was released today. https://github.com/${{ github.repository }}/releases/tag/${{ env.RELEASE_TAG }}"
}
}
]
}