From 37604ef61465a614f2a645e170db57d6a041eb34 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sat, 10 Jan 2026 14:59:42 +0100 Subject: [PATCH 01/13] fix(git-node): promoting a release using only PR number (#1028) Using the full URL should be preferred as that's the path to the least surprise, but passing only PR number should not error. --- components/git/release.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/git/release.js b/components/git/release.js index 69265b6d..94fa7f66 100644 --- a/components/git/release.js +++ b/components/git/release.js @@ -87,8 +87,8 @@ export function builder(yargs) { 'Prepare a new security release of Node.js with auto-determined version') .example('git node release --prepare --newVersion=1.2.3', 'Prepare a new release of Node.js tagged v1.2.3') - .example('git node release --promote 12345', - 'Promote a prepared release of Node.js with PR #12345') + .example('git node release --promote https://github.com/nodejs/node/pull/12345 https://github.com/nodejs/node/pull/54321', + 'Promote two prepared releases of Node.js with PR #12345 and #54321') .example('git node --prepare --startLTS', 'Prepare the first LTS release'); } @@ -182,7 +182,11 @@ async function main(state, argv, cli, dir) { console.info(`E.g. --fetch-from=git@github.com:${owner}/${repo}.git`); throw new Error('You need to tell what remote use to fetch security release proposal.'); } - releases.push(await release.preparePromotion({ owner, repo, prid: Number(prid) })); + releases.push(await release.preparePromotion({ + owner: owner ?? release.owner, + repo: repo ?? release.repo, + prid: Number(prid) + })); } return release.promote(releases); } From 19b468ad088a8200eabdc94a96f58a6027e2fc11 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Thu, 15 Jan 2026 14:13:25 -0800 Subject: [PATCH 02/13] feat: add list detail of failed GHA jobs (#960) --- lib/pr_checker.js | 81 ++++- lib/queries/PRCommits.gql | 10 +- .../github-ci/check-suite-cancelled.json | 37 +++ .../github-ci/check-suite-failure.json | 18 +- test/unit/pr_checker.test.js | 307 +++++++++++++++++- 5 files changed, 439 insertions(+), 14 deletions(-) create mode 100644 test/fixtures/github-ci/check-suite-cancelled.json diff --git a/lib/pr_checker.js b/lib/pr_checker.js index a4dfeaac..e48170ac 100644 --- a/lib/pr_checker.js +++ b/lib/pr_checker.js @@ -359,8 +359,13 @@ export default class PRChecker { return false; } + let hasFailures = false; + const failedJobs = []; + const cancelledJobs = []; + const pendingJobs = []; + // GitHub new Check API - for (const { status, conclusion, app } of checkSuites.nodes) { + for (const { status, conclusion, app, checkRuns } of checkSuites.nodes) { if (app.slug !== 'github-actions') { // Ignore all non-github check suites, such as Dependabot and Codecov. // They are expected to show up on PRs whose head branch is not on a @@ -369,16 +374,80 @@ export default class PRChecker { } if (status !== 'COMPLETED') { - cli.error('GitHub CI is still running'); - return false; + pendingJobs.push({ app: app.slug, status, conclusion }); + continue; } if (!GITHUB_SUCCESS_CONCLUSIONS.includes(conclusion)) { - cli.error('Last GitHub CI failed'); - return false; + hasFailures = true; + + // If we have detailed checkRuns, show specific failing jobs + if (checkRuns && checkRuns.nodes && checkRuns.nodes.length > 0) { + for (const checkRun of checkRuns.nodes) { + if (checkRun.status === 'COMPLETED' && + !GITHUB_SUCCESS_CONCLUSIONS.includes(checkRun.conclusion)) { + if (checkRun.conclusion === 'CANCELLED') { + cancelledJobs.push({ + name: checkRun.name, + conclusion: checkRun.conclusion, + url: checkRun.detailsUrl + }); + } else { + failedJobs.push({ + name: checkRun.name, + conclusion: checkRun.conclusion, + url: checkRun.detailsUrl + }); + } + } + } + } else { + // Fallback to check suite level information if no checkRuns + if (conclusion === 'CANCELLED') { + cancelledJobs.push({ + name: app.slug, + conclusion, + url: null + }); + } else { + failedJobs.push({ + name: app.slug, + conclusion, + url: null + }); + } + } + } + } + + // Report pending jobs + if (pendingJobs.length > 0) { + cli.error('GitHub CI is still running'); + return false; + } + + // Report failed jobs + if (failedJobs.length > 0) { + cli.error(`${failedJobs.length} GitHub CI job(s) failed:`); + for (const job of failedJobs) { + const urlInfo = job.url ? ` (${job.url})` : ''; + cli.error(` - ${job.name}: ${job.conclusion}${urlInfo}`); } } + // Report cancelled jobs + if (cancelledJobs.length > 0) { + cli.error(`${cancelledJobs.length} GitHub CI job(s) cancelled:`); + for (const job of cancelledJobs) { + const urlInfo = job.url ? ` (${job.url})` : ''; + cli.error(` - ${job.name}: ${job.conclusion}${urlInfo}`); + } + } + + if (hasFailures) { + return false; + } + // GitHub old commit status API if (commit.status) { const { state } = commit.status; @@ -388,7 +457,7 @@ export default class PRChecker { } if (!['SUCCESS', 'EXPECTED'].includes(state)) { - cli.error('Last GitHub CI failed'); + cli.error(`GitHub CI failed with status: ${state}`); return false; } } diff --git a/lib/queries/PRCommits.gql b/lib/queries/PRCommits.gql index d8a7db64..70cf2e4e 100644 --- a/lib/queries/PRCommits.gql +++ b/lib/queries/PRCommits.gql @@ -31,7 +31,15 @@ query Commits($prid: Int!, $owner: String!, $repo: String!, $after: String) { slug } conclusion, - status + status, + checkRuns(first: 40) { + nodes { + name + status + conclusion + detailsUrl + } + } } } status { diff --git a/test/fixtures/github-ci/check-suite-cancelled.json b/test/fixtures/github-ci/check-suite-cancelled.json new file mode 100644 index 00000000..b42d16d6 --- /dev/null +++ b/test/fixtures/github-ci/check-suite-cancelled.json @@ -0,0 +1,37 @@ +[ + { + "commit": { + "committedDate": "2017-10-26T12:10:20Z", + "oid": "9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d", + "messageHeadline": "doc: add api description README", + "author": { + "login": "foo" + }, + "checkSuites": { + "nodes": [ + { + "app": { "slug": "github-actions" }, + "status": "COMPLETED", + "conclusion": "CANCELLED", + "checkRuns": { + "nodes": [ + { + "name": "test-linux", + "status": "COMPLETED", + "conclusion": "CANCELLED", + "detailsUrl": "https://github.com/nodejs/node/runs/12345" + }, + { + "name": "lint", + "status": "COMPLETED", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/nodejs/node/runs/12346" + } + ] + } + } + ] + } + } + } +] diff --git a/test/fixtures/github-ci/check-suite-failure.json b/test/fixtures/github-ci/check-suite-failure.json index b299e1e7..d07172f0 100644 --- a/test/fixtures/github-ci/check-suite-failure.json +++ b/test/fixtures/github-ci/check-suite-failure.json @@ -12,7 +12,23 @@ { "app": { "slug": "github-actions" }, "status": "COMPLETED", - "conclusion": "FAILURE" + "conclusion": "FAILURE", + "checkRuns": { + "nodes": [ + { + "name": "test-linux", + "status": "COMPLETED", + "conclusion": "FAILURE", + "detailsUrl": "https://github.com/nodejs/node/runs/12345" + }, + { + "name": "test-macos", + "status": "COMPLETED", + "conclusion": "SUCCESS", + "detailsUrl": "https://github.com/nodejs/node/runs/12346" + } + ] + } } ] } diff --git a/test/unit/pr_checker.test.js b/test/unit/pr_checker.test.js index 4542e194..34827e2b 100644 --- a/test/unit/pr_checker.test.js +++ b/test/unit/pr_checker.test.js @@ -1304,7 +1304,8 @@ describe('PRChecker', () => { ['Last Jenkins CI successful'] ], error: [ - ['Last GitHub CI failed'] + ['1 GitHub CI job(s) failed:'], + [' - test-linux: FAILURE (https://github.com/nodejs/node/runs/12345)'] ], info: [ [`Last Full PR CI on 2018-10-22T04:16:36.458Z: ${jenkins.url}`] @@ -1711,7 +1712,8 @@ describe('PRChecker', () => { const expectedLogs = { error: [ - ['Last GitHub CI failed'] + ['1 GitHub CI job(s) failed:'], + [' - github-actions: FAILURE'] ] }; @@ -1771,7 +1773,8 @@ describe('PRChecker', () => { const expectedLogs = { error: [ - ['Last GitHub CI failed'] + ['1 GitHub CI job(s) failed:'], + [' - test-linux: FAILURE (https://github.com/nodejs/node/runs/12345)'] ] }; @@ -1828,7 +1831,7 @@ describe('PRChecker', () => { const expectedLogs = { error: [ - ['Last GitHub CI failed'] + ['GitHub CI failed with status: FAILURE'] ] }; @@ -1904,7 +1907,7 @@ describe('PRChecker', () => { const expectedLogs = { error: [ - ['Last GitHub CI failed'] + ['GitHub CI failed with status: FAILURE'] ] }; @@ -1923,7 +1926,8 @@ describe('PRChecker', () => { const expectedLogs = { error: [ - ['Last GitHub CI failed'] + ['1 GitHub CI job(s) failed:'], + [' - github-actions: FAILURE'] ] }; @@ -1974,6 +1978,297 @@ describe('PRChecker', () => { assert(status); cli.assertCalledWith(expectedLogs); }); + + it('should error if Check suite cancelled', async() => { + const cli = new TestCLI(); + + const expectedLogs = { + error: [ + ['1 GitHub CI job(s) cancelled:'], + [' - test-linux: CANCELLED (https://github.com/nodejs/node/runs/12345)'] + ] + }; + + const commits = githubCI['check-suite-cancelled']; + const data = Object.assign({}, baseData, { commits }); + + const checker = new PRChecker(cli, data, {}, testArgv); + + const status = await checker.checkCI(); + assert(!status); + cli.assertCalledWith(expectedLogs); + }); + + it('should handle multiple failed jobs with detailed output', async() => { + const cli = new TestCLI(); + + const multipleFailures = [{ + commit: { + committedDate: '2017-10-26T12:10:20Z', + oid: '9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d', + messageHeadline: 'doc: add api description README', + author: { login: 'foo' }, + checkSuites: { + nodes: [{ + app: { slug: 'github-actions' }, + status: 'COMPLETED', + conclusion: 'FAILURE', + checkRuns: { + nodes: [ + { + name: 'test-linux', + status: 'COMPLETED', + conclusion: 'FAILURE', + detailsUrl: 'https://github.com/nodejs/node/runs/1' + }, + { + name: 'test-windows', + status: 'COMPLETED', + conclusion: 'FAILURE', + detailsUrl: 'https://github.com/nodejs/node/runs/2' + }, + { + name: 'lint', + status: 'COMPLETED', + conclusion: 'SUCCESS', + detailsUrl: 'https://github.com/nodejs/node/runs/3' + } + ] + } + }] + } + } + }]; + + const expectedLogs = { + error: [ + ['2 GitHub CI job(s) failed:'], + [' - test-linux: FAILURE (https://github.com/nodejs/node/runs/1)'], + [' - test-windows: FAILURE (https://github.com/nodejs/node/runs/2)'] + ] + }; + + const data = Object.assign({}, baseData, { commits: multipleFailures }); + const checker = new PRChecker(cli, data, {}, testArgv); + + const status = await checker.checkCI(); + assert(!status); + cli.assertCalledWith(expectedLogs); + }); + + it('should handle mixed failed and cancelled jobs', async() => { + const cli = new TestCLI(); + + const mixedResults = [{ + commit: { + committedDate: '2017-10-26T12:10:20Z', + oid: '9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d', + messageHeadline: 'doc: add api description README', + author: { login: 'foo' }, + checkSuites: { + nodes: [{ + app: { slug: 'github-actions' }, + status: 'COMPLETED', + conclusion: 'FAILURE', + checkRuns: { + nodes: [ + { + name: 'test-linux', + status: 'COMPLETED', + conclusion: 'FAILURE', + detailsUrl: 'https://github.com/nodejs/node/runs/1' + }, + { + name: 'test-macos', + status: 'COMPLETED', + conclusion: 'CANCELLED', + detailsUrl: 'https://github.com/nodejs/node/runs/2' + } + ] + } + }] + } + } + }]; + + const expectedLogs = { + error: [ + ['1 GitHub CI job(s) failed:'], + [' - test-linux: FAILURE (https://github.com/nodejs/node/runs/1)'], + ['1 GitHub CI job(s) cancelled:'], + [' - test-macos: CANCELLED (https://github.com/nodejs/node/runs/2)'] + ] + }; + + const data = Object.assign({}, baseData, { commits: mixedResults }); + const checker = new PRChecker(cli, data, {}, testArgv); + + const status = await checker.checkCI(); + assert(!status); + cli.assertCalledWith(expectedLogs); + }); + + it('should fallback to checkSuite level when no checkRuns available', async() => { + const cli = new TestCLI(); + + const noCheckRuns = [{ + commit: { + committedDate: '2017-10-26T12:10:20Z', + oid: '9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d', + messageHeadline: 'doc: add api description README', + author: { login: 'foo' }, + checkSuites: { + nodes: [{ + app: { slug: 'github-actions' }, + status: 'COMPLETED', + conclusion: 'CANCELLED' + // No checkRuns field + }] + } + } + }]; + + const expectedLogs = { + error: [ + ['1 GitHub CI job(s) cancelled:'], + [' - github-actions: CANCELLED'] + ] + }; + + const data = Object.assign({}, baseData, { commits: noCheckRuns }); + const checker = new PRChecker(cli, data, {}, testArgv); + + const status = await checker.checkCI(); + assert(!status); + cli.assertCalledWith(expectedLogs); + }); + + it('should handle empty checkRuns array', async() => { + const cli = new TestCLI(); + + const emptyCheckRuns = [{ + commit: { + committedDate: '2017-10-26T12:10:20Z', + oid: '9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d', + messageHeadline: 'doc: add api description README', + author: { login: 'foo' }, + checkSuites: { + nodes: [{ + app: { slug: 'github-actions' }, + status: 'COMPLETED', + conclusion: 'FAILURE', + checkRuns: { nodes: [] } + }] + } + } + }]; + + const expectedLogs = { + error: [ + ['1 GitHub CI job(s) failed:'], + [' - github-actions: FAILURE'] + ] + }; + + const data = Object.assign({}, baseData, { commits: emptyCheckRuns }); + const checker = new PRChecker(cli, data, {}, testArgv); + + const status = await checker.checkCI(); + assert(!status); + cli.assertCalledWith(expectedLogs); + }); + + it('should handle jobs without URLs', async() => { + const cli = new TestCLI(); + + const noUrlJobs = [{ + commit: { + committedDate: '2017-10-26T12:10:20Z', + oid: '9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d', + messageHeadline: 'doc: add api description README', + author: { login: 'foo' }, + checkSuites: { + nodes: [{ + app: { slug: 'github-actions' }, + status: 'COMPLETED', + conclusion: 'FAILURE', + checkRuns: { + nodes: [{ + name: 'test-linux', + status: 'COMPLETED', + conclusion: 'FAILURE' + // No detailsUrl field + }] + } + }] + } + } + }]; + + const expectedLogs = { + error: [ + ['1 GitHub CI job(s) failed:'], + [' - test-linux: FAILURE'] + ] + }; + + const data = Object.assign({}, baseData, { commits: noUrlJobs }); + const checker = new PRChecker(cli, data, {}, testArgv); + + const status = await checker.checkCI(); + assert(!status); + cli.assertCalledWith(expectedLogs); + }); + + it('should ignore non-completed checkRuns when processing failures', async() => { + const cli = new TestCLI(); + + const mixedStatusJobs = [{ + commit: { + committedDate: '2017-10-26T12:10:20Z', + oid: '9d098ssiskj8dhd39js0sjd0cn2ng4is9n40sj12d', + messageHeadline: 'doc: add api description README', + author: { login: 'foo' }, + checkSuites: { + nodes: [{ + app: { slug: 'github-actions' }, + status: 'COMPLETED', + conclusion: 'FAILURE', + checkRuns: { + nodes: [ + { + name: 'test-linux', + status: 'COMPLETED', + conclusion: 'FAILURE', + detailsUrl: 'https://github.com/nodejs/node/runs/1' + }, + { + name: 'test-pending', + status: 'IN_PROGRESS', + conclusion: null, + detailsUrl: 'https://github.com/nodejs/node/runs/2' + } + ] + } + }] + } + } + }]; + + const expectedLogs = { + error: [ + ['1 GitHub CI job(s) failed:'], + [' - test-linux: FAILURE (https://github.com/nodejs/node/runs/1)'] + ] + }; + + const data = Object.assign({}, baseData, { commits: mixedStatusJobs }); + const checker = new PRChecker(cli, data, {}, testArgv); + + const status = await checker.checkCI(); + assert(!status); + cli.assertCalledWith(expectedLogs); + }); }); describe('checkAuthor', () => { From 63171d7553ced640393476346d28a82fd9e4ccce Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 4 Feb 2026 16:57:34 +0100 Subject: [PATCH 03/13] chore: optimize the Conventional Commit Linter workflow (#1031) --- .github/workflows/commitlint.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 64af26e3..b5d9f922 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -6,11 +6,24 @@ on: - main pull_request: +permissions: + contents: read + jobs: commitlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - name: Compute number of commits to fetch + id: nb-of-commits + # `+ 1` for PRs because of the merge commit + run: | + echo "toParse=$(echo "$EVENT" | jq -r 'if .commits then (.commits | length) else (.pull_request.commits + 1) end')" >> $GITHUB_OUTPUT + env: + EVENT: ${{ toJSON(github.event) }} + - name: Checkout + uses: actions/checkout@v6 with: - fetch-depth: 100 + persist-credentials: false + sparse-checkout: . + fetch-depth: ${{ steps.nb-of-commits.outputs.toParse }} - uses: wagoid/commitlint-github-action@v6 From 21fe4732ba20cf57332341941de448a93d107319 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 13 Mar 2026 14:47:07 +0100 Subject: [PATCH 04/13] fix(git-node): use stash and detached head for release operations (#1033) --- components/git/release.js | 20 ++++++++++++++++++-- lib/promote_release.js | 10 ++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/components/git/release.js b/components/git/release.js index 94fa7f66..3678dd54 100644 --- a/components/git/release.js +++ b/components/git/release.js @@ -4,7 +4,7 @@ import ReleasePreparation from '../../lib/prepare_release.js'; import ReleasePromotion from '../../lib/promote_release.js'; import TeamInfo from '../../lib/team_info.js'; import Request from '../../lib/request.js'; -import { runPromise } from '../../lib/run.js'; +import { forceRunAsync, runPromise } from '../../lib/run.js'; export const command = 'release [prid..]'; export const describe = 'Manage an in-progress release or start a new one.'; @@ -114,7 +114,7 @@ function release(state, argv) { cli.setAssumeYes(); } - return runPromise(main(state, argv, cli, dir)).catch((err) => { + return runPromise(wrapStash(() => main(state, argv, cli, dir))).catch((err) => { if (cli.spinner.enabled) { cli.spinner.fail(); } @@ -122,6 +122,22 @@ function release(state, argv) { }); } +async function wrapStash(fn) { + const stashTip = await forceRunAsync('git', ['stash', 'list', '-1', '--format="%gd"'], + { ignoreFailure: false, captureStdout: true }); + await forceRunAsync('git', ['stash', '--include-untracked'], { ignoreFailure: false }); + const newStashTip = await forceRunAsync('git', ['stash', 'list', '-1', '--format="%gd"'], + { ignoreFailure: false, captureStdout: true }); + const hasStashed = newStashTip !== stashTip && newStashTip.trim(); + try { + await fn(); + } finally { + if (hasStashed) { + await forceRunAsync('git', ['stash', 'pop'], { ignoreFailure: false }); + } + } +} + async function main(state, argv, cli, dir) { if (state === PREPARE) { const release = new ReleasePreparation(argv, cli, dir); diff --git a/lib/promote_release.js b/lib/promote_release.js index bdddacbb..0d90cb53 100644 --- a/lib/promote_release.js +++ b/lib/promote_release.js @@ -56,18 +56,12 @@ export default class ReleasePromotion extends Session { cli.warn('Current HEAD is not the release commit'); localCloneIsClean = false; } - try { - await forceRunAsync('git', ['--no-pager', 'diff', '--exit-code'], { ignoreFailure: false }); - } catch { - cli.warn('Some local changes have not been committed'); - localCloneIsClean = false; - } if (!localCloneIsClean) { - if (await cli.prompt('Should we reset the local HEAD to be the release proposal?')) { + if (await cli.prompt('Should we checkout the release proposal?')) { cli.startSpinner('Fetching the proposal upstream...'); await forceRunAsync('git', ['fetch', proposalUpstreamRemote, releaseCommitSha], { ignoreFailure: false }); - await forceRunAsync('git', ['reset', releaseCommitSha, '--hard'], { ignoreFailure: false }); + await forceRunAsync('git', ['checkout', releaseCommitSha], { ignoreFailure: false }); cli.stopSpinner('Local HEAD is now in sync with the proposal'); } else { cli.error('Local clone is not ready'); From 45861633306db130a587174d6abda676694f1447 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 13 Mar 2026 15:28:03 +0100 Subject: [PATCH 05/13] fix(git-node): do not enforce minimum wait time for release proposals (#1032) --- lib/pr_checker.js | 16 +++++++++++----- lib/promote_release.js | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/pr_checker.js b/lib/pr_checker.js index e48170ac..d722b607 100644 --- a/lib/pr_checker.js +++ b/lib/pr_checker.js @@ -128,20 +128,26 @@ export default class PRChecker { } } - checkReviewsAndWait(now, checkComments) { + checkReviewsAndWait(now, checkComments, isReleaseProposal) { const { pr, cli, reviewers } = this; const { requestedChanges, approved } = reviewers; + + const dateStr = new Date(pr.createdAt).toUTCString(); + cli.info(`This PR was created on ${dateStr}`); + this.displayReviews(checkComments); + + if (isReleaseProposal) { + cli.info('This PR is a release proposal'); + return approved.length !== 0; + } + const labels = pr.labels.nodes.map((l) => l.name); let isFastTracked = labels.includes('fast-track'); const isCodeAndLearn = labels.includes('code-and-learn'); const isSemverMajor = labels.includes('semver-major'); - - const dateStr = new Date(pr.createdAt).toUTCString(); - cli.info(`This PR was created on ${dateStr}`); - this.displayReviews(checkComments); // NOTE: a semver-major PR with fast-track should have either one of // these labels removed because that doesn't make sense if (isFastTracked) { diff --git a/lib/promote_release.js b/lib/promote_release.js index 0d90cb53..14585586 100644 --- a/lib/promote_release.js +++ b/lib/promote_release.js @@ -242,7 +242,7 @@ export default class ReleasePromotion extends Session { const checker = new PRChecker(cli, data, { prid, owner, repo }, { maxCommits: 0 }); const jenkinsReady = checker.checkJenkinsCI(); const githubCIReady = checker.checkGitHubCI(); - const isApproved = checker.checkReviewsAndWait(new Date(), false); + const isApproved = checker.checkReviewsAndWait(new Date(), false, true); return { githubCIReady, From 7b8686072ce6628ddca80d32913555ba1f7d54bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 22:39:45 +0100 Subject: [PATCH 06/13] chore(deps): bump semver from 7.7.2 to 7.7.3 (#1019) Bumps [semver](https://github.com/npm/node-semver) from 7.7.2 to 7.7.3. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.7.2...v7.7.3) --- updated-dependencies: - dependency-name: semver dependency-version: 7.7.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- npm-shrinkwrap.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index c87ddde7..872514fb 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -9898,9 +9898,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" From 48276fe763b5fd115f04e81d874ef1782fb46e6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 22:40:35 +0100 Subject: [PATCH 07/13] chore(deps): bump ghauth from 6.0.13 to 6.0.19 (#1021) Bumps [ghauth](https://github.com/rvagg/ghauth) from 6.0.13 to 6.0.19. - [Release notes](https://github.com/rvagg/ghauth/releases) - [Changelog](https://github.com/rvagg/ghauth/blob/master/CHANGELOG.md) - [Commits](https://github.com/rvagg/ghauth/compare/v6.0.13...v6.0.19) --- updated-dependencies: - dependency-name: ghauth dependency-version: 6.0.19 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- npm-shrinkwrap.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 872514fb..7a2780f1 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -4683,9 +4683,9 @@ } }, "node_modules/ghauth": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/ghauth/-/ghauth-6.0.13.tgz", - "integrity": "sha512-wdeDPCl3RBSoYEhZ4J/PXK7/b1xYQj1zKgWx9QyUEo0ZGvwFiwe8HWMkpbtuDgo6kwaRUYw7izV7LtO233J5iw==", + "version": "6.0.19", + "resolved": "https://registry.npmjs.org/ghauth/-/ghauth-6.0.19.tgz", + "integrity": "sha512-eiZtW8EyJjk++Gs8vdY1/gJccbaPl3cH40z9VikfvBou5dkI4L/m9bbauLiGnQ6SdYhu0wT4DlDuoRpUMwbyIg==", "license": "MIT", "dependencies": { "application-config": "^2.0.0", From 4df0f5436257c400972fa877b6e0549362c29269 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 22:41:22 +0100 Subject: [PATCH 08/13] chore(deps-dev): bump eslint from 9.39.0 to 9.39.2 (#1020) Bumps [eslint](https://github.com/eslint/eslint) from 9.39.0 to 9.39.2. - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v9.39.0...v9.39.2) --- updated-dependencies: - dependency-name: eslint dependency-version: 9.39.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- npm-shrinkwrap.json | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 7a2780f1..6044670c 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -296,9 +296,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", - "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { @@ -3757,9 +3757,9 @@ } }, "node_modules/eslint": { - "version": "9.39.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.0.tgz", - "integrity": "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", "dependencies": { @@ -3769,7 +3769,7 @@ "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.0", + "@eslint/js": "9.39.2", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -4222,19 +4222,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "9.39.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.0.tgz", - "integrity": "sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", From 2ea7b22724c3c507c5ed9a790ee278b66d99dcf0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 22:41:52 +0100 Subject: [PATCH 09/13] chore(deps-dev): bump @eslint/js from 9.39.1 to 9.39.2 (#1017) Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.39.1 to 9.39.2. - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/commits/v9.39.2/packages/js) --- updated-dependencies: - dependency-name: "@eslint/js" dependency-version: 9.39.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 7520eb9cc14c1fea783729de7cdd927303fa827a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 19:57:59 +0100 Subject: [PATCH 10/13] chore(deps): bump clipboardy from 4.0.0 to 5.0.2 (#1018) Bumps [clipboardy](https://github.com/sindresorhus/clipboardy) from 4.0.0 to 5.0.2. - [Release notes](https://github.com/sindresorhus/clipboardy/releases) - [Commits](https://github.com/sindresorhus/clipboardy/compare/v4.0.0...v5.0.2) --- updated-dependencies: - dependency-name: clipboardy dependency-version: 5.0.2 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- npm-shrinkwrap.json | 189 +++++++++++++++++++++++++++----------------- package.json | 2 +- 2 files changed, 118 insertions(+), 73 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 6044670c..78b4c761 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -17,7 +17,7 @@ "chalk": "^5.4.1", "changelog-maker": "^4.4.1", "cheerio": "^1.0.0", - "clipboardy": "^4.0.0", + "clipboardy": "^5.0.2", "core-validate-commit": "^4.1.0", "figures": "^6.1.0", "ghauth": "^6.0.12", @@ -1209,6 +1209,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "license": "MIT" + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -1221,6 +1227,18 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -2867,17 +2885,18 @@ } }, "node_modules/clipboardy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-4.0.0.tgz", - "integrity": "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-5.0.2.tgz", + "integrity": "sha512-3IG8i8Yfb410yqDlCx9Ve3lYLFN3bD1IkrWcowT1kyTo6y4bwYf2guK9Q8a6zck5vWm7afm6Y61i7BG/Ir3FMA==", "license": "MIT", "dependencies": { - "execa": "^8.0.1", + "execa": "^9.6.0", + "is-wayland": "^0.1.0", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4326,23 +4345,26 @@ "license": "MIT" }, "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", + "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==", "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" }, "engines": { - "node": ">=16.17" + "node": "^18.19.0 || >=20.5.0" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" @@ -4627,12 +4649,16 @@ } }, "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5384,12 +5410,12 @@ } }, "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", "license": "Apache-2.0", "engines": { - "node": ">=16.17.0" + "node": ">=18.18.0" } }, "node_modules/hyperquest": { @@ -5984,12 +6010,12 @@ } }, "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6070,6 +6096,18 @@ "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", "license": "MIT" }, + "node_modules/is-wayland": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-wayland/-/is-wayland-0.1.0.tgz", + "integrity": "sha512-QkbMsWkIfkrzOPxenwye0h56iAXirZYHG9eHVPb22fO9y+wPbaX/CHacOWBa/I++4ohTcByimhM1/nyCsH8KNA==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -6944,12 +6982,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7537,18 +7569,6 @@ "node": ">=8.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mimic-function": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", @@ -7730,15 +7750,16 @@ } }, "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7909,21 +7930,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -8126,6 +8132,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse5": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", @@ -8324,6 +8342,21 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -10470,12 +10503,12 @@ } }, "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10931,6 +10964,18 @@ "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", diff --git a/package.json b/package.json index bfb003de..319c0751 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "chalk": "^5.4.1", "changelog-maker": "^4.4.1", "cheerio": "^1.0.0", - "clipboardy": "^4.0.0", + "clipboardy": "^5.0.2", "core-validate-commit": "^4.1.0", "figures": "^6.1.0", "ghauth": "^6.0.12", From cc7645fa3d24f4dc941c40004231848241d8dfc6 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Tue, 17 Mar 2026 14:36:00 -0300 Subject: [PATCH 11/13] fix: improve --request-cve (#1037) --- lib/update_security_release.js | 97 ++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/lib/update_security_release.js b/lib/update_security_release.js index df636d75..8125e648 100644 --- a/lib/update_security_release.js +++ b/lib/update_security_release.js @@ -141,46 +141,55 @@ export default class UpdateSecurityRelease extends SecurityRelease { const vulnerabilitiesJSONPath = this.getVulnerabilitiesJSONPath(); const content = this.readVulnerabilitiesJSON(vulnerabilitiesJSONPath); const { reports } = content; + this.validateReportsForCVE(reports); const req = new Request(credentials); const programId = await this.getNodeProgramId(req); - const cves = await this.promptCVECreation(req, reports, programId); - this.assignCVEtoReport(cves, reports); - this.updateVulnerabilitiesJSON(content); - this.updateHackonerReportCve(req, reports); + await this.promptCVECreation(req, reports, programId, content); } - assignCVEtoReport(cves, reports) { - for (const cve of cves) { - const report = reports.find(report => report.id === cve.reportId); - report.cveIds = [cve.cve_identifier]; - report.patchedVersions = cve.patchedVersions; + validateReportsForCVE(reports) { + const invalid = []; + for (const report of reports) { + if (report.cveIds?.length) continue; + const missing = []; + if (!report.summary) missing.push('description'); + if (!report.severity?.weakness_id) missing.push('weakness_id'); + if (!report.severity?.cvss_vector_string) missing.push('cvss_vector_string'); + if (missing.length) { + invalid.push({ id: report.id, missing }); + } + } + if (invalid.length) { + for (const { id, missing } of invalid) { + this.cli.error(`Report ${id} is missing: ${missing.join(', ')}`); + } + throw new Error('Some reports are missing required fields for CVE request. ' + + 'Run `git node security --sync` to update them.'); } } - async updateHackonerReportCve(req, reports) { - for (const report of reports) { - const { id, cveIds } = report; - this.cli.startSpinner(`Updating report ${id} with CVEs ${cveIds}..`); - const body = { - data: { - type: 'report-cves', - attributes: { - cve_ids: cveIds - } + async updateHackonerReportCve(req, report) { + const { id, cveIds } = report; + this.cli.startSpinner(`Updating report ${id} with CVEs ${cveIds}..`); + const body = { + data: { + type: 'report-cves', + attributes: { + cve_ids: cveIds } - }; - const response = await req.updateReportCVE(id, body); - if (response.errors) { - this.cli.error(`Error updating report ${id}`); - this.cli.error(JSON.stringify(response.errors, null, 2)); } - this.cli.stopSpinner(`Done updating report ${id} with CVEs ${cveIds}..`); + }; + const response = await req.updateReportCVE(id, body); + if (response.errors) { + this.cli.error(`Error updating report ${id}`); + this.cli.error(JSON.stringify(response.errors, null, 2)); } + this.cli.stopSpinner(`Done updating report ${id} with CVEs ${cveIds}..`); } - async promptCVECreation(req, reports, programId) { + async promptCVECreation(req, reports, programId, content) { const supportedVersions = (await nv('supported')); - const cves = []; + const eolVersions = (await nv('eol')); for (const report of reports) { const { id, summary, title, affectedVersions, cveIds, link } = report; // skip if already has a CVE @@ -222,7 +231,7 @@ Summary: ${summary}\n`, if (!create) continue; const { h1AffectedVersions, patchedVersions } = - await this.calculateVersions(affectedVersions, supportedVersions); + await this.calculateVersions(affectedVersions, supportedVersions, eolVersions); const body = { data: { type: 'cve-request', @@ -243,16 +252,18 @@ Summary: ${summary}\n`, } } }; - const { data } = await req.requestCVE(programId, body); - if (data.errors) { + const response = await req.requestCVE(programId, body); + if (response.errors) { this.cli.error(`Error requesting CVE for report ${id}`); - this.cli.error(JSON.stringify(data.errors, null, 2)); + this.cli.error(JSON.stringify(response.errors, null, 2)); continue; } - const { cve_identifier } = data.attributes; - cves.push({ cve_identifier, reportId: id, patchedVersions }); + const { cve_identifier } = response.data.attributes; + report.cveIds = [cve_identifier]; + report.patchedVersions = patchedVersions; + this.updateVulnerabilitiesJSON(content); + await this.updateHackonerReportCve(req, report); } - return cves; } async getNodeProgramId(req) { @@ -266,7 +277,7 @@ Summary: ${summary}\n`, } } - async calculateVersions(affectedVersions, supportedVersions) { + async calculateVersions(affectedVersions, supportedVersions, eolVersions) { const h1AffectedVersions = []; const patchedVersions = []; let isPatchRelease = true; @@ -300,6 +311,22 @@ Summary: ${summary}\n`, affected: true }); } + + // All EOL versions are affected since they no longer receive security patches + for (const eolVersion of eolVersions) { + const version = semver.valid(eolVersion.version); + if (version) { + h1AffectedVersions.push({ + vendor: 'nodejs', + product: 'node', + func: '<=', + version, + versionType: 'semver', + affected: true + }); + } + } + return { h1AffectedVersions, patchedVersions }; } } From b6ef8b543191bc5e0e8ae6b7c0d693670affecf0 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 18 Mar 2026 08:24:08 +0100 Subject: [PATCH 12/13] fix: ensure all webcrypto idls are downloaded --- components/git/wpt.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/git/wpt.js b/components/git/wpt.js index b3ab6945..d65b0f26 100644 --- a/components/git/wpt.js +++ b/components/git/wpt.js @@ -48,7 +48,9 @@ async function main(argv) { let supported = [ 'dom', 'html', - 'webcrypto' + 'webcrypto', + 'webcrypto-secure-curves', + 'webcrypto-modern-algos', ]; if (fs.existsSync(statusFolder)) { const jsons = fs.readdirSync(statusFolder); From 478250b2c430fa2c578e378b641e83f724d1f167 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Wed, 18 Mar 2026 04:16:42 -0400 Subject: [PATCH 13/13] chore(main): release 6.2.0 --- CHANGELOG.md | 16 ++++++++++++++++ npm-shrinkwrap.json | 4 ++-- package.json | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3342719b..9a4a2b55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [6.2.0](https://github.com/nodejs/node-core-utils/compare/v6.1.1...v6.2.0) (2026-03-18) + + +### Features + +* add list detail of failed GHA jobs ([#960](https://github.com/nodejs/node-core-utils/issues/960)) ([19b468a](https://github.com/nodejs/node-core-utils/commit/19b468ad088a8200eabdc94a96f58a6027e2fc11)) + + +### Bug Fixes + +* ensure all webcrypto idls are downloaded ([b6ef8b5](https://github.com/nodejs/node-core-utils/commit/b6ef8b543191bc5e0e8ae6b7c0d693670affecf0)) +* **git-node:** do not enforce minimum wait time for release proposals ([#1032](https://github.com/nodejs/node-core-utils/issues/1032)) ([4586163](https://github.com/nodejs/node-core-utils/commit/45861633306db130a587174d6abda676694f1447)) +* **git-node:** promoting a release using only PR number ([#1028](https://github.com/nodejs/node-core-utils/issues/1028)) ([37604ef](https://github.com/nodejs/node-core-utils/commit/37604ef61465a614f2a645e170db57d6a041eb34)) +* **git-node:** use stash and detached head for release operations ([#1033](https://github.com/nodejs/node-core-utils/issues/1033)) ([21fe473](https://github.com/nodejs/node-core-utils/commit/21fe4732ba20cf57332341941de448a93d107319)) +* improve --request-cve ([#1037](https://github.com/nodejs/node-core-utils/issues/1037)) ([cc7645f](https://github.com/nodejs/node-core-utils/commit/cc7645fa3d24f4dc941c40004231848241d8dfc6)) + ## [6.1.1](https://github.com/nodejs/node-core-utils/compare/v6.1.0...v6.1.1) (2026-01-05) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 78b4c761..6ec1fd42 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,12 +1,12 @@ { "name": "@node-core/utils", - "version": "6.1.1", + "version": "6.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@node-core/utils", - "version": "6.1.1", + "version": "6.2.0", "license": "MIT", "dependencies": { "@inquirer/prompts": "^7.4.1", diff --git a/package.json b/package.json index 319c0751..a3366e8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@node-core/utils", - "version": "6.1.1", + "version": "6.2.0", "description": "Utilities for Node.js core collaborators", "type": "module", "engines": {