Skip to content

CD Release and Publish #31

CD Release and Publish

CD Release and Publish #31

Workflow file for this run

name: CD Release and Publish
on:
workflow_run:
workflows:
- CI Testing Workflow
types:
- completed
branches:
- main
# default: least privileged permissions across all jobs
permissions:
contents: read
jobs:
check_success:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Workflow completed successfully
run: echo "CI workflow passed. Proceeding with CD."
release:
runs-on: ubuntu-latest
needs: check_success
concurrency:
group: ${{ github.workflow }}-release-${{ github.ref_name }}
cancel-in-progress: false
environment: release
permissions:
contents: write
outputs:
released: ${{ steps.release.outputs.released }}
steps:
# Note: We checkout the repository at the branch that triggered the workflow
# with the entire history to ensure to match PSR's release branch detection
# and history evaluation.
# However, we forcefully reset the branch to the workflow sha because it is
# possible that the branch was updated while the workflow was running. This
# prevents accidentally releasing un-evaluated changes.
- name: Setup | Checkout Repository on Release Branch
uses: actions/checkout@v4
with:
token: ${{ secrets.PYTHON_SEMANTIC_RELEASE_TOKEN }}
ref: ${{ github.ref_name }}
fetch-depth: 0
- name: Setup | Force release branch to be at workflow sha
run: |
git reset --hard ${{ github.sha }}
- name: Evaluate | Verify upstream has NOT changed
# Last chance to abort before causing an error as another PR/push was applied to
# the upstream branch while this workflow was running. This is important
# because we are committing a version change (--commit). You may omit this step
# if you have 'commit: false' in your configuration.
#
# You may consider moving this to a repo script and call it from this step instead
# of writing it in-line.
shell: bash
run: |
set +o pipefail
UPSTREAM_BRANCH_NAME="$(git status -sb | head -n 1 | awk -F '\\.\\.\\.' '{print $2}' | cut -d ' ' -f1)"
printf '%s\n' "Upstream branch name: $UPSTREAM_BRANCH_NAME"
set -o pipefail
if [ -z "$UPSTREAM_BRANCH_NAME" ]; then
printf >&2 '%s\n' "::error::Unable to determine upstream branch name!"
exit 1
fi
git fetch "${UPSTREAM_BRANCH_NAME%%/*}"
if ! UPSTREAM_SHA="$(git rev-parse "$UPSTREAM_BRANCH_NAME")"; then
printf >&2 '%s\n' "::error::Unable to determine upstream branch sha!"
exit 1
fi
HEAD_SHA="$(git rev-parse HEAD)"
if [ "$HEAD_SHA" != "$UPSTREAM_SHA" ]; then
printf >&2 '%s\n' "[HEAD SHA] $HEAD_SHA != $UPSTREAM_SHA [UPSTREAM SHA]"
printf >&2 '%s\n' "::error::Upstream has changed, aborting release..."
exit 1
fi
printf '%s\n' "Verified upstream branch has not changed, continuing with release..."
- name: Action | Semantic Version Release
id: release
# Adjust tag with desired version if applicable.
uses: python-semantic-release/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
git_committer_name: "github-actions"
git_committer_email: "[email protected]"
- name: Publish | Upload to GitHub Release Assets
uses: python-semantic-release/[email protected]
if: steps.release.outputs.released == 'true'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ steps.release.outputs.tag }}
- name: Upload | Distribution Artifacts
uses: actions/upload-artifact@v4
if: steps.release.outputs.released == 'true'
with:
name: distribution-artifacts
path: dist
if-no-files-found: error
deploy:
# 1. Separate out the deploy step from the publish step to run each step at
# the least amount of token privilege
# 2. Also, deployments can fail, and its better to have a separate job if you need to retry
# and it won't require reversing the release.
runs-on: ubuntu-latest
needs: release
if: ${{ needs.release.outputs.released == 'true' }}
environment: release
permissions:
contents: read
id-token: write
steps:
- name: Setup | Download Build Artifacts
uses: actions/download-artifact@v4
id: artifact-download
with:
name: distribution-artifacts
path: dist
- name: Publish package distributions to PyPI
uses: pypa/[email protected]
with:
packages-dir: dist
print-hash: true
verbose: true