Skip to content

Commit 719afce

Browse files
committed
fix(repo): pin internal deps to exact versions in canary/snapshot releases
Why this change was needed: Canary/snapshot releases using `workspace:^` produced dependencies like `^3.0.0-canary.v20251211` which semver interprets as `>=3.0.0-canary <4.0.0`. This incorrectly matched older versions like `3.0.0-snapshot.v20251204`, causing dependency mismatches when installing canary packages. What changed: Added `pinWorkspaceDeps()` that converts `workspace:^` to `workspace:*` for all @clerk/* dependencies before running `changeset version --snapshot`. This ensures published packages use exact versions (no ^ prefix) for internal dependencies while keeping the semver range behavior for stable releases.
1 parent 60f0bf9 commit 719afce

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

scripts/canary.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { $, echo } from 'zx';
44

5-
import { constants, getPackageNames } from './common.mjs';
5+
import { constants, getPackageNames, pinWorkspaceDeps } from './common.mjs';
66

77
const packageNames = await getPackageNames();
88
const packageEntries = packageNames.map(name => `'${name}': patch`).join('\n');
@@ -31,6 +31,10 @@ try {
3131
// in order to force a canary release of all packages
3232
await $`touch .changeset/snap.md && echo ${snapshot} > .changeset/snap.md`;
3333

34+
// Convert workspace:^ to workspace:* for @clerk/* deps to ensure exact versions
35+
// This prevents semver range issues like ^3.0.0-canary matching older snapshots
36+
await pinWorkspaceDeps();
37+
3438
const res = await $`pnpm changeset version --snapshot canary`;
3539
const success = !res.stderr.includes('No unreleased changesets found');
3640

scripts/common.mjs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
import { readFile } from 'fs/promises';
1+
import { readFile, writeFile } from 'fs/promises';
22
import { $ } from 'zx';
33

44
export const constants = {
55
ChangesetConfigFile: '.changeset/config.json',
66
};
77

8+
export async function getPackageJsonFiles() {
9+
const result = await $`find packages -mindepth 2 -maxdepth 2 -name package.json`.quiet();
10+
return result.stdout.trim().split('\n').filter(Boolean);
11+
}
12+
813
export async function getPackageNames() {
9-
const packageJsonFiles = await $`find packages -mindepth 2 -maxdepth 2 -name package.json`.quiet();
14+
const packageJsonFiles = await getPackageJsonFiles();
1015
const packageNames = [];
1116

12-
for (const file of packageJsonFiles.stdout.trim().split('\n').filter(Boolean)) {
17+
for (const file of packageJsonFiles) {
1318
try {
1419
const packageJsonContent = await readFile(file, 'utf-8');
1520
const packageJson = JSON.parse(packageJsonContent);
@@ -23,3 +28,41 @@ export async function getPackageNames() {
2328

2429
return packageNames.sort();
2530
}
31+
32+
/**
33+
* Converts `workspace:^` to `workspace:*` for all @clerk/* dependencies.
34+
* This ensures that snapshot/canary releases use exact versions instead of
35+
* semver ranges, preventing issues like ^3.0.0-canary.v20251211 matching
36+
* older versions like 3.0.0-snapshot.v20251204.
37+
*/
38+
export async function pinWorkspaceDeps() {
39+
const packageJsonFiles = await getPackageJsonFiles();
40+
41+
for (const file of packageJsonFiles) {
42+
try {
43+
const content = await readFile(file, 'utf-8');
44+
const packageJson = JSON.parse(content);
45+
let modified = false;
46+
47+
for (const depType of ['dependencies', 'devDependencies', 'peerDependencies']) {
48+
const deps = packageJson[depType];
49+
if (!deps) {
50+
continue;
51+
}
52+
53+
for (const [name, version] of Object.entries(deps)) {
54+
if (name.startsWith('@clerk/') && version === 'workspace:^') {
55+
deps[name] = 'workspace:*';
56+
modified = true;
57+
}
58+
}
59+
}
60+
61+
if (modified) {
62+
await writeFile(file, JSON.stringify(packageJson, null, 2) + '\n');
63+
}
64+
} catch {
65+
// package.json doesn't exist or is invalid, skip
66+
}
67+
}
68+
}

scripts/snapshot.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { $, argv, echo } from 'zx';
44

5-
import { constants, getPackageNames } from './common.mjs';
5+
import { constants, getPackageNames, pinWorkspaceDeps } from './common.mjs';
66

77
const packageNames = await getPackageNames();
88
const packageEntries = packageNames.map(name => `'${name}': patch`).join('\n');
@@ -33,6 +33,10 @@ try {
3333
// in order to force a snapshot release of all packages
3434
await $`touch .changeset/snap.md && echo ${snapshot} > .changeset/snap.md`;
3535

36+
// Convert workspace:^ to workspace:* for @clerk/* deps to ensure exact versions
37+
// This prevents semver range issues like ^3.0.0-snapshot matching older versions
38+
await pinWorkspaceDeps();
39+
3640
const res = await $`pnpm changeset version --snapshot ${prefix}`;
3741
const success = !res.stderr.includes('No unreleased changesets found');
3842

0 commit comments

Comments
 (0)