From fef37978ac894d1afe6bf12168615ea5a3b36bb7 Mon Sep 17 00:00:00 2001 From: Yuta Kasai Date: Mon, 25 Nov 2024 15:58:56 +0900 Subject: [PATCH] Automate to prepare release note with next version --- .github/workflows/create-draft-release.yml | 117 +++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 .github/workflows/create-draft-release.yml diff --git a/.github/workflows/create-draft-release.yml b/.github/workflows/create-draft-release.yml new file mode 100644 index 00000000..8f7715d8 --- /dev/null +++ b/.github/workflows/create-draft-release.yml @@ -0,0 +1,117 @@ +name: Create Draft Release with Auto-Generated Notes + +on: + workflow_dispatch: + inputs: + version_type: + description: "Select the version type to increment (major, minor, patch)" + required: true + type: choice + options: + - patch + - minor + - major + release_title: + description: "Enter the title of the release" + required: true + type: string + acknowledge_draft: + description: "I understand that I must re-edit and finalize the draft release (Y/N)" + required: true + type: choice + options: + - "No" + - "Yes" + +jobs: + validate-input: + runs-on: ubuntu-latest + steps: + - name: Validate Acknowledgement + if: ${{ github.event.inputs.acknowledge_draft != 'Yes' }} + run: | + echo "You must select 'Yes' to acknowledge your responsibility for finalizing the draft release." + exit 1 + - name: Validate title (no empty) + if: ${{ github.event.inputs.release_title == '' }} + run: | + echo "You must enter a title for the release." + exit 1 + + create-draft-release: + runs-on: ubuntu-latest + needs: validate-input + + steps: + - uses: actions/checkout@v4 + - name: Fetch Latest Release + id: get-latest-release + uses: actions/github-script@v6 + with: + script: | + const latestRelease = await github.rest.repos.getLatestRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + }).catch(() => null); + + if (latestRelease) { + core.setOutput('latest_tag', latestRelease.data.tag_name); + } else { + core.setOutput('latest_tag', 'v0.0.0'); // Default for first release + } + + - name: Calculate New Version + id: calculate-version + uses: actions/github-script@v6 + with: + script: | + const latestTag = '${{ steps.get-latest-release.outputs.latest_tag }}'; + const versionType = '${{ github.event.inputs.version_type }}'; + + const [major, minor, patch] = latestTag.replace('v', '').split('.').map(Number); + + let newVersion; + if (versionType === 'major') { + newVersion = `v${major + 1}.0.0`; + } else if (versionType === 'minor') { + newVersion = `v${major}.${minor + 1}.0`; + } else { + newVersion = `v${major}.${minor}.${patch + 1}`; + } + + core.setOutput('new_version', newVersion); + + - name: Generate Release Notes + id: generate-release-notes + uses: actions/github-script@v6 + with: + script: | + const { data: releaseNotes } = await github.rest.repos.generateReleaseNotes({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: "${{ steps.calculate-version.outputs.new_version }}" + }); + + const actor = context.actor; + const noteToAdd = `**@${actor} 👈 TODO: Write detailed release note for this version before release**\n`; + + const footer = `---\nThis release is prepared by @${actor}`; + + const modifiedBody = releaseNotes.body.replace( + '## What\'s Changed', + `## What's Changed\n\n${noteToAdd}` + ) + .concat(`\n\n${footer}`); + + console.log(`releaseNotes (modified): ${JSON.stringify(modifiedBody, null, 2)}`); + core.setOutput("release_body", modifiedBody); + + - name: Create Draft Release + run: | + gh release create "${{ steps.calculate-version.outputs.new_version }}" \ + --title "${{ steps.calculate-version.outputs.new_version }} ${{ github.event.inputs.release_title }}" \ + --notes "${{ steps.generate-release-notes.outputs.release_body }}" \ + --draft \ + --repo "${{ github.repository }}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}