From 0517a3132646e0518e9731d83618843c482cc1fd Mon Sep 17 00:00:00 2001 From: Kyle Vorster Date: Wed, 17 Jul 2024 18:54:35 +0200 Subject: [PATCH] feat: Enhancement to the release workflow Signed-off-by: Kyle Vorster --- .github/workflows/release.yml | 116 ++++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b22fcd8..b5a2310 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + name: Release Workflow on: @@ -6,16 +8,18 @@ on: properties: milestone_number: type: string + jobs: release: runs-on: ubuntu-latest steps: + # Checkout the main branch with all history - name: Checkout Repository uses: actions/checkout@v2 with: ref: main fetch-depth: 0 # Fetch all tags - + # Fetch merged pull request and determine release labels - uses: actions-ecosystem/action-get-merged-pull-request@v1 id: get-merged-pull-request @@ -27,28 +31,29 @@ jobs: if: ${{ steps.get-merged-pull-request.outputs.title != null }} with: github_token: ${{ secrets.GITHUB_TOKEN }} - #labels: ${{ steps.get-merged-pull-request.outputs.labels }} - # Get the latest tag in the repositorys + # Get the latest tag in the repository - uses: actions-ecosystem/action-get-latest-tag@v1 id: get-latest-tag if: ${{ steps.release-label.outputs.level != null }} with: semver_only: true + # Setup Node.js environment - name: Setup Node.js (.npmrc) uses: actions/setup-node@v3 with: - node-version: 16.x + node-version: 20.x registry-url: https://npm.pkg.github.com/ - # Defaults to the user or organization that owns the workflow file scope: '@frmscoe' + # Install dependencies - name: Install dependencies run: npm ci env: GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}' + # Run Tests - name: Run Tests run: npm test env: @@ -58,10 +63,10 @@ jobs: - name: Determine Release Type id: determine_release run: | - export PREV_VERSION=$(git describe --abbrev=0 --tags) + PREV_VERSION=$(git describe --abbrev=0 --tags) echo "Previous Version: $PREV_VERSION" - export COMMIT_MESSAGES=$(git log $PREV_VERSION^..HEAD --format=%B) + COMMIT_MESSAGES=$(git log $PREV_VERSION^..HEAD --format=%B) echo "Commit Messages: $COMMIT_MESSAGES" # Determine release type based on commit messages and labels @@ -69,14 +74,16 @@ jobs: if echo "$COMMIT_MESSAGES" | grep -q -e "BREAKING CHANGE:"; then RELEASE_TYPE="major" + elif echo "$COMMIT_MESSAGES" | grep -q -e "feat!:"; then + RELEASE_TYPE="major" elif echo "$COMMIT_MESSAGES" | grep -q -e "feat:"; then RELEASE_TYPE="minor" elif echo "$COMMIT_MESSAGES" | grep -q -e "feat:" && (echo "$COMMIT_MESSAGES" | grep -q -e "fix:" || echo "$COMMIT_MESSAGES" | grep -q -e "enhancement:" || echo "$COMMIT_MESSAGES" | grep -q -e "docs:" || echo "$COMMIT_MESSAGES" | grep -q -e "refactor:" || echo "$COMMIT_MESSAGES" | grep -q -e "chore:"); then RELEASE_TYPE="minor" - elif echo "$COMMIT_MESSAGES" | grep -q -e "fix:" -e "enhancement:" -e "docs:" -e "refactor:" -e "chore:"; then + elif echo "$COMMIT_MESSAGES" | grep -q -e "fix:" -e "enhancement:" -e "docs:" -e "refactor:" -e "chore:" -e "build:" -e "ci:" -e "perf:" -e "style:" -e "test:" -e "chore(deps):" -e "chore(deps-dev):"; then RELEASE_TYPE="patch" fi - + echo "Release Type: $RELEASE_TYPE" echo "::set-output name=release_type::$RELEASE_TYPE" @@ -84,32 +91,32 @@ jobs: - name: Bump Version id: bump_version run: | - export PREV_VERSION=$(git describe --abbrev=0 --tags) + PREV_VERSION=$(git describe --abbrev=0 --tags) echo "Previous Version: $PREV_VERSION" - export RELEASE_TYPE=${{ steps.determine_release.outputs.release_type }} + RELEASE_TYPE=${{ steps.determine_release.outputs.release_type }} echo "Release Type: $RELEASE_TYPE" - export VERSION_PARTS=($(echo $PREV_VERSION | tr '.' '\n')) - MAJOR=${VERSION_PARTS[0]} - MINOR=${VERSION_PARTS[1]} - PATCH=${VERSION_PARTS[2]} + # Strip the 'v' from the version if it exists + PREV_VERSION=${PREV_VERSION#v} + + IFS='.' read -r MAJOR MINOR PATCH <<< "$PREV_VERSION" if [[ $RELEASE_TYPE == "major" ]]; then MAJOR=$((MAJOR + 1)) MINOR=0 PATCH=0 elif [[ $RELEASE_TYPE == "minor" ]]; then - MINOR=$((MINOR + 1)) - PATCH=0 + MINOR=$((MINOR + 1)) + PATCH=0 else PATCH=$((PATCH + 1)) fi - NEW_VERSION="$MAJOR.$MINOR.$PATCH" + NEW_VERSION="v$MAJOR.$MINOR.$PATCH" echo "New Version: $NEW_VERSION" echo "::set-output name=new_version::$NEW_VERSION" - + # Get the milestone details - name: Get Milestone Details id: get_milestone @@ -137,9 +144,18 @@ jobs: LABEL_DOCS="docs:" LABEL_REFACTOR="refactor:" LABEL_CHORE="chore:" + LABEL_BUILD="build:" + LABEL_CI="ci:" + LABEL_PERFORMANCE="perf:" + LABEL_STYLE="style:" + LABEL_TEST="test:" LABEL_BREAKING_CHANGE="BREAKING CHANGE:" + LABEL_FEAT_BREAKING="feat!:" + LABEL_DEPS="chore(deps):" + LABEL_DEPS_DEV="chore(deps-dev):" # Get the last release tag LAST_RELEASE_TAG=$(git describe --abbrev=0 --tags) + echo "Last Release Tag: $LAST_RELEASE_TAG" # Get the milestone details from the output of the previous step MILESTONE_TITLE="${{ steps.get_milestone.outputs.milestone_title }}" MILESTONE_DESCRIPTION="${{ steps.get_milestone.outputs.milestone_description }}" @@ -155,12 +171,14 @@ jobs: local section_label="$2" local section_icon="$3" # Get the commit messages with the specified label between the last release and the current release - local commit_messages=$(git log --pretty=format:"- %s (Milestone: %b, Linked Issues: %C(yellow)%H%Creset)" "$LAST_RELEASE_TAG..HEAD" --grep="$section_label" --no-merges --decorate --decorate-refs=refs/issues) + local commit_messages=$(git log --pretty=format:"- %s (Linked Issues: %C(yellow)%H%Creset)" "$LAST_RELEASE_TAG..HEAD" --grep="$section_label" --no-merges --decorate --decorate-refs=refs/issues) # If there are commit messages, append the section to the changelog file if [ -n "$commit_messages" ]; then + # Remove duplicate commit messages + local unique_commit_messages=$(echo "$commit_messages" | awk '!seen[$0]++') echo "### $section_icon $section_title" >> "$CHANGELOG_FILE" echo "" >> "$CHANGELOG_FILE" - echo "$commit_messages" >> "$CHANGELOG_FILE" + echo "$unique_commit_messages" >> "$CHANGELOG_FILE" echo "" >> "$CHANGELOG_FILE" fi } @@ -171,7 +189,33 @@ jobs: append_section "Documentation" "$LABEL_DOCS" "๐Ÿ“š" append_section "Refactorings" "$LABEL_REFACTOR" "๐Ÿ”จ" append_section "Chores" "$LABEL_CHORE" "โš™๏ธ" + append_section "Build" "$LABEL_BUILD" "๐Ÿ—๏ธ" + append_section "CI" "$LABEL_CI" "โš™๏ธ" + append_section "Performance" "$LABEL_PERFORMANCE" "๐Ÿš€" + append_section "Style" "$LABEL_STYLE" "๐Ÿ’…" + append_section "Tests" "$LABEL_TEST" "๐Ÿงช" append_section "Breaking Changes" "$LABEL_BREAKING_CHANGE" "๐Ÿ’ฅ" + append_section "Feature Breaking Changes" "$LABEL_FEAT_BREAKING" "๐Ÿ’ฅ" + append_section "Dependencies" "$LABEL_DEPS" "๐Ÿ“ฆ" + append_section "Dev Dependencies" "$LABEL_DEPS_DEV" "๐Ÿ”ง" + + # Function to append non-labeled commits to the changelog file + append_non_labeled_commits() { + # Get the commit messages that do not match any conventional commit labels between the last release and the current release + local non_labeled_commit_messages=$(git log --pretty=format:"- %s (Linked Issues: %C(yellow)%H%Creset)" "$LAST_RELEASE_TAG..HEAD" --invert-grep --grep="^fix:\|^feat:\|^enhancement:\|^docs:\|^refactor:\|^chore:\|^build:\|^ci:\|^perf:\|^style:\|^test:\|^BREAKING CHANGE:\|^feat!:\|^chore(deps):\|^chore(deps-dev):") + # If there are non-labeled commit messages, append the section to the changelog file + if [ -n "$non_labeled_commit_messages" ]; then + # Remove duplicate commit messages + local unique_commit_messages=$(echo "$non_labeled_commit_messages" | awk '!seen[$0]++') + echo "### ๐Ÿ“ Other Changes" >> "$CHANGELOG_FILE" + echo "" >> "$CHANGELOG_FILE" + echo "$unique_commit_messages" >> "$CHANGELOG_FILE" + echo "" >> "$CHANGELOG_FILE" + fi + } + # Append non-labeled commits to the changelog file + append_non_labeled_commits + echo "::set-output name=changelog_file::$CHANGELOG_FILE" # Read changelog contents into a variable @@ -203,3 +247,33 @@ jobs: body_path: /home/runner/work/changelog.txt draft: false prerelease: false + + # Update the CHANGELOG.md file in the repository + - name: Update CHANGELOG.md + run: | + NEW_VERSION=${{ steps.bump_version.outputs.new_version }} + CHANGELOG_CONTENTS=$(cat /home/runner/work/changelog.txt) + # Prepend the new changelog content to the existing CHANGELOG.md below SPDX-License-Identifier section + echo -e "$(head -n 2 CHANGELOG.md)\n\n## $NEW_VERSION\n\n$CHANGELOG_CONTENTS\n\n$(tail -n +3 CHANGELOG.md)" > CHANGELOG.md + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git add CHANGELOG.md + git commit -m "chore: Update CHANGELOG.md for $NEW_VERSION" + git push origin HEAD:main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + STARTUP_TYPE: 'nats' + + # Update the VERSION file + - name: Update VERSION file + run: | + NEW_VERSION=${{ steps.bump_version.outputs.new_version }} + echo -e "# SPDX-License-Identifier: Apache-2.0\n\n$NEW_VERSION" > VERSION + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git add VERSION + git commit -m "chore: Update VERSION to $NEW_VERSION" + git push origin HEAD:main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + STARTUP_TYPE: 'nats' \ No newline at end of file