Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 212 additions & 0 deletions .github/workflows/releases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
name: Generate GH Release with Proper Release Notes for OpenTofu Modules

on:
workflow_dispatch:
inputs:
module_name:
description: Name of the module to perform a release for
type: environment
required: true
release_type:
description: Type of release that to be performed
type: choice
options:
- patch
- minor
- major
default: patch
is_dev_release:
description: Perform a development release than a full release?
type: boolean
default: false

jobs:
prepare_release_details:
name: Preparing release details such as next release version and changelogs
runs-on: ubuntu-latest
environment: ${{ inputs.module_name }}
env:
MODULE: ${{ inputs.module_name }}
RELEASE_TYPE: ${{ inputs.release_type }}
IS_DEV_RELEASE: ${{ inputs.is_dev_release }}
CURRENT_FULL_VERSION: ${{ vars.FULL_VERSION || '0.0.0' }}
outputs:
version: ${{ steps.version.outputs.NEXT_RELEASE_VERSION }}
changelog: ${{ steps.changelog.outputs.NOTES }}
permissions:
contents: read
steps:
- name: Checking out the repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0

- name: Checking if there's anything committed to create a new release
run: |

CURRENT_TAG=$(git tag -l "$MODULE/v*" --sort=-v:refname | head -n 1)
CURRENT_TAG=${CURRENT_TAG:-$(git rev-list --max-parents=0 HEAD)}
# Count commits in the module path excluding [INF]
CHANGE_COUNT=$(git log $CURRENT_TAG..HEAD --oneline -- "modules/$MODULE" | grep -v "\[INF\]" | wc -l)

if [ "$CHANGE_COUNT" -eq "0" ]; then
echo "::error title=No Changes Detected::No non-[INF] commits found in modules/$MODULE since $CURRENT_FULL_VERSION."
exit 1
fi
echo "Found $CHANGE_COUNT relevant changes."

- id: version
name: Calculating the next release version from the previous if it exists
run: |

# Fetch the raw version without any development tags if it exists
BASE_VERSION=$(echo "$CURRENT_FULL_VERSION" | cut -d- -f1)

# If the previous release was a development version, extract the release number
DEV_VERSION=$(echo "$CURRENT_FULL_VERSION" | grep -oP 'dev\.\K\d+' || echo "0")

# Calculating the next release version
# Case 1: if the current release was a dev version and the next one is not, the next
# release version will be the base version without any dev tags added onto it
if [[ "$CURRENT_FULL_VERSION" == *"dev."* && "$IS_DEV_RELEASE" == "false" ]]; then
NEXT_RELEASE_VERSION="$BASE_VERSION"

# Case 2: if the current release was a dev version and the next one is also a dev
# release, the next release version will be the same with the dev version incremented
elif [[ "$CURRENT_FULL_VERSION" == *"dev."* && "$IS_DEV_RELEASE" == "true" ]]; then
DEV_VERSION=$(( DEV_VERSION + 1 ))
NEXT_RELEASE_VERSION="$BASE_VERSION-dev.$DEV_VERSION"

# Case 3: if the current release is not a dev version and the next too is not
# According to the provided inputs, increment major/minor/patch version and
# make that as the next release version to be performed
else
# Split the basen version up using period
# and extract the individual versions
IFS='.' read -ra VERSIONS <<< "$BASE_VERSION"
MAJOR_VERSION=${VERSIONS[0]}
MINOR_VERSION=${VERSIONS[1]}
PATCH_VERSION=${VERSIONS[2]}

# Increment the version according to the inputs and create the final version
if [[ "$RELEASE_TYPE" == "major" ]]; then MAJOR_VERSION=$(( MAJOR_VERSION + 1 )); MINOR_VERSION=0; PATCH_VERSION=0;
elif [[ "$RELEASE_TYPE" == "minor" ]]; then MINOR_VERSION=$(( MINOR_VERSION + 1 )); PATCH_VERSION=0;
else PATCH_VERSION=$(( PATCH_VERSION + 1 )); fi

NEXT_RELEASE_VERSION="$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION"

# If its a development release, attach the tag accordingly
if [[ "$IS_DEV_RELEASE" == "true" ]]; then
NEXT_RELEASE_VERSION="$NEXT_RELEASE_VERSION-dev.1"
fi
fi

# Outputting the version as a GH Output
echo "NEXT_RELEASE_VERSION=$NEXT_RELEASE_VERSION" >> $GITHUB_OUTPUT

- id: changelog
name: Generating Change log from the previous versions if exists for the new release
run: |

# We will output the change log
# as one big blob of text
echo "NOTES<<EOF" >> $GITHUB_OUTPUT

