From ca254d9596a730c4836b17691ce3139eefaa2234 Mon Sep 17 00:00:00 2001 From: Jacek Date: Tue, 10 Mar 2026 11:52:42 -0500 Subject: [PATCH 1/3] fix(repo): add recovery step for release downstream notifications --- .changeset/release-dispatch-recovery.md | 2 + .github/workflows/release.yml | 75 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 .changeset/release-dispatch-recovery.md diff --git a/.changeset/release-dispatch-recovery.md b/.changeset/release-dispatch-recovery.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/release-dispatch-recovery.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8b5a527b8e0..e73b0ab4de8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -73,6 +73,7 @@ jobs: NPM_CONFIG_PROVENANCE: true - name: Trigger workflows on related repos + id: trigger if: steps.changesets.outputs.published == 'true' uses: actions/github-script@v7 with: @@ -114,6 +115,80 @@ jobs: core.warning("Changeset in pre-mode should not prepare a ClerkJS production release") } + # Recovery: if the changesets action published to npm but then failed + # (e.g. git push --follow-tags error), the `published` output is never + # set and downstream repos are not notified. This step detects that + # scenario by checking npm for the local package version and dispatches + # if the packages are already live. + - name: Recover downstream notifications + if: always() && steps.changesets.conclusion == 'failure' + uses: actions/github-script@v7 + with: + result-encoding: string + retries: 3 + retry-exempt-status-codes: 400,401 + github-token: ${{ secrets.CLERK_COOKIE_PAT }} + script: | + const { execSync } = require('child_process'); + + const clerkjsVersion = require('./packages/clerk-js/package.json').version; + + // Only recover stable releases + if (clerkjsVersion.includes('-')) { + console.log(`Skipping recovery: ${clerkjsVersion} is a pre-release`); + return; + } + + // Check if this version was actually published to npm + let npmVersion; + try { + npmVersion = execSync(`npm view @clerk/clerk-js@${clerkjsVersion} version`, { encoding: 'utf8' }).trim(); + } catch { + console.log(`Version ${clerkjsVersion} not found on npm, no recovery needed`); + return; + } + + if (npmVersion !== clerkjsVersion) { + console.log(`Version mismatch: local=${clerkjsVersion}, npm=${npmVersion}`); + return; + } + + core.warning(`Recovery: @clerk/clerk-js@${clerkjsVersion} was published to npm but downstream repos were not notified. Dispatching now.`); + + const preMode = require("fs").existsSync("./.changeset/pre.json"); + if (preMode) { + core.warning("Changeset in pre-mode, skipping recovery dispatch"); + return; + } + + const clerkUiVersion = require('./packages/ui/package.json').version; + const nextjsVersion = require('./packages/nextjs/package.json').version; + + const dispatches = [ + github.rest.actions.createWorkflowDispatch({ + owner: 'clerk', + repo: 'sdk-infra-workers', + workflow_id: 'update-pkg-versions.yml', + ref: 'main', + inputs: { clerkjsVersion, clerkUiVersion } + }), + github.rest.actions.createWorkflowDispatch({ + owner: 'clerk', + repo: 'dashboard', + workflow_id: 'prepare-nextjs-sdk-update.yml', + ref: 'main', + inputs: { version: nextjsVersion } + }), + github.rest.actions.createWorkflowDispatch({ + owner: 'clerk', + repo: 'clerk-docs', + workflow_id: 'typedoc.yml', + ref: 'main', + }), + ]; + await Promise.all(dispatches); + core.notice('Recovery dispatch completed successfully'); + - name: Generate notification payload id: notification if: steps.changesets.outputs.published == 'true' From 3ceed53b52948c27b51558327f969d4bea28628d Mon Sep 17 00:00:00 2001 From: Jacek Date: Tue, 10 Mar 2026 11:55:34 -0500 Subject: [PATCH 2/3] fix(repo): check both clerk-js and ui versions in recovery step --- .github/workflows/release.yml | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e73b0ab4de8..f572c679cb0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,6 +132,7 @@ jobs: const { execSync } = require('child_process'); const clerkjsVersion = require('./packages/clerk-js/package.json').version; + const clerkUiVersion = require('./packages/ui/package.json').version; // Only recover stable releases if (clerkjsVersion.includes('-')) { @@ -139,21 +140,26 @@ jobs: return; } - // Check if this version was actually published to npm - let npmVersion; - try { - npmVersion = execSync(`npm view @clerk/clerk-js@${clerkjsVersion} version`, { encoding: 'utf8' }).trim(); - } catch { - console.log(`Version ${clerkjsVersion} not found on npm, no recovery needed`); - return; - } + // Check if these versions were actually published to npm + const packagesToCheck = [ + { name: '@clerk/clerk-js', version: clerkjsVersion }, + { name: '@clerk/ui', version: clerkUiVersion }, + ]; - if (npmVersion !== clerkjsVersion) { - console.log(`Version mismatch: local=${clerkjsVersion}, npm=${npmVersion}`); - return; + for (const { name, version } of packagesToCheck) { + try { + const npmVersion = execSync(`npm view ${name}@${version} version`, { encoding: 'utf8' }).trim(); + if (npmVersion !== version) { + console.log(`${name}@${version} not published to npm, no recovery needed`); + return; + } + } catch { + console.log(`${name}@${version} not found on npm, no recovery needed`); + return; + } } - core.warning(`Recovery: @clerk/clerk-js@${clerkjsVersion} was published to npm but downstream repos were not notified. Dispatching now.`); + core.warning(`Recovery: @clerk/clerk-js@${clerkjsVersion} and @clerk/ui@${clerkUiVersion} were published to npm but downstream repos were not notified. Dispatching now.`); const preMode = require("fs").existsSync("./.changeset/pre.json"); if (preMode) { @@ -161,7 +167,6 @@ jobs: return; } - const clerkUiVersion = require('./packages/ui/package.json').version; const nextjsVersion = require('./packages/nextjs/package.json').version; const dispatches = [ From 9a6a63fa9de01e984811caa0ae116d24bb76c47e Mon Sep 17 00:00:00 2001 From: Jacek Date: Tue, 10 Mar 2026 11:56:53 -0500 Subject: [PATCH 3/3] fix(repo): trigger recovery if either clerk-js or ui is published --- .github/workflows/release.yml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f572c679cb0..76568532782 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -140,26 +140,28 @@ jobs: return; } - // Check if these versions were actually published to npm - const packagesToCheck = [ - { name: '@clerk/clerk-js', version: clerkjsVersion }, - { name: '@clerk/ui', version: clerkUiVersion }, - ]; - - for (const { name, version } of packagesToCheck) { + // Check if either version was actually published to npm + function isPublished(name, version) { try { - const npmVersion = execSync(`npm view ${name}@${version} version`, { encoding: 'utf8' }).trim(); - if (npmVersion !== version) { - console.log(`${name}@${version} not published to npm, no recovery needed`); - return; - } + return execSync(`npm view ${name}@${version} version`, { encoding: 'utf8' }).trim() === version; } catch { - console.log(`${name}@${version} not found on npm, no recovery needed`); - return; + return false; } } - core.warning(`Recovery: @clerk/clerk-js@${clerkjsVersion} and @clerk/ui@${clerkUiVersion} were published to npm but downstream repos were not notified. Dispatching now.`); + const clerkjsPublished = isPublished('@clerk/clerk-js', clerkjsVersion); + const clerkUiPublished = isPublished('@clerk/ui', clerkUiVersion); + + if (!clerkjsPublished && !clerkUiPublished) { + console.log('Neither @clerk/clerk-js nor @clerk/ui were published to npm, no recovery needed'); + return; + } + + const published = [ + clerkjsPublished && `@clerk/clerk-js@${clerkjsVersion}`, + clerkUiPublished && `@clerk/ui@${clerkUiVersion}`, + ].filter(Boolean).join(', '); + core.warning(`Recovery: ${published} published to npm but downstream repos were not notified. Dispatching now.`); const preMode = require("fs").existsSync("./.changeset/pre.json"); if (preMode) {