From ac7ad720a5d18ab9f5d559d9dd687dd10ece7462 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 25 Sep 2024 16:30:55 +0200 Subject: [PATCH 01/16] WIP: Notify linked issues... --- .github/workflows/release-comment-issues.yml | 28 +++++ .../.eslintrc.cjs | 14 +++ .../action.yml | 12 ++ .../index.mjs | 31 +++++ .../package.json | 23 ++++ package.json | 1 + yarn.lock | 110 ++++++++++++++++++ 7 files changed, 219 insertions(+) create mode 100644 .github/workflows/release-comment-issues.yml create mode 100644 dev-packages/release-comment-issues-gh-action/.eslintrc.cjs create mode 100644 dev-packages/release-comment-issues-gh-action/action.yml create mode 100644 dev-packages/release-comment-issues-gh-action/index.mjs create mode 100644 dev-packages/release-comment-issues-gh-action/package.json diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml new file mode 100644 index 000000000000..409a8f107331 --- /dev/null +++ b/.github/workflows/release-comment-issues.yml @@ -0,0 +1,28 @@ +name: "Automation: Notify issues for release" +on: + release: + types: + - published + workflow_dispatch: + inputs: + version: + description: Which version to notify issues for + required: false + +# This workflow is triggered when a release is published +jobs: + release-comment-issues: + runs-on: ubuntu-20.04 + name: 'Notify issues that are included in a release' + + steps: + - name: Get version + id: get_version + run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name }}" >> $GITHUB_OUTPUT + + - name: Comment on linked issues that are mentioned in release + if: steps.get_version.outputs.version != '' + uses: ./dev-packages/release-comment-issues-gh-action + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + version: ${{ steps.get_version.outputs.version }} diff --git a/dev-packages/release-comment-issues-gh-action/.eslintrc.cjs b/dev-packages/release-comment-issues-gh-action/.eslintrc.cjs new file mode 100644 index 000000000000..8c67e0037908 --- /dev/null +++ b/dev-packages/release-comment-issues-gh-action/.eslintrc.cjs @@ -0,0 +1,14 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + parserOptions: { + sourceType: 'module', + ecmaVersion: 'latest', + }, + + overrides: [ + { + files: ['*.mjs'], + extends: ['@sentry-internal/sdk/src/base'], + }, + ], +}; diff --git a/dev-packages/release-comment-issues-gh-action/action.yml b/dev-packages/release-comment-issues-gh-action/action.yml new file mode 100644 index 000000000000..fcfb0bf00f2b --- /dev/null +++ b/dev-packages/release-comment-issues-gh-action/action.yml @@ -0,0 +1,12 @@ +name: 'release-comment-issues-gh-action' +description: 'An internal Github Action to comment on related issues when a release is published.' +inputs: + github_token: + required: true + description: 'a github access token' + version: + required: true + description: 'Which version was released' +runs: + using: 'node20' + main: 'index.mjs' diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs new file mode 100644 index 000000000000..b9988c5c9c61 --- /dev/null +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -0,0 +1,31 @@ +import * as core from '@actions/core'; +import { context, getOctokit } from '@actions/github'; + +async function run() { + const { getInput } = core; + + const githubToken = getInput('gh_token'); + const version = getInput('version'); + + if (!githubToken || !version) { + return; + } + + const { repo } = context; + const {owner} = repo; + + const octokit = getOctokit(githubToken); + + const release = await octokit.request('GET /repos/{owner}/{repo}/releases/tags/{tag}', { + owner, + repo, + tag: version, + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }); + + console.log(release); +} + +run(); diff --git a/dev-packages/release-comment-issues-gh-action/package.json b/dev-packages/release-comment-issues-gh-action/package.json new file mode 100644 index 000000000000..49c8f2ad5caa --- /dev/null +++ b/dev-packages/release-comment-issues-gh-action/package.json @@ -0,0 +1,23 @@ +{ + "name": "@sentry-internal/release-comment-issues-gh-action", + "description": "An internal Github Action to comment on related issues when a release is published.", + "version": "8.31.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "private": true, + "main": "index.mjs", + "type": "module", + "scripts": { + "lint": "eslint . --format stylish", + "fix": "eslint . --format stylish --fix" + }, + "dependencies": { + "@actions/core": "1.10.1", + "@actions/github": "6.0.0" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/package.json b/package.json index 365e1eb13922..b17092f04a80 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "dev-packages/size-limit-gh-action", "dev-packages/clear-cache-gh-action", "dev-packages/external-contributor-gh-action", + "dev-packages/release-comment-issues-gh-action", "dev-packages/rollup-utils" ], "devDependencies": { diff --git a/yarn.lock b/yarn.lock index a32337e3835f..91c55bb33d69 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27,6 +27,16 @@ dependencies: "@actions/io" "^1.0.1" +"@actions/github@6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@actions/github/-/github-6.0.0.tgz#65883433f9d81521b782a64cc1fd45eef2191ea7" + integrity sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g== + dependencies: + "@actions/http-client" "^2.2.0" + "@octokit/core" "^5.0.1" + "@octokit/plugin-paginate-rest" "^9.0.0" + "@octokit/plugin-rest-endpoint-methods" "^10.0.0" + "@actions/github@^5.0.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@actions/github/-/github-5.1.1.tgz#40b9b9e1323a5efcf4ff7dadd33d8ea51651bbcb" @@ -53,6 +63,14 @@ tunnel "^0.0.6" undici "^5.25.4" +"@actions/http-client@^2.2.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.3.tgz#31fc0b25c0e665754ed39a9f19a8611fc6dab674" + integrity sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA== + dependencies: + tunnel "^0.0.6" + undici "^5.25.4" + "@actions/io@1.1.3", "@actions/io@^1.0.1": version "1.1.3" resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.3.tgz#4cdb6254da7962b07473ff5c335f3da485d94d71" @@ -6747,6 +6765,11 @@ dependencies: "@octokit/types" "^8.0.0" +"@octokit/auth-token@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" + integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== + "@octokit/core@^3.6.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" @@ -6786,6 +6809,19 @@ before-after-hook "^2.2.0" universal-user-agent "^6.0.0" +"@octokit/core@^5.0.1": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" + integrity sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg== + dependencies: + "@octokit/auth-token" "^4.0.0" + "@octokit/graphql" "^7.1.0" + "@octokit/request" "^8.3.1" + "@octokit/request-error" "^5.1.0" + "@octokit/types" "^13.0.0" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + "@octokit/endpoint@^6.0.1": version "6.0.12" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" @@ -6804,6 +6840,14 @@ is-plain-object "^5.0.0" universal-user-agent "^6.0.0" +"@octokit/endpoint@^9.0.1": + version "9.0.5" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.5.tgz#e6c0ee684e307614c02fc6ac12274c50da465c44" + integrity sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw== + dependencies: + "@octokit/types" "^13.1.0" + universal-user-agent "^6.0.0" + "@octokit/graphql@^4.5.8": version "4.8.0" resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" @@ -6822,6 +6866,15 @@ "@octokit/types" "^8.0.0" universal-user-agent "^6.0.0" +"@octokit/graphql@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-7.1.0.tgz#9bc1c5de92f026648131f04101cab949eeffe4e0" + integrity sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ== + dependencies: + "@octokit/request" "^8.3.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^6.0.0" + "@octokit/openapi-types@^12.11.0": version "12.11.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" @@ -6842,6 +6895,16 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-18.0.0.tgz#f43d765b3c7533fd6fb88f3f25df079c24fccf69" integrity sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw== +"@octokit/openapi-types@^20.0.0": + version "20.0.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-20.0.0.tgz#9ec2daa0090eeb865ee147636e0c00f73790c6e5" + integrity sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA== + +"@octokit/openapi-types@^22.2.0": + version "22.2.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-22.2.0.tgz#75aa7dcd440821d99def6a60b5f014207ae4968e" + integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== + "@octokit/plugin-enterprise-rest@6.0.1": version "6.0.1" resolved "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" @@ -6869,11 +6932,25 @@ "@octokit/tsconfig" "^1.0.2" "@octokit/types" "^9.2.3" +"@octokit/plugin-paginate-rest@^9.0.0": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz#2e2a2f0f52c9a4b1da1a3aa17dabe3c459b9e401" + integrity sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw== + dependencies: + "@octokit/types" "^12.6.0" + "@octokit/plugin-request-log@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== +"@octokit/plugin-rest-endpoint-methods@^10.0.0": + version "10.4.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz#41ba478a558b9f554793075b2e20cd2ef973be17" + integrity sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg== + dependencies: + "@octokit/types" "^12.6.0" + "@octokit/plugin-rest-endpoint-methods@^5.13.0": version "5.16.2" resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342" @@ -6915,6 +6992,15 @@ deprecation "^2.0.0" once "^1.4.0" +"@octokit/request-error@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.1.0.tgz#ee4138538d08c81a60be3f320cd71063064a3b30" + integrity sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q== + dependencies: + "@octokit/types" "^13.1.0" + deprecation "^2.0.0" + once "^1.4.0" + "@octokit/request@^5.6.0", "@octokit/request@^5.6.3": version "5.6.3" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" @@ -6939,6 +7025,16 @@ node-fetch "^2.6.7" universal-user-agent "^6.0.0" +"@octokit/request@^8.3.0", "@octokit/request@^8.3.1": + version "8.4.0" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-8.4.0.tgz#7f4b7b1daa3d1f48c0977ad8fffa2c18adef8974" + integrity sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw== + dependencies: + "@octokit/endpoint" "^9.0.1" + "@octokit/request-error" "^5.1.0" + "@octokit/types" "^13.1.0" + universal-user-agent "^6.0.0" + "@octokit/rest@19.0.11": version "19.0.11" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.11.tgz#2ae01634fed4bd1fca5b642767205ed3fd36177c" @@ -6971,6 +7067,20 @@ dependencies: "@octokit/openapi-types" "^18.0.0" +"@octokit/types@^12.6.0": + version "12.6.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-12.6.0.tgz#8100fb9eeedfe083aae66473bd97b15b62aedcb2" + integrity sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw== + dependencies: + "@octokit/openapi-types" "^20.0.0" + +"@octokit/types@^13.0.0", "@octokit/types@^13.1.0": + version "13.5.1" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.5.1.tgz#5685a91f295195ddfff39723b093b0df9609ce6e" + integrity sha512-F41lGiWBKPIWPBgjSvaDXTTQptBujnozENAK3S//nj7xsFdYdirImKlBB/hTjr+Vii68SM+8jG3UJWRa6DMuDA== + dependencies: + "@octokit/openapi-types" "^22.2.0" + "@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0": version "6.41.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" From 51ee8a32c0189505111cd849a38905644759963c Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 25 Sep 2024 16:32:27 +0200 Subject: [PATCH 02/16] debug it... --- .github/workflows/release-comment-issues.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml index 409a8f107331..3f3dbfa40924 100644 --- a/.github/workflows/release-comment-issues.yml +++ b/.github/workflows/release-comment-issues.yml @@ -9,6 +9,9 @@ on: description: Which version to notify issues for required: false + # WIP just for debugging this... + push: + # This workflow is triggered when a release is published jobs: release-comment-issues: @@ -18,7 +21,7 @@ jobs: steps: - name: Get version id: get_version - run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name }}" >> $GITHUB_OUTPUT + run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name || '8.32.0' }}" >> $GITHUB_OUTPUT - name: Comment on linked issues that are mentioned in release if: steps.get_version.outputs.version != '' From b73167b903cc161c0806c4ccb5d20e844f6d5f68 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 25 Sep 2024 16:35:24 +0200 Subject: [PATCH 03/16] install deps... --- .github/workflows/release-comment-issues.yml | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml index 3f3dbfa40924..e86f3397a0c9 100644 --- a/.github/workflows/release-comment-issues.yml +++ b/.github/workflows/release-comment-issues.yml @@ -16,9 +16,33 @@ on: jobs: release-comment-issues: runs-on: ubuntu-20.04 - name: 'Notify issues that are included in a release' + name: 'Notify issues' steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Compute dependency cache key + id: compute_lockfile_hash + run: node ./scripts/dependency-hash-key.js >> "$GITHUB_OUTPUT" + shell: bash + + - name: Check dependency cache + uses: actions/cache/restore@v4 + id: cache_dependencies + with: + path: | + ${{ github.workspace }}/node_modules + ${{ github.workspace }}/packages/*/node_modules + ${{ github.workspace }}/dev-packages/*/node_modules + ~/.cache/mongodb-binaries/ + key: ${{ steps.compute_lockfile_hash.outputs.hash }} + + - name: Install dependencies + if: steps.cache_dependencies.outputs.cache-hit != 'true' + run: yarn install --ignore-engines --frozen-lockfile + shell: bash + - name: Get version id: get_version run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name || '8.32.0' }}" >> $GITHUB_OUTPUT From 6ce4d585695efc0269554085dfb255aadd7c74bb Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 25 Sep 2024 16:36:59 +0200 Subject: [PATCH 04/16] WIP actually cache it... --- .github/workflows/release-comment-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml index e86f3397a0c9..cbfec7421f2f 100644 --- a/.github/workflows/release-comment-issues.yml +++ b/.github/workflows/release-comment-issues.yml @@ -28,7 +28,7 @@ jobs: shell: bash - name: Check dependency cache - uses: actions/cache/restore@v4 + uses: actions/cache@v4 id: cache_dependencies with: path: | From 2de596f59a50b5fc7aa85b24acc2678bd563ac18 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 25 Sep 2024 16:41:10 +0200 Subject: [PATCH 05/16] fix input --- dev-packages/release-comment-issues-gh-action/index.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index b9988c5c9c61..5bac727c7315 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -4,10 +4,11 @@ import { context, getOctokit } from '@actions/github'; async function run() { const { getInput } = core; - const githubToken = getInput('gh_token'); + const githubToken = getInput('github_token'); const version = getInput('version'); if (!githubToken || !version) { + core.debug('Skipping because github_token or version are empty.'); return; } From 493ddf35f9e3d70940c5bd082163e60f1a5087c2 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 25 Sep 2024 16:47:53 +0200 Subject: [PATCH 06/16] fix it --- dev-packages/release-comment-issues-gh-action/index.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index 5bac727c7315..46ba7bad7c93 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -12,8 +12,7 @@ async function run() { return; } - const { repo } = context; - const {owner} = repo; + const {owner, repo} = context.repo; const octokit = getOctokit(githubToken); From e3829815ca3d3b9fd84eddb33ddd83b5f90eaa15 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:04:47 +0200 Subject: [PATCH 07/16] query linked issues --- .../index.mjs | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index 46ba7bad7c93..989e67afb148 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -25,7 +25,90 @@ async function run() { } }); - console.log(release); + + const prNumbers = extractPrsFromReleaseBody(release.data.body); + + if(!prNumbers.length) { + core.debug('No PRs found in release body.'); + return; + } + + core.debug(`Found PRs in release body: ${prNumbers.join(', ')}`); + + + const res = await octokit.graphql(` + { + query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $prNumber) { + id + closingIssuesReferences (first: 50) { + edges { + node { + id + number + } + } + } + } + } + } + } + `, { + prNumber: prNumbers[0], + owner, + repo + }); + + const linkedIssues = Promise.all(prNumbers.map((prNumber) => getLinkedIssuesForPr(octokit, { repo, owner, prNumber }))); + + console.log(linkedIssues); +} + +/** + * + * @param {string} body + * @returns {number[]} + */ +function extractPrsFromReleaseBody(body) { + const regex = /\[#(\d+)\]\(https:\/\/github\.com\/getsentry\/sentry-javascript\/pull\/(?:\d+)\)/gm; + const prNumbers = Array.from(new Set([...body.matchAll(regex)].map((match) => parseInt(match[1])))); + + return prNumbers.filter(number => !!number && !Number.isNaN(number)); +} + +/** + * + * @param {ReturnType} octokit + * @param {{ repo: string, owner: string, prNumber: number}} options + * @returns {Promise<{id: string, number: number}[]>} + */ +async function getLinkedIssuesForPr(octokit, { repo, owner, prNumber }) { + const res = await octokit.graphql(` + { + query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $prNumber) { + id + closingIssuesReferences (first: 50) { + edges { + node { + id + number + } + } + } + } + } + } + } + `, { + prNumber, + owner, + repo + }); + + return res.data.repository?.pullRequest?.closingIssuesReferences.edges.map(edge => edge.node); } run(); From 1700846db62ed44565200a87e364265fbc12a07e Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:06:33 +0200 Subject: [PATCH 08/16] fix query --- .../index.mjs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index 989e67afb148..8b5695dfb6ee 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -85,24 +85,21 @@ function extractPrsFromReleaseBody(body) { */ async function getLinkedIssuesForPr(octokit, { repo, owner, prNumber }) { const res = await octokit.graphql(` - { - query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { - repository(owner: $owner, name: $repo) { - pullRequest(number: $prNumber) { +query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $prNumber) { + id + closingIssuesReferences (first: 50) { + edges { + node { id - closingIssuesReferences (first: 50) { - edges { - node { - id - number - } - } - } + number } } } } - `, { + } +}`, { prNumber, owner, repo From 8818b97efeebd7517f408a6532a7a737ec4e76cb Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:12:10 +0200 Subject: [PATCH 09/16] oops fix it --- .../index.mjs | 63 +++++++++---------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index 8b5695dfb6ee..1a223d3d8ead 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -35,34 +35,20 @@ async function run() { core.debug(`Found PRs in release body: ${prNumbers.join(', ')}`); + const linkedIssues = Promise.all(prNumbers.map((prNumber) => getLinkedIssuesForPr(octokit, { repo, owner, prNumber }))); - const res = await octokit.graphql(` - { - query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { - repository(owner: $owner, name: $repo) { - pullRequest(number: $prNumber) { - id - closingIssuesReferences (first: 50) { - edges { - node { - id - number - } - } - } - } - } - } + console.log(linkedIssues); + + for(const pr of linkedIssues) { + if(!pr.issues.length) { + core.debug(`No linked issues found for PR #${pr.prNumber}`); + continue; } - `, { - prNumber: prNumbers[0], - owner, - repo - }); - const linkedIssues = Promise.all(prNumbers.map((prNumber) => getLinkedIssuesForPr(octokit, { repo, owner, prNumber }))); + core.debug(`Linked issues for PR #${pr.prNumber}: ${pr.issues.map(issue => issue.number).join(',')}`); + } + - console.log(linkedIssues); } /** @@ -75,16 +61,15 @@ function extractPrsFromReleaseBody(body) { const prNumbers = Array.from(new Set([...body.matchAll(regex)].map((match) => parseInt(match[1])))); return prNumbers.filter(number => !!number && !Number.isNaN(number)); -} - -/** +}/** * * @param {ReturnType} octokit * @param {{ repo: string, owner: string, prNumber: number}} options - * @returns {Promise<{id: string, number: number}[]>} + * @returns {Promise<{ prNumber: number, issues: {id: string, number: number}[] }>} */ async function getLinkedIssuesForPr(octokit, { repo, owner, prNumber }) { - const res = await octokit.graphql(` + const res = await octokit.graphql( + ` query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { @@ -99,13 +84,21 @@ query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { } } } -}`, { - prNumber, - owner, - repo - }); +}`, + { + prNumber, + owner, + repo, + }, + ); - return res.data.repository?.pullRequest?.closingIssuesReferences.edges.map(edge => edge.node); + console.log(res); + + const issues = res.data.repository?.pullRequest?.closingIssuesReferences.edges.map(edge => edge.node); + return { + prNumber, + issues + }; } run(); From 9268a7d1c9d795a68bd1f85a544d44dc8427f015 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:14:21 +0200 Subject: [PATCH 10/16] ensure we await --- dev-packages/release-comment-issues-gh-action/index.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index 1a223d3d8ead..b785ce447bb4 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -35,7 +35,7 @@ async function run() { core.debug(`Found PRs in release body: ${prNumbers.join(', ')}`); - const linkedIssues = Promise.all(prNumbers.map((prNumber) => getLinkedIssuesForPr(octokit, { repo, owner, prNumber }))); + const linkedIssues = await Promise.all(prNumbers.map((prNumber) => getLinkedIssuesForPr(octokit, { repo, owner, prNumber }))); console.log(linkedIssues); From 4f56773df5eb365921b960209b7062bb990e0ec6 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:15:56 +0200 Subject: [PATCH 11/16] fix graphql shape --- dev-packages/release-comment-issues-gh-action/index.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index b785ce447bb4..ec80cca600c5 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -94,7 +94,7 @@ query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { console.log(res); - const issues = res.data.repository?.pullRequest?.closingIssuesReferences.edges.map(edge => edge.node); + const issues = res.repository?.pullRequest?.closingIssuesReferences.edges.map(edge => edge.node); return { prNumber, issues From 9e834f53c75c5c1bcbd00eaf2bfa1bb135008c35 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:25:56 +0200 Subject: [PATCH 12/16] create comment (dry) --- .../index.mjs | 72 ++++++++++++++----- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index ec80cca600c5..ce8e784d7a7b 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -1,18 +1,20 @@ import * as core from '@actions/core'; -import { context, getOctokit } from '@actions/github'; +import { context, getOctokit } from '@actions/github'; + +const RELEASE_COMMENT_HEADING = '## A PR closing this issue has just been released 🚀'; async function run() { const { getInput } = core; const githubToken = getInput('github_token'); - const version = getInput('version'); + const version = getInput('version'); if (!githubToken || !version) { core.debug('Skipping because github_token or version are empty.'); return; } - const {owner, repo} = context.repo; + const { owner, repo } = context.repo; const octokit = getOctokit(githubToken); @@ -21,34 +23,50 @@ async function run() { repo, tag: version, headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } + 'X-GitHub-Api-Version': '2022-11-28', + }, }); - const prNumbers = extractPrsFromReleaseBody(release.data.body); - if(!prNumbers.length) { + if (!prNumbers.length) { core.debug('No PRs found in release body.'); return; } core.debug(`Found PRs in release body: ${prNumbers.join(', ')}`); - const linkedIssues = await Promise.all(prNumbers.map((prNumber) => getLinkedIssuesForPr(octokit, { repo, owner, prNumber }))); - - console.log(linkedIssues); + const linkedIssues = await Promise.all( + prNumbers.map(prNumber => getLinkedIssuesForPr(octokit, { repo, owner, prNumber })), + ); - for(const pr of linkedIssues) { - if(!pr.issues.length) { + for (const pr of linkedIssues) { + if (!pr.issues.length) { core.debug(`No linked issues found for PR #${pr.prNumber}`); continue; } core.debug(`Linked issues for PR #${pr.prNumber}: ${pr.issues.map(issue => issue.number).join(',')}`); - } + for (const issue of pr.issues) { + if (await hasExistingComment(octokit, { repo, owner, issueNumber: issue.number })) { + core.debug(`Comment already exists for issue #${issue.number}`); + continue; + } + + const body = `${RELEASE_COMMENT_HEADING}\n\nThis issue was closed by PR #${pr.prNumber}, which was included in the [${version} release](https://github.com/${owner}/${repo}/releases/tag/${version}).`; + + core.debug(`Creating comment for issue #${issue.number}`); + core.debug(body); + /* await octokit.rest.issues.createComment({ + repo, + owner, + issue_number: issue.number, + body, + }); */ + } + } } /** @@ -58,10 +76,12 @@ async function run() { */ function extractPrsFromReleaseBody(body) { const regex = /\[#(\d+)\]\(https:\/\/github\.com\/getsentry\/sentry-javascript\/pull\/(?:\d+)\)/gm; - const prNumbers = Array.from(new Set([...body.matchAll(regex)].map((match) => parseInt(match[1])))); + const prNumbers = Array.from(new Set([...body.matchAll(regex)].map(match => parseInt(match[1])))); + + return prNumbers.filter(number => !!number && !Number.isNaN(number)); +} - return prNumbers.filter(number => !!number && !Number.isNaN(number)); -}/** +/** * * @param {ReturnType} octokit * @param {{ repo: string, owner: string, prNumber: number}} options @@ -92,13 +112,27 @@ query issuesForPr($owner: String!, $repo: String!, $prNumber: Int!) { }, ); - console.log(res); - const issues = res.repository?.pullRequest?.closingIssuesReferences.edges.map(edge => edge.node); return { prNumber, - issues + issues, }; } +/** + * + * @param {ReturnType} octokit + * @param {{ repo: string, owner: string, issueNumber: number}} options + * @returns {Promise} + */ +async function hasExistingComment(octokit, { repo, owner, issueNumber }) { + const { data: commentList } = await octokit.rest.issues.listComments({ + repo, + owner, + issue_number: issueNumber, + }); + + return commentList.some(comment => comment.body.startsWith(RELEASE_COMMENT_HEADING)); +} + run(); From eceb10d43363516521aa2a56265e9115c24702e5 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:38:52 +0200 Subject: [PATCH 13/16] actually do it??! --- dev-packages/release-comment-issues-gh-action/index.mjs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index ce8e784d7a7b..dde44ea797af 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -57,14 +57,13 @@ async function run() { const body = `${RELEASE_COMMENT_HEADING}\n\nThis issue was closed by PR #${pr.prNumber}, which was included in the [${version} release](https://github.com/${owner}/${repo}/releases/tag/${version}).`; core.debug(`Creating comment for issue #${issue.number}`); - core.debug(body); - /* await octokit.rest.issues.createComment({ + await octokit.rest.issues.createComment({ repo, owner, issue_number: issue.number, body, - }); */ + }); } } } From e4e484078539366e6e2a8cd9c6f263aae1cf7c0d Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:46:10 +0200 Subject: [PATCH 14/16] make it production ready --- .github/workflows/release-comment-issues.yml | 5 +---- dev-packages/release-comment-issues-gh-action/index.mjs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml index cbfec7421f2f..6352dc82621a 100644 --- a/.github/workflows/release-comment-issues.yml +++ b/.github/workflows/release-comment-issues.yml @@ -9,9 +9,6 @@ on: description: Which version to notify issues for required: false - # WIP just for debugging this... - push: - # This workflow is triggered when a release is published jobs: release-comment-issues: @@ -45,7 +42,7 @@ jobs: - name: Get version id: get_version - run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name || '8.32.0' }}" >> $GITHUB_OUTPUT + run: echo "version=${{ github.event.inputs.version || github.event.release.tag_name }}" >> $GITHUB_OUTPUT - name: Comment on linked issues that are mentioned in release if: steps.get_version.outputs.version != '' diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index dde44ea797af..d0458dfe6a67 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -54,7 +54,7 @@ async function run() { continue; } - const body = `${RELEASE_COMMENT_HEADING}\n\nThis issue was closed by PR #${pr.prNumber}, which was included in the [${version} release](https://github.com/${owner}/${repo}/releases/tag/${version}).`; + const body = `${RELEASE_COMMENT_HEADING}\n\nThis issue was referenced by PR #${pr.prNumber}, which was included in the [${version} release](https://github.com/${owner}/${repo}/releases/tag/${version}).`; core.debug(`Creating comment for issue #${issue.number}`); From eb767c0262bb702e02e7c1c1eea19c5352a72726 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 11:48:05 +0200 Subject: [PATCH 15/16] do not cache deps --- .github/workflows/release-comment-issues.yml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml index 6352dc82621a..58ca4e571809 100644 --- a/.github/workflows/release-comment-issues.yml +++ b/.github/workflows/release-comment-issues.yml @@ -19,26 +19,8 @@ jobs: - name: Check out code uses: actions/checkout@v4 - - name: Compute dependency cache key - id: compute_lockfile_hash - run: node ./scripts/dependency-hash-key.js >> "$GITHUB_OUTPUT" - shell: bash - - - name: Check dependency cache - uses: actions/cache@v4 - id: cache_dependencies - with: - path: | - ${{ github.workspace }}/node_modules - ${{ github.workspace }}/packages/*/node_modules - ${{ github.workspace }}/dev-packages/*/node_modules - ~/.cache/mongodb-binaries/ - key: ${{ steps.compute_lockfile_hash.outputs.hash }} - - name: Install dependencies - if: steps.cache_dependencies.outputs.cache-hit != 'true' - run: yarn install --ignore-engines --frozen-lockfile - shell: bash + run: yarn install --frozen-lockfile - name: Get version id: get_version From ef4520ff95864ce7b154824a4887e83734c13e41 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 26 Sep 2024 12:52:48 +0200 Subject: [PATCH 16/16] avoid hard-coding stuff --- .github/workflows/release-comment-issues.yml | 1 - dev-packages/release-comment-issues-gh-action/index.mjs | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-comment-issues.yml b/.github/workflows/release-comment-issues.yml index 58ca4e571809..80cb04eb6b54 100644 --- a/.github/workflows/release-comment-issues.yml +++ b/.github/workflows/release-comment-issues.yml @@ -14,7 +14,6 @@ jobs: release-comment-issues: runs-on: ubuntu-20.04 name: 'Notify issues' - steps: - name: Check out code uses: actions/checkout@v4 diff --git a/dev-packages/release-comment-issues-gh-action/index.mjs b/dev-packages/release-comment-issues-gh-action/index.mjs index d0458dfe6a67..c49ad6575ef7 100644 --- a/dev-packages/release-comment-issues-gh-action/index.mjs +++ b/dev-packages/release-comment-issues-gh-action/index.mjs @@ -27,7 +27,7 @@ async function run() { }, }); - const prNumbers = extractPrsFromReleaseBody(release.data.body); + const prNumbers = extractPrsFromReleaseBody(release.data.body, { repo, owner }); if (!prNumbers.length) { core.debug('No PRs found in release body.'); @@ -71,10 +71,11 @@ async function run() { /** * * @param {string} body + * @param {{ repo: string, owner: string}} options * @returns {number[]} */ -function extractPrsFromReleaseBody(body) { - const regex = /\[#(\d+)\]\(https:\/\/github\.com\/getsentry\/sentry-javascript\/pull\/(?:\d+)\)/gm; +function extractPrsFromReleaseBody(body, { repo, owner }) { + const regex = new RegExp(`\\[#(\\d+)\\]\\(https:\\/\\/github\\.com\\/${owner}\\/${repo}\\/pull\\/(?:\\d+)\\)`, 'gm'); const prNumbers = Array.from(new Set([...body.matchAll(regex)].map(match => parseInt(match[1])))); return prNumbers.filter(number => !!number && !Number.isNaN(number));