# Fetching the current release tag if it exists
# If it does not, we are starting from scratch
CURRENT_TAG=$(git tag -l "$MODULE/v*" --sort=-v:refname | head -n 1)
CURRENT_TAG=${CURRENT_TAG:-$(git rev-list --max-parents=0 HEAD)}

# Fetch all commits since the previous release for this specific module
COMMITS=$(git log $CURRENT_TAG..HEAD --format="%H" -- "modules/$MODULE")

# Looping across all commits to pull out
# Change log for the next release
for SHASUM in $COMMITS; do
# Fetch the body of the commit
# Since all commits on the main
# branch is PRs getting squashed
# and merged, the body will contain
# the changes made
BODY=$(git log -1 --format="%b" $SHASUM)

# If the body is garbage, DO NOT INCLUDE
# IN THE CHANGELOG
if [[ ! "$BODY" == *"# Implemented Changes"* ]]; then
continue
fi

# Fetch the commit message
SUBJECT=$(git log -1 --format="%s" $SHASUM)

# If the commit message is for an infrastructure
# folder update, ignore it safely
if [[ $SUBJECT == "[INF]"* ]]; then
continue
fi

# Fetch the PR number from the commit message
PR_REF=$(echo "$SUBJECT" | grep -o '(#[0-9]\+)' | sed 's/[()]//g' || echo "N/A")

# Fetch the issue number from the body of the commit
CLOSE_REF=$(echo "$BODY" | grep -i "Closes:" | sed 's/.*Closes://I' | sed 's/[*]//g' | xargs || echo "N/A")
CLOSE_REF=${CLOSE_REF:-"N/A"}

# Fetch all the changes made in the body and ignore everything apart from the changes points
CHANGES=$(echo "$BODY" | awk '/# Implemented Changes/{flag=1; next} /\*\*Closes:/{flag=0} flag' | sed '/^[[:space:]]*$/d')

# Take the changes points and output it as the changelogs
if [ ! -z "$CHANGES" ]; then
echo "#### From PR: $PR_REF (Issues closed: $CLOSE_REF)" >> $GITHUB_OUTPUT
echo "$CHANGES" >> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
fi

done
echo "EOF" >> $GITHUB_OUTPUT

- name: Printing out the release information as a step summary for validation
run: |
echo "### Release Preview: ${{ inputs.module_name }}" >> $GITHUB_STEP_SUMMARY
echo "**New Version:** \`${{ steps.version.outputs.NEXT_RELEASE_VERSION }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Release Type:** ${{ inputs.is_dev_release && 'In Development (Dev)' || 'Stable' }}" >> $GITHUB_STEP_SUMMARY
echo "#### Proposed Changelogs:" >> $GITHUB_STEP_SUMMARY
if [ -z "${{ steps.changelog.outputs.NOTES }}" ]; then
echo "*No descriptive changes found (commits may lack the 'Implemented Changes' section).*" >> $GITHUB_STEP_SUMMARY
else
echo "${{ steps.changelog.outputs.NOTES }}" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "> **Note:** Please review the details above. If correct, approve the next job to finalize the release." >> $GITHUB_STEP_SUMMARY

perform_release:
name: Create the release for the ${{ inputs.module_name }} module
runs-on: ubuntu-latest
environment: "manual-approval"
needs: prepare_release_details
env:
version: ${{ needs.prepare_release_details.outputs.version }}
changelog: ${{ needs.prepare_release_details.outputs.changelog }}
permissions:
contents: write
steps:
- name: Checking out the repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
fetch-depth: 0

- name: Finalize the release version in GitHub Environment for ${{ inputs.module_name }}
env:
GITHUB_TOKEN: ${{ secrets.RELEASES_TOKEN }}
run: gh variable set MODULE_VERSION --body "${{ env.version }}" --env "${{ inputs.module_name }}"

- name: Create GitHub Release for the ${{ inputs.module_name }}
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe
with:
tag_name: ${{ inputs.module_name }}/v${{ env.version }}
name: ${{ inputs.module_name }} v${{ env.version }}
body: |
## Changes in ${{ github.event.inputs.module_name }}
${{ env.changelog }}
prerelease: ${{ inputs.is_dev_release }}
make_latest: ${{ inputs.is_dev_release == 'false' }}
3 changes: 3 additions & 0 deletions .github/workflows/tofu-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: Infrastructure Deployment on Self Hosted Kubernetes Cluster
on:
workflow_dispatch:
push:
paths:
- infrastructure/**
- modules/**
branches:
- task/**
- bug/**
Expand Down
Loading