diff --git a/.github/config/release.yml b/.github/config/release.yml new file mode 100644 index 0000000000..cf08521604 --- /dev/null +++ b/.github/config/release.yml @@ -0,0 +1,28 @@ +changelog: + exclude: + labels: + - 'kind/skip-release-notes' + - 'wontfix' + - 'triage/wont-fix' + - 'triage/invalid' + categories: + - title: '‼️ Breaking Changes' + labels: + - 'breaking-change' + - title: '🚀 Features' + labels: + - 'kind/enhancement' + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'kind/bug' + - 'fix' + - 'bugfix' + - 'bug' + - title: '🧰 Maintenance' + labels: + - 'chore' + - title: '⬆️ Dependencies' + labels: + - 'dependencies' \ No newline at end of file diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml deleted file mode 100644 index 6827c023ff..0000000000 --- a/.github/release-drafter.yml +++ /dev/null @@ -1,38 +0,0 @@ -name-template: 'v$RESOLVED_VERSION' -tag-template: 'v$RESOLVED_VERSION' -version-template: '$COMPLETE' -change-template: '- $TITLE (#$NUMBER)' -change-title-escapes: '\<*_&#@`' -template: | - # Release v$RESOLVED_VERSION - - $CHANGES -exclude-labels: - - 'kind/skip-release-notes' - - 'wontfix' - - 'triage/wont-fix' - - 'triage/invalid' -categories: - - title: '‼️ Breaking Changes' - labels: - - 'breaking-change' - - title: '🚀 Features' - labels: - - 'kind/enhancement' - - 'feature' - - 'enhancement' - - title: '🐛 Bug Fixes' - collapse-after: 5 - labels: - - 'kind/bug' - - 'fix' - - 'bugfix' - - 'bug' - - title: '🧰 Maintenance' - collapse-after: 3 - labels: - - 'chore' - - title: '⬆️ Dependencies' - collapse-after: 3 - labels: - - 'dependencies' diff --git a/.github/workflows/release-branch.yaml b/.github/workflows/release-branch.yaml index f63d279c5f..ac0d425169 100644 --- a/.github/workflows/release-branch.yaml +++ b/.github/workflows/release-branch.yaml @@ -80,7 +80,15 @@ jobs: ref: main fetch-depth: 0 token: ${{ steps.generate_token.outputs.token }} - + # tag the cutoff point in main so that it can be used for release note generation + - name: Create Cutoff Tag in Main + run: | + set -e + tag="v${{ needs.cutoff-preconditions.outputs.minor }}" + msg="Cutoff for $tag" + git tag --annotate --message "${msg}" "$tag" + git push origin "$tag" + # create a new branch - name: Create Release Branch run: | set -e diff --git a/.github/workflows/release-drafter.yaml b/.github/workflows/release-drafter.yaml index 607cf7613b..d7abccb460 100644 --- a/.github/workflows/release-drafter.yaml +++ b/.github/workflows/release-drafter.yaml @@ -11,7 +11,7 @@ on: permissions: contents: read # The release-drafter action adds PR titles to the release notes once these are merged to main. - # A draft release is kept up-to-date listing the changes for the next minor release version. + # A draft release is kept up-to-date listing the changes for the next minor or patch release version for that branch. jobs: release-version: name: Release Version @@ -31,12 +31,68 @@ jobs: env: RELEASE_VERSION: ${{ needs.release-version.outputs.version }} steps: + - name: Generate token + id: generate_token + uses: tibdex/github-app-token@v2 + with: + app_id: ${{ secrets.OCMBOT_APP_ID }} + private_key: ${{ secrets.OCMBOT_PRIV_KEY }} - name: Checkout uses: actions/checkout@v4 - - name: Drafter - uses: release-drafter/release-drafter@v6 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag: ${{env.RELEASE_VERSION }} - version: ${{env.RELEASE_VERSION }} \ No newline at end of file + fetch-depth: 0 + fetch-tags: true + - name: Setup Release with gh + env: + REF: ${{ github.ref }} + REPO: ${{ github.repository }} + GH_TOKEN: ${{ steps.generate_token.outputs.token }} + run: | + # generate the release notes based on the last previous tag. + # do not match for any latest tag but only a valid semver tag. + # also do not match for the cutoff tag for the release branch. + # Example: If we are in releases/v0.18, we don't want to match v0.18 as the cutoff tag. + # Instead we want to match the one before that, which would be v0.17. + # That would generate us the notes from + # v0.17 to HEAD, which is what we want. + previous_tag=$(git describe HEAD --abbrev=0 --tags --match "v*" --exclude "*latest*" --exclude "${REF#releases/}") + + if [[ -z $previous_tag ]]; then + echo "No previous tag found, cannot generate release notes" + exit 1 + fi + + echo "Generating release notes for ${{env.RELEASE_VERSION}} starting from ${previous_tag} to HEAD" + + notes=$(\ + gh api \ + --method POST \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /repos/${REPO}/releases/generate-notes \ + -f "tag_name=${{env.RELEASE_VERSION}}" \ + -f "target_commitish=${{ github.ref }}" \ + -f "previous_tag_name=${previous_tag}" \ + -f "configuration_file_path=.github/config/release.yml" \ + -q .body \ + ) + + echo "Release Notes generated for ${{env.RELEASE_VERSION}}:" + echo "${notes}" + + echo "Verifying if release ${{env.RELEASE_VERSION}} already exists" + if [[ -z $(gh release list -R ${REPO} --json name -q '.[] | select(.name == "${{env.RELEASE_VERSION}}")') ]]; then + echo "Release ${{env.RELEASE_VERSION}} does not exist yet, creating from scratch" + gh release create ${{env.RELEASE_VERSION}} \ + --title "${{env.RELEASE_VERSION}}" \ + --notes "${notes}" \ + --draft \ + --latest=false \ + --target ${{ github.ref }} \ + -R ${REPO} + else + echo "Release ${{env.RELEASE_VERSION}} already exists, updating existing..." + gh release edit ${{env.RELEASE_VERSION}} \ + --notes "${notes}" \ + -R ${REPO} + fi diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f15bdb2250..79b97c6a53 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -181,8 +181,22 @@ jobs: git commit -m "Release $RELEASE_VERSION" msg="Release ${{ env.RELEASE_VERSION }}" git tag --annotate --message "${msg}" ${{ env.RELEASE_VERSION }} - # push both the tag as well as a release branch with that tag. + # push the tag. git push origin ${{ env.RELEASE_VERSION }} + # in case we do not have a release candidate, we should merge the release into the branch + # this is so that the tag shows up in the branch and we can use it for the release notes. + # This allows us to generate the notes for the next versions based on the last release. + # Example: + # Branch releases/v0.19 + # - Candidate Build v0.19.0-rc.1 => no merge, release notes based on original cutoff + # - Actual Build v0.19.0 => merge, release notes based on original cutoff + # - Candidate Build v0.19.1-rc.1 => no merge, release notes based on v0.19.0 due to previous merge + - name: Merge Release Tag back into release branch if not a release candidate + if: inputs.release_candidate == false + run: | + git checkout ${{ github.ref }} + git merge --strategy ours ${{ env.RELEASE_VERSION }} + git push origin ${{ github.ref }} - name: Create GPG Token file from Secret run: |