diff --git a/.github/actions/version-bump-summary/action.yml b/.github/actions/version-bump-summary/action.yml new file mode 100644 index 0000000000..85f073c2bf --- /dev/null +++ b/.github/actions/version-bump-summary/action.yml @@ -0,0 +1,24 @@ +name: Version Bump Summary +description: Generates a JSON summary of all packages bumped in the current commit, with their previous and current versions. + +inputs: + ref: + description: Git commit SHA or ref to read tags from. Defaults to HEAD. + required: false + default: HEAD + +outputs: + json-file: + description: Path to the JSON summary temp file. + value: ${{ steps.summary.outputs.json-file }} + text-file: + description: Path to the text summary temp file. + value: ${{ steps.summary.outputs.text-file }} + +runs: + using: composite + steps: + - name: Generate version bump summary + id: summary + shell: bash + run: node ${{ github.action_path }}/index.js ${{ inputs.ref }} diff --git a/.github/actions/version-bump-summary/index.js b/.github/actions/version-bump-summary/index.js new file mode 100644 index 0000000000..e90218cbce --- /dev/null +++ b/.github/actions/version-bump-summary/index.js @@ -0,0 +1,54 @@ +const { execSync, execFileSync } = require("child_process"); +const fs = require("fs"); +const tmp = require("tmp"); + +const ref = process.argv[2] || "HEAD"; + +const newTags = execFileSync("git", ["tag", "--points-at", ref]) + .toString() + .trim() + .split("\n") + .filter(Boolean); + +const summary = newTags.map((tag) => { + const atIndex = tag.lastIndexOf("@"); + const packageName = tag.slice(0, atIndex); + const currentVersion = tag.slice(atIndex + 1); + + const previousTags = execSync( + `git tag --sort=-version:refname -l "${packageName}@*"` + ) + .toString() + .trim() + .split("\n") + .filter(Boolean); + + const previousTag = previousTags.find((t) => t !== tag); + const previousVersion = previousTag + ? previousTag.slice(previousTag.lastIndexOf("@") + 1) + : null; + + return { package: packageName, previousVersion, currentVersion }; +}); + +const jsonContent = JSON.stringify(summary, null, 2); +const textContent = summary + .map((entry) => { + const prev = entry.previousVersion || "new"; + return `${entry.package}: ${prev} -> ${entry.currentVersion}`; + }) + .join("\n"); + +console.log(textContent); + +const jsonTmp = tmp.fileSync({ prefix: "version-bump-summary-", postfix: ".json" }); +fs.writeFileSync(jsonTmp.name, jsonContent + "\n"); + +const txtTmp = tmp.fileSync({ prefix: "version-bump-summary-", postfix: ".txt" }); +fs.writeFileSync(txtTmp.name, textContent + "\n"); + +const ghOutput = process.env.GITHUB_OUTPUT; +if (ghOutput) { + fs.appendFileSync(ghOutput, `json-file=${jsonTmp.name}\n`); + fs.appendFileSync(ghOutput, `text-file=${txtTmp.name}\n`); +} diff --git a/.github/workflows/npmjs-release.yml b/.github/workflows/npmjs-release.yml index b3e915ea8c..5edd79fc1d 100644 --- a/.github/workflows/npmjs-release.yml +++ b/.github/workflows/npmjs-release.yml @@ -12,7 +12,7 @@ on: default: false permissions: - contents: read + contents: write id-token: write pull-requests: read @@ -177,6 +177,12 @@ jobs: run: | yarn lerna publish --sign-git-tag --sign-git-commit --include-merged-tags --conventional-commits --conventional-graduate --verify-access --yes + - name: Generate version bump summary + id: version-bump-summary + if: inputs.dry-run == false + continue-on-error: true + uses: ./.github/actions/version-bump-summary + - name: Extract published version if: inputs.dry-run == false id: extract-version @@ -184,3 +190,14 @@ jobs: NEW_VERSION=$(jq -r '.version' ./modules/bitgo/package.json) echo "New version: $NEW_VERSION" echo "new-version=$NEW_VERSION" >> "$GITHUB_OUTPUT" + + - name: Create GitHub release draft + if: inputs.dry-run == false && steps.version-bump-summary.outcome == 'success' + continue-on-error: true + env: + GH_TOKEN: ${{ secrets.BITGOBOT_PAT_TOKEN || github.token }} + run: | + gh release create "v${{ steps.extract-version.outputs.new-version }}" \ + --draft \ + --title "v${{ steps.extract-version.outputs.new-version }}" \ + --notes-file "${{ steps.version-bump-summary.outputs.text-file }}"