From a639c5835bb0fd265163b6088aa8f12423f7e7ab Mon Sep 17 00:00:00 2001 From: Dimitrios Pantazis Date: Fri, 18 Oct 2024 17:34:27 +0300 Subject: [PATCH] Process changelog workflow --- .github/actions/process-changelog/action.yml | 96 ++++++++++++++ .github/workflows/process-changelog.yml | 128 +++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 .github/actions/process-changelog/action.yml create mode 100644 .github/workflows/process-changelog.yml diff --git a/.github/actions/process-changelog/action.yml b/.github/actions/process-changelog/action.yml new file mode 100644 index 0000000000..bdd9a3c771 --- /dev/null +++ b/.github/actions/process-changelog/action.yml @@ -0,0 +1,96 @@ +name: "Process the changelog" +description: "Generate or amend the changelog entries" + +inputs: + release-version: + description: "The release version for which the action should generate the changelog (e.g. 4.5.0)" + required: true + release-date: + description: "The release date (format: YYYY-MM-DD) for which the action should generate the changelog (default: unreleased)" + required: false + default: "unreleased" + action-type: + description: 'Whether this is to generate or amend the changelog entries (generate or amend)' + required: false + default: "generate" + +outputs: + changelog: + description: "The escaped changelog content" + value: ${{ steps.process_changelog.outputs.CHANGELOG }} + +runs: + using: composite + steps: + - name: "Verify the action type" + id: verify_action_type + if: ${{ inputs.action-type == 'generate' }} + shell: bash + env: + RELEASE_VERSION: ${{ inputs.release-version }} + RELEASE_DATE: ${{ inputs.release-date }} + ACTION_TYPE: ${{ inputs.action-type }} + run: | + FINAL_RELEASE_VERSION=$(echo "$RELEASE_VERSION" | grep -Po '\d.\d.\d(.*?)') # Keep only x.y.z from x.y.z(-test-n) + CURRENT_RELEASE_VERSION=$(jq '.version' package.json -r) + + # If the changelog directory is empty (except .gitkeep) and the final release version is already defined in package.json, we need to switch to amend + # This use case is mainly for the last test package created from the release branch, to avoid an empty changelog + if [ "$(ls -A changelog | wc -l)" -eq 1 ] && [[ "$FINAL_RELEASE_VERSION" == "$CURRENT_RELEASE_VERSION" ]]; then + echo "ACTION_TYPE=amend-version" >> $GITHUB_OUTPUT + echo "CURRENT_VERSION=$CURRENT_RELEASE_VERSION" >> $GITHUB_OUTPUT + fi + + - name: "Process changelog for changelog.txt" + id: process_changelog + shell: bash + env: + ACTION_TYPE: ${{ steps.verify_action_type.outputs.ACTION_TYPE || inputs.action-type }} + CURRENT_VERSION: ${{ steps.verify_action_type.outputs.CURRENT_VERSION }} + RELEASE_VERSION: ${{ inputs.release-version }} + RELEASE_DATE: ${{ inputs.release-date }} + run: | + if ${{ env.ACTION_TYPE == 'amend-version' }}; then + sed -i "s/^= $CURRENT_VERSION - .* =$/= $RELEASE_VERSION - $RELEASE_DATE =/" changelog.txt + else + # Install this dev package globally to gather changelog entries while not including it into the release package + composer global require automattic/jetpack-changelogger:^3.0.7 + + if ${{ env.ACTION_TYPE == 'generate' }}; then + CHANGELOG_FLAG="" + echo "Generating the changelog entries." >> $GITHUB_STEP_SUMMARY + else + CHANGELOG_FLAG="--amend" + echo "Amending the changelog entries." >> $GITHUB_STEP_SUMMARY + fi + + ~/.composer/vendor/bin/changelogger write --use-version="$RELEASE_VERSION" --release-date="$RELEASE_DATE" $CHANGELOG_FLAG --no-interaction --yes + fi + + CHANGELOG=$(awk '/^= / { if (p) { exit }; p=1; next } p && NF' changelog.txt) + + # Escape backslash, new line and ampersand characters. The order is important. + CHANGELOG=${CHANGELOG//\\/\\\\} + CHANGELOG=${CHANGELOG//$'\n'/\\n} + CHANGELOG=${CHANGELOG//&/\\&} + + echo "CHANGELOG=$CHANGELOG" >> $GITHUB_OUTPUT + + - name: "Process changelog for readme.txt" + shell: bash + env: + ACTION_TYPE: ${{ steps.verify_action_type.outputs.ACTION_TYPE || inputs.action-type }} + CURRENT_VERSION: ${{ steps.verify_action_type.outputs.CURRENT_VERSION }} + RELEASE_VERSION: ${{ inputs.release-version }} + RELEASE_DATE: ${{ inputs.release-date }} + CHANGELOG: ${{ steps.process_changelog.outputs.CHANGELOG }} + run: | + if ${{ env.ACTION_TYPE == 'amend-version' }}; then + sed -i "s/^= $CURRENT_VERSION - .* =$/= $RELEASE_VERSION - $RELEASE_DATE =/" readme.txt + else + if ${{ env.ACTION_TYPE == 'amend' }}; then + perl -i -p0e "s/= $RELEASE_VERSION.*?(\n){2}//s" readme.txt # Delete the existing changelog for the release version first + fi + + sed -ri "s|(== Changelog ==)|\1\n\n= $RELEASE_VERSION - $RELEASE_DATE =\n$CHANGELOG|" readme.txt + fi diff --git a/.github/workflows/process-changelog.yml b/.github/workflows/process-changelog.yml new file mode 100644 index 0000000000..3ef9296cb8 --- /dev/null +++ b/.github/workflows/process-changelog.yml @@ -0,0 +1,128 @@ +name: "Release - Changelog" + +# This action will run when it is triggered manually +on: + workflow_dispatch: + inputs: + release-version: + description: "The release version for which the action should process the changelog (e.g. 4.5.0) (default: will try to figure it out)" + default: 'figure-it-out' + required: true + type: string + release-date: + description: "The release date in human-readable format (default: 'today')." + required: false + default: "today" + type: string + action-type: + description: "Whether this is to amend or generate the changelog entries (default: 'generate')." + required: true + default: "generate" + type: choice + options: + - amend + - generate + +defaults: + run: + shell: bash + +jobs: + process-changelog: + name: "Process the changelog" + runs-on: ubuntu-latest + env: + CHANGELOG_ACTION: ${{ inputs.action-type }} + RELEASE_VERSION: ${{ inputs.release-version }} + RELEASE_DATE: ${{ inputs.release-date }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + + - name: Set Variables + id: vars + run: echo "sha_short=$(git rev-parse --short ${{ github.sha }})" >> $GITHUB_OUTPUT + + - name: Set up Git configuration + run: | + git config --global user.email "actions@github.com" + git config --global user.name "github-actions" + + - name: Check for .puprc file and paths.versions + id: check-puprc + run: | + if [ ! -f ".puprc" ]; then + echo "Error: .puprc file not found" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + if ! jq -e '.paths.versions' .puprc > /dev/null; then + echo "Error: paths.versions not found in .puprc" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + - name: Figure out Version + id: figure-out-version + run: | + if [ "$RELEASE_VERSION" == "figure-it-out" ]; then + jq -c '.paths.versions[]' .puprc | while read -r version; do + echo "Processing version info: $version" + file=$(echo "$version" | jq -r '.file') + regex=$(echo "$version" | jq -r '.regex') + + existing_version=$(grep -Po "$regex" "$file" | grep -Po '(\d+\.\d+\.\d+(\.\d+)?)') + echo "Current version: $existing_version" + + if [ -n "$existing_version" ]; then + break + fi + done + echo "RELEASE_VERSION=$existing_version" >> $GITHUB_OUTPUT + else + echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_OUTPUT + fi + + - name: "Format the release date" + id: format_date + run: | + RELEASE_DATE=$( date "+%Y-%m-%d" -d "$RELEASE_DATE" ) # Release date formatted as YYYY-MM-DD + echo "RELEASE_DATE=$RELEASE_DATE" >> $GITHUB_OUTPUT + + - name: Create new branch + id: versions + run: | + changeBranch="task/process-changelog/${{ steps.format_date.outputs.RELEASE_DATE }}/${{ steps.figure-out-version.outputs.RELEASE_VERSION }}/${{ steps.vars.outputs.sha_short }}" + git checkout -b "$changeBranch" + git push origin "$changeBranch" + + - name: "Process changelog" + id: process_changelog + uses: ./.github/actions/process-changelog + with: + release-version: ${{ steps.figure-out-version.outputs.RELEASE_VERSION }} + release-date: ${{ steps.format_date.outputs.RELEASE_DATE }} + action-type: ${{ env.CHANGELOG_ACTION }} + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + id: cpr + with: + token: ${{ secrets.GITHUB_TOKEN }} + base: ${{ github.ref }} + branch: "task/process-changelog/${{ steps.format_date.outputs.RELEASE_DATE }}/${{ steps.figure-out-version.outputs.RELEASE_VERSION }}/${{ steps.vars.outputs.sha_short }}" + title: "Process changelog for ${{ github.ref }}" + body: | + This is an automated PR created by ${{ github.actor }}. + It was generated by [this GitHub Action](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}). + labels: "automation" + commit-message: | + Process changelog for ${{ github.ref }} + This is an automated PR created by ${{ github.actor }}. + Generated by: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + - name: Check outputs + if: ${{ steps.cpr.outputs.pull-request-number }} + run: | + echo "## Pull Request" >> $GITHUB_STEP_SUMMARY + echo "* Number - ${{ steps.cpr.outputs.pull-request-number }}" >> $GITHUB_STEP_SUMMARY + echo "* URL - [${{ steps.cpr.outputs.pull-request-url }}](${{ steps.cpr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY