From 60b00fc7396929dffb66c2960ffa6b2fcd2103af Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Mon, 18 Nov 2024 11:58:48 -0500 Subject: [PATCH] Update Release Drafter for Dev Branches Changes the way release drafter handles drafting releases on repos with release branches (which have dev branches now). Ultimately, a release is drafted for the dev branch and the release branch. The releases are differentiated by both their release title and tag. - Release Branch - Title: `release-v` - Tag: `v` - Dev Branch - Title: `dev-v` - Tag: `dev-v` Note that the tag for the release branch follows the same convention as existing release tags. The "release branch" release includes all pull requests made to the dev branch with the `type:backport` label since the last "dev branch" release. For this reason, the "dev branch" and "release branch" should be released at the same time. Then, this effectively results in the "release branch" having all relevant changes since the last release. The "dev branch" release will be based at the same point in history as the "release branch" release but include all changes not just those with the `type:backport` label. The "release branch" release for the current release branch should be marked as "latest". For example, if "release/202311" and "release/202405" exist, the "release/202405" "release branch" release would be marked as latest. The `release-drafter/release-drafter` action is still used. Signed-off-by: Michael Kubacki --- .github/workflows/ReleaseDrafter.yml | 126 ++++++++++++++++-- .sync/Files.yml | 17 ++- .../release-draft/release-draft-config.yml | 18 ++- .sync/workflows/leaf/release-draft.yml | 11 +- 4 files changed, 157 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ReleaseDrafter.yml b/.github/workflows/ReleaseDrafter.yml index 46764fc6..d9edd637 100644 --- a/.github/workflows/ReleaseDrafter.yml +++ b/.github/workflows/ReleaseDrafter.yml @@ -11,10 +11,10 @@ # # 1. A "latest release branch" # - Example: `release/202405` -# - Config file: `release-draft-config-n.yml` +# - Config file: `release-draft-config-n.yml` and `release-draft-config-n-dev.yml` # 2. A "previous release branch" # - Example: `release/202311` -# - Config file: `release-draft-config-n-1.yml` +# - Config file: `release-draft-config-n-1.yml` and `release-draft-config-n-1-dev.yml` # 3. A "main branch" # - Example: `main` # - Config file: `release-draft-config.yml` @@ -68,13 +68,19 @@ jobs: run: | fileContent=$(cat "${FILE_PATH}") latestMuReleaseBranch=$(echo "$fileContent" | grep -oP '(?<=latest_mu_release_branch = ").*(?=")') + latestMuDevBranch=$(echo "$latestMuReleaseBranch" | sed 's/release/dev/') previousMuReleaseBranch=$(echo "$fileContent" | grep -oP '(?<=previous_mu_release_branch = ").*(?=")') - echo "latest_mu_branch=${latestMuReleaseBranch}" >> $GITHUB_ENV - echo "latest_mu_branch_full=refs/heads/${latestMuReleaseBranch}" >> $GITHUB_ENV - echo "previous_mu_branch=${previousMuReleaseBranch}" >> $GITHUB_ENV - echo "previous_mu_branch_full=refs/heads/${previousMuReleaseBranch}" >> $GITHUB_ENV - - name: Build a ${{ env.latest_mu_branch }} Draft - if: ${{ startsWith(github.ref, env.latest_mu_branch_full) }} + previousMuDevBranch=$(echo "$previousMuReleaseBranch" | sed 's/release/dev/') + echo "latest_mu_release_branch=${latestMuReleaseBranch}" >> $GITHUB_ENV + echo "latest_mu_dev_branch=${latestMuDevBranch}" >> $GITHUB_ENV + echo "latest_mu_dev_branch_full=refs/heads/${latestMuDevBranch}" >> $GITHUB_ENV + echo "latest_mu_release_branch_full=refs/heads/${latestMuReleaseBranch}" >> $GITHUB_ENV + echo "previous_mu_release_branch=${previousMuReleaseBranch}" >> $GITHUB_ENV + echo "previous_mu_dev_branch=${previousMuDevBranch}" >> $GITHUB_ENV + echo "previous_mu_dev_branch_full=refs/heads/${previousMuDevBranch}" >> $GITHUB_ENV + echo "previous_mu_release_branch_full=refs/heads/${previousMuReleaseBranch}" >> $GITHUB_ENV + - name: Build a ${{ env.latest_mu_release_branch }} Draft + if: ${{ startsWith(github.ref, env.latest_mu_dev_branch_full) }} id: update_draft_n uses: release-drafter/release-drafter@v6.0.0 with: @@ -82,8 +88,49 @@ jobs: config-name: release-draft-config-n.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Build a ${{ env.previous_mu_branch }} Draft - if: ${{ startsWith(github.ref, env.previous_mu_branch_full) }} + - name: Draft Release for Current (${{ env.latest_mu_release_branch }}) Release Branch + if: steps.update_draft_n.outcome == 'success' + run: | + # Prepare the release body + release_body_path="${{ runner.temp }}/release_body.txt" + release_body=$(cat <<'EOF' + ${{ steps.update_draft_n.outputs.body }} + EOF + ) + release_body="${release_body//\`/\\\`}" + echo "${release_body}" > $release_body_path + sed -i 's/\\`/`/g' $release_body_path + sed -i '/\**Full Changelog\**:/d' $release_body_path + + # Get the new tag and title + new_tag=$(echo "${{ steps.update_draft_n.outputs.tag_name }}" | sed 's/dev-//') + new_title=$(echo "${{ steps.update_draft_n.outputs.tag_name }}" | sed 's/dev/release/') + + # Determine the corresponding tag names + existing_tag_prefix="" + tag_regex="v([0-9]{6}).*\." + if [[ $new_tag =~ $tag_regex ]]; then + existing_tag_prefix="${BASH_REMATCH[1]}" + fi + + # Delete the template dev draft created + gh release delete "${{ steps.update_draft_n.outputs.tag_name }}" --repo ${{ github.repository }} --yes + + # Delete any existing draft releases for this release branch + for tag in $(gh release list --repo ${{ github.repository }} --json tagName,isPrerelease,isDraft --jq ".[] | select(.isDraft == true and .isPrerelease == false and (.tagName | startswith(\"v$existing_tag_prefix\"))) | .tagName"); do + gh release delete "$tag" --repo ${{ github.repository }} --yes + done + + gh release create "$new_tag" \ + --repo "${{ github.repository }}" \ + --target "${{ env.latest_mu_release_branch_full }}" \ + --title "$new_title" \ + --notes-file "$release_body_path" \ + --draft + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Build a ${{ env.previous_mu_release_branch }} Draft + if: ${{ startsWith(github.ref, env.previous_mu_dev_branch_full) }} id: update_draft_n_1 uses: release-drafter/release-drafter@v6.0.0 with: @@ -91,8 +138,65 @@ jobs: config-name: release-draft-config-n-1.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Draft Release for N-1 (${{ env.previous_mu_release_branch }}) Release Branch + if: steps.update_draft_n_1.outcome == 'success' + run: | + # Prepare the release body + release_body_path="${{ runner.temp }}/release_body.txt" + release_body=$(cat <<'EOF' + ${{ steps.update_draft_n_1.outputs.body }} + EOF + ) + release_body="${release_body//\`/\\\`}" + echo "${release_body}" > $release_body_path + sed -i 's/\\`/`/g' $release_body_path + sed -i '/\**Full Changelog\**:/d' $release_body_path + + # Get the new tag and title + new_tag=$(echo "${{ steps.update_draft_n_1.outputs.tag_name }}" | sed 's/dev-//') + new_title=$(echo "${{ steps.update_draft_n_1.outputs.tag_name }}" | sed 's/dev/release/') + + # Determine the corresponding tag names + existing_tag_prefix="" + tag_regex="v([0-9]{6}).*\." + if [[ $new_tag =~ $tag_regex ]]; then + existing_tag_prefix="${BASH_REMATCH[1]}" + fi + + # Delete the template dev draft created + gh release delete "${{ steps.update_draft_n_1.outputs.tag_name }}" --repo ${{ github.repository }} --yes + + # Delete any existing draft releases for this release branch + for tag in $(gh release list --repo ${{ github.repository }} --json tagName,isPrerelease,isDraft --jq ".[] | select(.isDraft == true and .isPrerelease == false and (.tagName | startswith(\"v$existing_tag_prefix\"))) | .tagName"); do + gh release delete "$tag" --repo ${{ github.repository }} --yes + done + + gh release create "$new_tag" \ + --repo "${{ github.repository }}" \ + --target "${{ env.previous_mu_release_branch_full }}" \ + --title "$new_title" \ + --notes-file "$release_body_path" \ + --draft + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create the ${{ env.latest_mu_dev_branch }} Draft + if: ${{ startsWith(github.ref, env.latest_mu_dev_branch_full) }} + uses: release-drafter/release-drafter@v6.0.0 + with: + # Note: Path is relative to .github/ + config-name: release-draft-config-n-dev.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create the ${{ env.previous_mu_dev_branch }} Draft + if: ${{ startsWith(github.ref, env.previous_mu_dev_branch_full) }} + uses: release-drafter/release-drafter@v6.0.0 + with: + # Note: Path is relative to .github/ + config-name: release-draft-config-n-1-dev.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build the New Release Draft - if: ${{ !startsWith(github.ref, 'refs/heads/release') }} + if: ${{ !startsWith(github.ref, 'refs/heads/release') && !startsWith(github.ref, 'refs/heads/dev') }} id: update_draft_non_release uses: release-drafter/release-drafter@v6.0.0 with: diff --git a/.sync/Files.yml b/.sync/Files.yml index 7a2696ec..e34b2097 100644 --- a/.sync/Files.yml +++ b/.sync/Files.yml @@ -614,15 +614,30 @@ group: - files: - source: .sync/workflows/leaf/release-draft.yml dest: .github/workflows/release-draft.yml - template: true + template: + depend_on_backport: true - source: .sync/workflows/config/release-draft/release-draft-config.yml dest: .github/release-draft-config-n.yml template: + filter_to_backport: true + latest: true + release_branch: true + - source: .sync/workflows/config/release-draft/release-draft-config.yml + dest: .github/release-draft-config-n-dev.yml + template: + filter_to_backport: false latest: true release_branch: true - source: .sync/workflows/config/release-draft/release-draft-config.yml dest: .github/release-draft-config-n-1.yml template: + filter_to_backport: true + latest: false + release_branch: true + - source: .sync/workflows/config/release-draft/release-draft-config.yml + dest: .github/release-draft-config-n-1-dev.yml + template: + filter_to_backport: false latest: false release_branch: true repos: | diff --git a/.sync/workflows/config/release-draft/release-draft-config.yml b/.sync/workflows/config/release-draft/release-draft-config.yml index 073b7fcd..709b7abc 100644 --- a/.sync/workflows/config/release-draft/release-draft-config.yml +++ b/.sync/workflows/config/release-draft/release-draft-config.yml @@ -19,15 +19,25 @@ {% import '../../../Version.njk' as sync_version -%} +{%- if release_branch %} +name-template: 'dev-v$RESOLVED_VERSION' +tag-template: 'dev-v$RESOLVED_VERSION' +{% else %} name-template: 'v$RESOLVED_VERSION' tag-template: 'v$RESOLVED_VERSION' +{% endif %} {# `release_branch` applies a commitish. `latest` then determines the branch to use. -#} {# If a commitish is not specified, then the `github.ref` value is implicitly used. -#} {%- if release_branch %} -{% set release_branch = "refs/heads/" + (sync_version.latest_mu_release_branch if latest else sync_version.previous_mu_release_branch) %} -commitish: {{ release_branch }} +{%- set latest_mu_dev_branch = "refs/heads/" + (sync_version.latest_mu_release_branch | replace("release", "dev")) %} +{%- set previous_mu_dev_branch = "refs/heads/" + (sync_version.previous_mu_release_branch | replace("release", "dev")) %} +{%- set actual_branch = latest_mu_dev_branch if latest else previous_mu_dev_branch %} +commitish: {{ actual_branch }} filter-by-commitish: true +{% if filter_to_backport %} +include-labels: ["type:backport"] +{% endif %} {% endif %} template: | @@ -35,7 +45,11 @@ template: | $CHANGES +{% if release_branch %} + **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...dev-v$RESOLVED_VERSION +{% else %} **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION +{% endif %} categories: - title: '⚠️ Breaking Changes' diff --git a/.sync/workflows/leaf/release-draft.yml b/.sync/workflows/leaf/release-draft.yml index f32a1b52..894381c2 100644 --- a/.sync/workflows/leaf/release-draft.yml +++ b/.sync/workflows/leaf/release-draft.yml @@ -23,12 +23,21 @@ name: Update Release Draft on: +{% if depend_on_backport %} + workflow_run: + workflows: ["Backport Commits to Release Branch"] + branches: [{{ trigger_branch_name if trigger_branch_name else sync_version.latest_mu_release_branch | replace ("release", "dev") }}] + types: + - completed +{% else %} push: branches: - - {{ trigger_branch_name if trigger_branch_name else sync_version.latest_mu_release_branch }} + - {{ trigger_branch_name if trigger_branch_name else sync_version.latest_mu_release_branch | replace ("release", "dev") }} +{% endif %} jobs: draft: + name: Draft Releases permissions: contents: write