From d6ab3af18eda5ae21cc252f9793020df3ff9ee6f Mon Sep 17 00:00:00 2001 From: Alec Larson <1925840+aleclarson@users.noreply.github.com> Date: Mon, 12 Aug 2024 00:25:04 -0400 Subject: [PATCH] chore: refactor ./scripts/bundle-impact/ --- .github/workflows/bundle-impact.yml | 12 +- scripts/bundle-impact.sh | 2 +- scripts/bundle-impact/package.json | 4 +- scripts/bundle-impact/pnpm-lock.yaml | 145 +++++++++++++++++- ...pact.test.cjs => pr-bundle-impact.test.ts} | 28 ++-- scripts/bundle-impact/pr-bundle-impact.ts | 69 ++++++--- scripts/bundle-impact/{ => src}/dedent.ts | 2 +- .../bundle-impact/{ => src}/weigh-changed.ts | 6 +- 8 files changed, 215 insertions(+), 53 deletions(-) rename scripts/bundle-impact/{pr-bundle-impact.test.cjs => pr-bundle-impact.test.ts} (82%) rename scripts/bundle-impact/{ => src}/dedent.ts (97%) rename scripts/bundle-impact/{ => src}/weigh-changed.ts (95%) diff --git a/.github/workflows/bundle-impact.yml b/.github/workflows/bundle-impact.yml index 0bd090df..1e1a9ab9 100644 --- a/.github/workflows/bundle-impact.yml +++ b/.github/workflows/bundle-impact.yml @@ -9,8 +9,6 @@ jobs: bundle-impact: name: Calculate Bundle Impact runs-on: ubuntu-latest - permissions: - pull-requests: write steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 @@ -23,12 +21,8 @@ jobs: pnpm install -C scripts/bundle-impact - name: Run Bundle Impact - uses: actions/github-script@v7 env: + RADASHI_BOT_TOKEN: ${{ secrets.RADASHI_BOT_TOKEN }} TARGET_BRANCH: ${{ github.base_ref }} - NODE_OPTIONS: '--import ./scripts/bundle-impact/node_modules/tsx/dist/esm/index.mjs' - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const script = await import('${{ github.workspace }}/scripts/bundle-impact/pr-bundle-impact.ts') - await script.run({ github, core, context }) + run: | + scripts/bundle-impact/node_modules/.bin/tsx pr-bundle-impact.ts ${{ github.event.number }} diff --git a/scripts/bundle-impact.sh b/scripts/bundle-impact.sh index 54092057..8ad7829b 100644 --- a/scripts/bundle-impact.sh +++ b/scripts/bundle-impact.sh @@ -5,7 +5,7 @@ if [ ! -d "scripts/release-notes/node_modules" ]; then pnpm install -C scripts/release-notes fi -pnpm -s tsx -e ' +pnpm -s scripts/bundle-impact/node_modules/.bin/tsx -e ' import {weighChangedFunctions} from "./scripts/bundle-impact/weigh-changed.ts"; weighChangedFunctions().then(console.log) ' diff --git a/scripts/bundle-impact/package.json b/scripts/bundle-impact/package.json index 3b522f4f..acd22ed9 100644 --- a/scripts/bundle-impact/package.json +++ b/scripts/bundle-impact/package.json @@ -2,8 +2,10 @@ "private": true, "type": "module", "dependencies": { + "@octokit/rest": "^21.0.1", "execa": "^9.3.0", - "radashi": "12.2.0-beta.7fb6e89", + "mri": "^1.2.0", + "radashi": "link:../../src", "tsx": "^4.17.0" } } diff --git a/scripts/bundle-impact/pnpm-lock.yaml b/scripts/bundle-impact/pnpm-lock.yaml index 1c4cec16..8ef9ae56 100644 --- a/scripts/bundle-impact/pnpm-lock.yaml +++ b/scripts/bundle-impact/pnpm-lock.yaml @@ -8,12 +8,18 @@ importers: .: dependencies: + '@octokit/rest': + specifier: ^21.0.1 + version: 21.0.1 execa: specifier: ^9.3.0 version: 9.3.0 + mri: + specifier: ^1.2.0 + version: 1.2.0 radashi: - specifier: 12.2.0-beta.7fb6e89 - version: 12.2.0-beta.7fb6e89 + specifier: link:../../src + version: link:../../src tsx: specifier: ^4.17.0 version: 4.17.0 @@ -164,6 +170,58 @@ packages: cpu: [x64] os: [win32] + '@octokit/auth-token@5.1.1': + resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==} + engines: {node: '>= 18'} + + '@octokit/core@6.1.2': + resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==} + engines: {node: '>= 18'} + + '@octokit/endpoint@10.1.1': + resolution: {integrity: sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==} + engines: {node: '>= 18'} + + '@octokit/graphql@8.1.1': + resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@22.2.0': + resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} + + '@octokit/plugin-paginate-rest@11.3.3': + resolution: {integrity: sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=6' + + '@octokit/plugin-request-log@5.3.1': + resolution: {integrity: sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=6' + + '@octokit/plugin-rest-endpoint-methods@13.2.4': + resolution: {integrity: sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=6' + + '@octokit/request-error@6.1.4': + resolution: {integrity: sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==} + engines: {node: '>= 18'} + + '@octokit/request@9.1.3': + resolution: {integrity: sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==} + engines: {node: '>= 18'} + + '@octokit/rest@21.0.1': + resolution: {integrity: sha512-RWA6YU4CqK0h0J6tfYlUFnH3+YgBADlxaHXaKSG+BVr2y4PTfbU2tlKuaQoQZ83qaTbi4CUxLNAmbAqR93A6mQ==} + engines: {node: '>= 18'} + + '@octokit/types@13.5.0': + resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==} + '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -171,6 +229,9 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} + before-after-hook@3.0.2: + resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -219,6 +280,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -239,10 +304,6 @@ packages: resolution: {integrity: sha512-o1piW0n3tgKIKCwk2vpM/vOV13zjJzvP37Ioze54YlTHE06m4tjEbzg9WsKkvTuyYln2DHjo5pY4qrZGI0otpw==} engines: {node: '>=18'} - radashi@12.2.0-beta.7fb6e89: - resolution: {integrity: sha512-zBJajRnOB3vnX1mBNOMBrfblepRxSJ7/peTndW0wnfvw53mZ2Ra77ZXU9XCfpyO003y6cjJBqEioLX39jhyAsg==} - engines: {node: '>=16.0.0'} - resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} @@ -267,6 +328,9 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + universal-user-agent@7.0.2: + resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -350,10 +414,73 @@ snapshots: '@esbuild/win32-x64@0.23.0': optional: true + '@octokit/auth-token@5.1.1': {} + + '@octokit/core@6.1.2': + dependencies: + '@octokit/auth-token': 5.1.1 + '@octokit/graphql': 8.1.1 + '@octokit/request': 9.1.3 + '@octokit/request-error': 6.1.4 + '@octokit/types': 13.5.0 + before-after-hook: 3.0.2 + universal-user-agent: 7.0.2 + + '@octokit/endpoint@10.1.1': + dependencies: + '@octokit/types': 13.5.0 + universal-user-agent: 7.0.2 + + '@octokit/graphql@8.1.1': + dependencies: + '@octokit/request': 9.1.3 + '@octokit/types': 13.5.0 + universal-user-agent: 7.0.2 + + '@octokit/openapi-types@22.2.0': {} + + '@octokit/plugin-paginate-rest@11.3.3(@octokit/core@6.1.2)': + dependencies: + '@octokit/core': 6.1.2 + '@octokit/types': 13.5.0 + + '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.2)': + dependencies: + '@octokit/core': 6.1.2 + + '@octokit/plugin-rest-endpoint-methods@13.2.4(@octokit/core@6.1.2)': + dependencies: + '@octokit/core': 6.1.2 + '@octokit/types': 13.5.0 + + '@octokit/request-error@6.1.4': + dependencies: + '@octokit/types': 13.5.0 + + '@octokit/request@9.1.3': + dependencies: + '@octokit/endpoint': 10.1.1 + '@octokit/request-error': 6.1.4 + '@octokit/types': 13.5.0 + universal-user-agent: 7.0.2 + + '@octokit/rest@21.0.1': + dependencies: + '@octokit/core': 6.1.2 + '@octokit/plugin-paginate-rest': 11.3.3(@octokit/core@6.1.2) + '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.2) + '@octokit/plugin-rest-endpoint-methods': 13.2.4(@octokit/core@6.1.2) + + '@octokit/types@13.5.0': + dependencies: + '@octokit/openapi-types': 22.2.0 + '@sec-ant/readable-stream@0.4.1': {} '@sindresorhus/merge-streams@4.0.0': {} + before-after-hook@3.0.2: {} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -428,6 +555,8 @@ snapshots: isexe@2.0.0: {} + mri@1.2.0: {} + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -442,8 +571,6 @@ snapshots: dependencies: parse-ms: 4.0.0 - radashi@12.2.0-beta.7fb6e89: {} - resolve-pkg-maps@1.0.0: {} shebang-command@2.0.0: @@ -463,6 +590,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + universal-user-agent@7.0.2: {} + which@2.0.2: dependencies: isexe: 2.0.0 diff --git a/scripts/bundle-impact/pr-bundle-impact.test.cjs b/scripts/bundle-impact/pr-bundle-impact.test.ts similarity index 82% rename from scripts/bundle-impact/pr-bundle-impact.test.cjs rename to scripts/bundle-impact/pr-bundle-impact.test.ts index b31a4999..e836d337 100644 --- a/scripts/bundle-impact/pr-bundle-impact.test.cjs +++ b/scripts/bundle-impact/pr-bundle-impact.test.ts @@ -1,14 +1,12 @@ -import { test, vi } from 'vitest' -import { dedent } from './dedent' +import { expect, test, vi } from 'vitest' import { run } from './pr-bundle-impact' +import { dedent } from './src/dedent' +import { weighChangedFunctions } from './src/weigh-changed' - -vi.mock('./weigh-changed', () => ({ - weighChangedFunctions: vi.fn(), -})) +vi.mock('./src/weigh-changed') test('adds the bundle impact to the PR body', async () => { - const pulls = { + const pulls: Record = { 'radashi-org/radashi#1': { body: dedent` ## Summary @@ -29,7 +27,15 @@ test('adds the bundle impact to the PR body', async () => { github: { rest: { pulls: { - get({ owner, repo, pull_number }) { + get({ + owner, + repo, + pull_number, + }: { + owner: string + repo: string + pull_number: number + }) { return Promise.resolve({ data: pulls[`${owner}/${repo}#${pull_number}`], }) @@ -44,9 +50,7 @@ test('adds the bundle impact to the PR body', async () => { }, } - const { weighChangedFunctions } = await import('./weigh-changed') - - weighChangedFunctions.mockResolvedValue( + vi.mocked(weighChangedFunctions).mockResolvedValue( dedent` | Status | File | Size | Difference (%) | | --- | --- | --- | --- | @@ -101,7 +105,7 @@ test('adds the bundle impact to the PR body', async () => { // Now that we've tested adding the "Bundle Impact" section, let's test // updating that section upon a subsequent run. - weighChangedFunctions.mockResolvedValue( + vi.mocked(weighChangedFunctions).mockResolvedValue( dedent` | Status | File | Size | Difference (%) | | --- | --- | --- | --- | diff --git a/scripts/bundle-impact/pr-bundle-impact.ts b/scripts/bundle-impact/pr-bundle-impact.ts index f51fb01a..0a7b3071 100644 --- a/scripts/bundle-impact/pr-bundle-impact.ts +++ b/scripts/bundle-impact/pr-bundle-impact.ts @@ -1,22 +1,32 @@ -import { weighChangedFunctions } from './weigh-changed' +import { Octokit } from '@octokit/rest' +import mri from 'mri' +import { weighChangedFunctions } from './src/weigh-changed' -export async function run({ github, core, context }) { - const repo = `${context.repo.owner}/${context.repo.repo}` - core.info(`fetching PR #${context.issue.number} data from ${repo}...`) +const octokit = new Octokit({ + auth: process.env.RADASHI_BOT_TOKEN, +}) - const { data: pullRequest } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.issue.number, +main() + +async function main() { + const { prNumber } = parseArgv(process.argv.slice(2)) + + console.log(`fetching PR #${prNumber} data...`) + + const { data: pullRequest } = await octokit.rest.pulls.get({ + owner: 'radashi-org', + repo: 'radashi', + pull_number: prNumber, }) - core.info('calculating bundle impact...') + console.log('weighing changed functions...') + let bundleImpact = await weighChangedFunctions() - if (bundleImpact) { - bundleImpact = `## Bundle impact\n\n${bundleImpact}\n\n` - } + bundleImpact = bundleImpact ? `## Bundle impact\n\n${bundleImpact}\n\n` : '' + + console.log('updating PR description...') - const originalBody = pullRequest.body + const originalBody = pullRequest.body! const bundleImpactRegex = /## Bundle impact[\s\S]*?(?=##|$)/ let updatedBody: string @@ -27,14 +37,35 @@ export async function run({ github, core, context }) { } if (updatedBody !== originalBody) { - core.info('updating PR description...') - await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.issue.number, + console.log('updating PR description...') + await octokit.rest.pulls.update({ + owner: 'radashi-org', + repo: 'radashi', + pull_number: prNumber, body: updatedBody, }) - core.info('PR description updated with bundle impact.') + console.log('PR description updated with bundle impact.') + } +} + +function parseArgv(argv: string[]) { + if (!process.env.RADASHI_BOT_TOKEN) { + throw new Error('RADASHI_BOT_TOKEN is required') + } + if (!process.env.TARGET_BRANCH) { + throw new Error('TARGET_BRANCH is required') + } + + const { + _: [prNumber], + } = mri(argv) + + if (!Number.isInteger(+prNumber)) { + throw new Error('PR number is required') + } + + return { + prNumber: +prNumber, } } diff --git a/scripts/bundle-impact/dedent.ts b/scripts/bundle-impact/src/dedent.ts similarity index 97% rename from scripts/bundle-impact/dedent.ts rename to scripts/bundle-impact/src/dedent.ts index ab9e3099..6a955db6 100644 --- a/scripts/bundle-impact/dedent.ts +++ b/scripts/bundle-impact/src/dedent.ts @@ -1,4 +1,4 @@ -import { isArray } from 'radashi' +import { isArray } from 'radashi/typed/isArray.js' /** * Remove indentation from a string. The given string is expected to diff --git a/scripts/bundle-impact/weigh-changed.ts b/scripts/bundle-impact/src/weigh-changed.ts similarity index 95% rename from scripts/bundle-impact/weigh-changed.ts rename to scripts/bundle-impact/src/weigh-changed.ts index ba408d06..decdac88 100644 --- a/scripts/bundle-impact/weigh-changed.ts +++ b/scripts/bundle-impact/src/weigh-changed.ts @@ -1,6 +1,8 @@ import { execa } from 'execa' -import * as readline from 'node:readline/promises' -import { cluster, map, select } from 'radashi' +import readline from 'node:readline/promises' +import { cluster } from 'radashi/array/cluster.js' +import { select } from 'radashi/array/select.js' +import { map } from 'radashi/async/map.js' export async function weighChangedFunctions() { const targetBranch = await getTargetBranch()