9.9.9 - Version Bump and Changelog Generation #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# **what?** | |
# Perform the version bump, generate the changelog and run tests. | |
# | |
# Inputs: | |
# version_number: The release version number (i.e. 1.0.0b1, 1.2.3rc2, 1.0.0) | |
# test_run: Test run (The temp branch will be used for release) | |
# | |
# Branching strategy: | |
# - During execution workflow execution the temp branch will be generated. | |
# - For normal runs the temp branch will be removed once changes were merged to target branch; | |
# - For test runs we will keep temp branch and will use it for release; | |
# Naming strategy: | |
# - For normal runs: prep-release/${{ inputs.version_number }}_$GITHUB_RUN_ID | |
# - For test runs: prep-release/test-run/${{ inputs.version_number }}_$GITHUB_RUN_ID | |
# | |
# **why?** | |
# Reusable and consistent GitHub release process. | |
# | |
# **when?** | |
# Call when ready to kick off a build and release | |
# | |
# Validation Checks | |
# | |
# 1. Bump the version if it has not been bumped | |
# 2. Generate the changelog (via changie) if there is no markdown file for this version | |
# | |
name: Version Bump and Changelog Generation | |
run-name: "${{ inputs.version_number }} - Version Bump and Changelog Generation" | |
on: | |
workflow_dispatch: | |
inputs: | |
version_number: | |
required: true | |
type: string | |
test_run: | |
required: false | |
default: true | |
type: boolean | |
permissions: | |
contents: write | |
defaults: | |
run: | |
shell: bash | |
env: | |
PYTHON_TARGET_VERSION: 3.9 | |
NOTIFICATION_PREFIX: "[Release Preparation]" | |
jobs: | |
log-inputs: | |
runs-on: ubuntu-latest | |
steps: | |
- name: "[DEBUG] Print Variables" | |
run: | | |
# WORKFLOW INPUTS | |
echo The release version number: ${{ inputs.version_number }} | |
echo Test run: ${{ inputs.test_run }} | |
# ENVIRONMENT VARIABLES | |
echo Python target version: ${{ env.PYTHON_TARGET_VERSION }} | |
echo Notification prefix: ${{ env.NOTIFICATION_PREFIX }} | |
audit-changelog: | |
runs-on: ubuntu-latest | |
outputs: | |
changelog_path: ${{ steps.set_path.outputs.changelog_path }} | |
exists: ${{ steps.set_existence.outputs.exists }} | |
base_version: ${{ steps.semver.outputs.base-version }} | |
prerelease: ${{ steps.semver.outputs.pre-release }} | |
is_prerelease: ${{ steps.semver.outputs.is-pre-release }} | |
steps: | |
- name: "Checkout ${{ github.repository }} Commit ${{ github.ref }}" | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ github.ref }} | |
- name: "Audit Version And Parse Into Parts" | |
id: semver | |
uses: dbt-labs/actions/[email protected] | |
with: | |
version: ${{ inputs.version_number }} | |
- name: "Set Changelog Path" | |
id: set_path | |
run: | | |
path=".changes/${{ steps.semver.outputs.base-version }}.md" | |
# Send notification | |
echo "changelog_path=$path" >> $GITHUB_OUTPUT | |
title="Changelog path" | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$changelog_path" | |
- name: "Set Changelog Existence For Subsequent Jobs" | |
id: set_existence | |
run: | | |
does_exist=false | |
if test -f ${{ steps.set_path.outputs.changelog_path }} | |
then | |
does_exist=true | |
fi | |
echo "exists=$does_exist">> $GITHUB_OUTPUT | |
- name: "[Notification] Set Changelog Existence For Subsequent Jobs" | |
run: | | |
title="Changelog exists" | |
if [[ ${{ steps.set_existence.outputs.exists }} == true ]] | |
then | |
message="Changelog file ${{ steps.set_path.outputs.changelog_path }} already exists" | |
else | |
message="Changelog file ${{ steps.set_path.outputs.changelog_path }} doesn't exist" | |
fi | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
- name: "[DEBUG] Print Outputs" | |
run: | | |
echo changelog_path: ${{ steps.set_path.outputs.changelog_path }} | |
echo exists: ${{ steps.set_existence.outputs.exists }} | |
echo base_version: ${{ steps.semver.outputs.base-version }} | |
echo prerelease: ${{ steps.semver.outputs.pre-release }} | |
echo is_prerelease: ${{ steps.semver.outputs.is-pre-release }} | |
audit-version-in-code: | |
runs-on: ubuntu-latest | |
outputs: | |
up_to_date: ${{ steps.version-check.outputs.up_to_date }} | |
steps: | |
- name: "Checkout ${{ github.repository }} Commit ${{ github.ref }}" | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ github.ref }} | |
- name: "Set up Python & Hatch - ${{ env.PYTHON_TARGET_VERSION }}" | |
uses: ./.github/actions/setup-python-hatch | |
with: | |
python-version: "${{ env.PYTHON_TARGET_VERSION }}" | |
- name: "Check Current Version In Code" | |
id: version-check | |
run: | | |
is_updated=false | |
current_version=$(hatch version) | |
if [ "$current_version" == "${{ inputs.version_number }}" ]; then | |
is_updated=true | |
fi | |
echo "up_to_date=$is_updated" >> $GITHUB_OUTPUT | |
- name: "[Notification] Check Current Version In Code" | |
run: | | |
title="Version check" | |
if [[ ${{ steps.version-check.outputs.up_to_date }} == true ]] | |
then | |
message="The version in the codebase is equal to the provided version" | |
else | |
message="The version in the codebase differs from the provided version" | |
fi | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
- name: "[DEBUG] Print Outputs" | |
run: | | |
echo up_to_date: ${{ steps.version-check.outputs.up_to_date }} | |
skip-generate-changelog: | |
runs-on: ubuntu-latest | |
needs: [audit-changelog] | |
if: needs.audit-changelog.outputs.exists == 'true' | |
steps: | |
- name: "Changelog Exists, Skip Generating New Changelog" | |
run: | | |
# Send notification | |
title="Skip changelog generation" | |
message="A changelog file already exists at ${{ needs.audit-changelog.outputs.changelog_path }}, skipping generating changelog" | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
skip-version-bump: | |
runs-on: ubuntu-latest | |
needs: [audit-version-in-code] | |
if: needs.audit-version-in-code.outputs.up_to_date == 'true' | |
steps: | |
- name: "Version Already Bumped" | |
run: | | |
# Send notification | |
title="Skip version bump" | |
message="The version has already been bumped to ${{ inputs.version_number }}, skipping version bump" | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
create-temp-branch: | |
runs-on: ubuntu-latest | |
needs: [audit-changelog, audit-version-in-code] | |
if: needs.audit-changelog.outputs.exists == 'false' || needs.audit-version-in-code.outputs.up_to_date == 'false' | |
outputs: | |
branch_name: ${{ steps.variables.outputs.branch_name }} | |
steps: | |
- name: "Checkout ${{ github.repository }} Commit ${{ github.ref }}" | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ github.ref }} | |
- name: "Generate Branch Name" | |
id: variables | |
run: | | |
name="prep-release/" | |
if [[ ${{ inputs.test_run }} == true ]] | |
then | |
name+="test-run/" | |
fi | |
name+="${{ inputs.version_number }}_$GITHUB_RUN_ID" | |
echo "branch_name=$name" >> $GITHUB_OUTPUT | |
- name: "Create Branch - ${{ steps.variables.outputs.branch_name }}" | |
run: | | |
git checkout -b ${{ steps.variables.outputs.branch_name }} | |
git push -u origin ${{ steps.variables.outputs.branch_name }} | |
- name: "[Notification] Temp branch created" | |
run: | | |
# Send notification | |
title="Temp branch generated" | |
message="The ${{ steps.variables.outputs.branch_name }} branch created" | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
- name: "[DEBUG] Print Outputs" | |
run: | | |
echo branch_name ${{ steps.variables.outputs.branch_name }} | |
generate-changelog-bump-version: | |
runs-on: ubuntu-latest | |
needs: [audit-changelog, audit-version-in-code, create-temp-branch] | |
steps: | |
- name: "Set Git User" | |
run: | | |
git config user.name "Github Build Bot" | |
git config user.email "[email protected]" | |
- name: "Checkout ${{ github.repository }} Branch ${{ needs.create-temp-branch.outputs.branch_name }}" | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ needs.create-temp-branch.outputs.branch_name }} | |
- name: "Add Homebrew To PATH" | |
run: | | |
echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >> $GITHUB_PATH | |
- name: "Install Homebrew Packages" | |
run: | | |
brew install pre-commit | |
brew tap miniscruff/changie https://github.com/miniscruff/changie | |
brew install changie | |
- name: "Set json File Name" | |
id: json_file | |
run: | | |
echo "name=output_$GITHUB_RUN_ID.json" >> $GITHUB_OUTPUT | |
- name: "Get Core Team Membership" | |
run: | | |
gh api -H "Accept: application/vnd.github+json" orgs/dbt-labs/teams/core-group/members > ${{ steps.json_file.outputs.name }} | |
env: | |
GH_TOKEN: ${{ secrets.IT_TEAM_MEMBERSHIP }} | |
- name: "Set Core Team Membership for Changie Contributors exclusion" | |
id: set_team_membership | |
run: | | |
team_list=$(jq -r '.[].login' ${{ steps.json_file.outputs.name }}) | |
echo $team_list | |
team_list_single=$(echo $team_list | tr '\n' ' ') | |
echo "CHANGIE_CORE_TEAM=$team_list_single" >> $GITHUB_ENV | |
- name: "Delete the json File" | |
run: | | |
rm ${{ steps.json_file.outputs.name }} | |
- name: "Generate Release Changelog" | |
if: needs.audit-changelog.outputs.exists == 'false' | |
run: | | |
if [[ -d ".changes/${{ needs.audit-changelog.outputs.base_version }}" ]] | |
then | |
changie batch ${{ needs.audit-changelog.outputs.base_version }} --include '${{ needs.audit-changelog.outputs.base_version }}' --remove-prereleases | |
else # releasing a final patch with no prereleases | |
changie batch ${{ needs.audit-changelog.outputs.base_version }} | |
fi | |
changie merge | |
git status | |
- name: "Check Changelog Created Successfully" | |
if: needs.audit-changelog.outputs.exists == 'false' | |
run: | | |
title="Changelog" | |
if [[ -f ${{ needs.audit-changelog.outputs.changelog_path }} ]] | |
then | |
message="Changelog file created successfully" | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
else | |
message="Changelog failed to generate" | |
echo "::error title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
exit 1 | |
fi | |
- name: "Set up Python & Hatch - ${{ env.PYTHON_TARGET_VERSION }}" | |
uses: ./.github/actions/setup-python-hatch | |
with: | |
python-version: "${{ env.PYTHON_TARGET_VERSION }}" | |
- name: "Bump Version To ${{ inputs.version_number }}" | |
if: needs.audit-version-in-code.outputs.up_to_date == 'false' | |
run: | | |
hatch version "${{ inputs.version_number }}" | |
git status | |
- name: "[Notification] Bump Version To ${{ inputs.version_number }}" | |
if: needs.audit-version-in-code.outputs.up_to_date == 'false' | |
run: | | |
title="Version bump" | |
message="Version successfully bumped in codebase to ${{ inputs.version_number }}" | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" | |
# this step will fail on whitespace errors but also correct them, so add a `| true` to avoid failure | |
- name: "Remove Trailing Whitespace Via Pre-commit" | |
run: | | |
pre-commit run trailing-whitespace --files .bumpversion.cfg CHANGELOG.md .changes/* | true | |
git status | |
# this step will fail on newline errors but also correct them, so add a `| true` to avoid failure | |
- name: "Removing Extra Newlines Via Pre-commit" | |
run: | | |
pre-commit run end-of-file-fixer --files .bumpversion.cfg CHANGELOG.md .changes/* | true | |
git status | |
- name: "Commit & Push Changes" | |
run: | | |
commit_message="Bumping version to ${{ inputs.version_number }} and generate changelog" | |
#Commit changes to branch | |
git pull | |
git add . | |
git commit -m "$commit_message" | |
git push | |
run-unit-tests: | |
runs-on: ubuntu-latest | |
needs: [create-temp-branch, generate-changelog-bump-version] | |
env: | |
TOXENV: unit | |
steps: | |
- name: "Checkout ${{ github.repository }} Branch ${{ needs.create-temp-branch.outputs.branch_name }}" | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ needs.create-temp-branch.outputs.branch_name }} | |
- name: "Set up Python & Hatch - ${{ env.PYTHON_TARGET_VERSION }}" | |
uses: ./.github/actions/setup-python-hatch | |
with: | |
python-version: "${{ env.PYTHON_TARGET_VERSION }}" | |
- name: "Run Tests" | |
run: | | |
hatch run test:unit | |
merge-changes: | |
name: "Merge Changes Into ${{ github.ref }}" | |
runs-on: ubuntu-latest | |
needs: [run-unit-tests, create-temp-branch, audit-version-in-code, audit-changelog] | |
if: | | |
!failure() && !cancelled() && | |
inputs.test_run == false && | |
( | |
needs.audit-changelog.outputs.exists == 'false' || | |
needs.audit-version-in-code.outputs.up_to_date == 'false' | |
) | |
steps: | |
- name: "[Debug] Print Variables" | |
run: | | |
echo branch_name: ${{ needs.create-temp-branch.outputs.branch_name }} | |
echo inputs.test_run: ${{ inputs.test_run }} | |
echo needs.audit-changelog.outputs.exists: ${{ needs.audit-changelog.outputs.exists }} | |
echo needs.audit-version-in-code.outputs.up_to_date: ${{ needs.audit-version-in-code.outputs.up_to_date }} | |
- name: "Set Git User" | |
run: | | |
git config user.name "Github Build Bot" | |
git config user.email "[email protected]" | |
- name: "Checkout Repo ${{ github.repository }}" | |
uses: actions/checkout@v4 | |
with: | |
ref: ${{ github.ref }} | |
token: ${{ secrets.FISHTOWN_BOT_PAT }} | |
- name: "Merge in changes" | |
run: | | |
git fetch origin ${{ needs.create-temp-branch.outputs.branch_name }} | |
if ! git merge origin/${{ needs.create-temp-branch.outputs.branch_name }} --no-ff -m "Merge version bump and changelogs"; then | |
echo "::error::Merge failed" | |
exit 1 | |
fi | |
git push origin HEAD || { | |
echo "::error::Push failed" | |
exit 1 | |
} | |
- name: "Delete Temp Branch" | |
env: | |
GH_TOKEN: ${{ secrets.FISHTOWN_BOT_PAT }} | |
run: | | |
gh api -X DELETE repos/${{ github.repository }}/git/refs/heads/${{ needs.create-temp-branch.outputs.branch_name }} | |
- name: "[Notification] Changes Merged" | |
run: | | |
title="Changelog and Version Bump Branch Merge" | |
message="The ${{ needs.create-temp-branch.outputs.branch_name }} branch was merged into ${{ github.ref }}" | |
echo "::notice title=${{ env.NOTIFICATION_PREFIX }}: $title::$message" |