Skip to content

Commit e600901

Browse files
authored
chore(ci): Move monorepo to nx (#19325)
- Replace lerna with Nx for all monorepo task execution (`lerna run` → `nx run-many`). Lerna was already using Nx under the hood, so this removes the wrapper layer and uses Nx directly. - Replace `lerna version` with a custom `scripts/bump-version.js` for release version bumping. The script replicates `lerna version --force-publish --exact --no-git-tag-version --no-push` – bumps all workspace package versions and updates internal dependency references to exact versions. Also added some unit tests. - Remove lerna dependency (`lerna.json`, `lerna` devDependency) and add `nx` as a direct devDependency (22.5.0). - Move lockfile stability check to its own CI jo (`job_check_lockfile`) that runs in parallel with the build. - Configure Nx TUI to auto-exit so `yarn build` doesn't hang waiting for ESC. - Adds a `.version.json` as a single source of truth for the current version (this works well with triggering gitflow) - Update docs (`CLAUDE.md`, `CONTRIBUTING.md`, `.cursor/rules`) to reflect the migration. Closes #19340 (added automatically)
1 parent bd59033 commit e600901

52 files changed

Lines changed: 698 additions & 1902 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/rules/sdk_development.mdc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ You are working on the Sentry JavaScript SDK, a critical production SDK used by
2323
- `yarn build:dev` - Development build (transpile + types)
2424
- `yarn build:dev:watch` - Development build in watch mode (recommended)
2525
- `yarn build:dev:filter <package>` - Build specific package and dependencies
26-
- `yarn build:types:watch` - Watch mode for TypeScript types only
2726
- `yarn build:bundle` - Build browser bundles only
2827

2928
### Testing
@@ -59,7 +58,7 @@ This repository uses **Git Flow**. See [docs/gitflow.md](docs/gitflow.md) for de
5958

6059
## Repository Architecture
6160

62-
This is a Lerna monorepo with 40+ packages in the `@sentry/*` namespace.
61+
This is a monorepo with 40+ packages in the `@sentry/*` namespace, managed with Yarn workspaces and Nx.
6362

6463
### Core Packages
6564

@@ -111,7 +110,7 @@ This is a Lerna monorepo with 40+ packages in the `@sentry/*` namespace.
111110

112111
- Uses Rollup for bundling (`rollup.*.config.mjs`)
113112
- TypeScript with multiple tsconfig files per package
114-
- Lerna manages package dependencies and publishing
113+
- Nx orchestrates task execution across packages with caching
115114
- Vite for testing with `vitest`
116115

117116
### Package Structure Pattern

.github/workflows/build.yml

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,16 +307,29 @@ jobs:
307307
uses: ./.github/actions/restore-cache
308308
with:
309309
dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }}
310-
- name: Check for duplicate dependencies in lockfile
311-
# Run `yarn dedupe-deps:fix` locally to resolve any duplicates.
312-
run: yarn dedupe-deps:check
313310
- name: Lint source files
314-
run: yarn lint:lerna
311+
run: yarn lint:eslint
315312
- name: Lint for ES compatibility
316313
run: yarn lint:es-compatibility
317314

315+
job_check_lockfile:
316+
name: Check lockfile
317+
needs: [job_get_metadata]
318+
timeout-minutes: 10
319+
runs-on: ubuntu-24.04
320+
steps:
321+
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
322+
uses: actions/checkout@v6
323+
with:
324+
ref: ${{ env.HEAD_COMMIT }}
325+
- name: Set up Node
326+
uses: actions/setup-node@v6
327+
with:
328+
node-version-file: 'package.json'
318329
- name: Check that yarn.lock is stable
319-
run: yarn && git diff --exit-code yarn.lock
330+
run: yarn install --frozen-lockfile --ignore-engines
331+
- name: Check for duplicate dependencies in lockfile
332+
run: yarn dedupe-deps:check
320333

321334
job_check_format:
322335
name: Check file formatting
@@ -1204,6 +1217,7 @@ jobs:
12041217
job_e2e_tests,
12051218
job_artifacts,
12061219
job_lint,
1220+
job_check_lockfile,
12071221
job_check_format,
12081222
job_circular_dep_check,
12091223
job_size_check,

.github/workflows/gitflow-sync-develop.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ on:
44
branches:
55
- master
66
paths:
7-
# When the version is updated on master (but nothing else)
8-
- 'lerna.json'
7+
# When versions are bumped on master (written by scripts/bump-version.js)
8+
- '.version.json'
99
- '!**/*.js'
1010
- '!**/*.ts'
1111
workflow_dispatch:

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ packages/*/sentry-*.tgz
2424
# logs
2525
yarn-error.log
2626
npm-debug.log
27-
lerna-debug.log
2827
local.log
2928

3029
# ide

.version.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"_comment": "Auto-generated by scripts/bump-version.js. Used by the gitflow sync workflow to detect version bumps. Do not edit manually.",
3+
"version": "10.39.0"
4+
}

CLAUDE.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ You are working on the Sentry JavaScript SDK, a critical production SDK used by
2222
- `yarn build:dev` - Development build (transpile + types)
2323
- `yarn build:dev:watch` - Development build in watch mode (recommended)
2424
- `yarn build:dev:filter <package>` - Build specific package and dependencies
25-
- `yarn build:types:watch` - Watch mode for TypeScript types only
2625
- `yarn build:bundle` - Build browser bundles only
2726

2827
### Testing
@@ -58,7 +57,7 @@ This repository uses **Git Flow**. See [docs/gitflow.md](docs/gitflow.md) for de
5857

5958
## Repository Architecture
6059

61-
This is a Lerna monorepo with 40+ packages in the `@sentry/*` namespace.
60+
This is a monorepo with 40+ packages in the `@sentry/*` namespace, managed with Yarn workspaces and Nx.
6261

6362
### Core Packages
6463

@@ -102,7 +101,7 @@ This is a Lerna monorepo with 40+ packages in the `@sentry/*` namespace.
102101

103102
- Uses Rollup for bundling (`rollup.*.config.mjs`)
104103
- TypeScript with multiple tsconfig files per package
105-
- Lerna manages package dependencies and publishing
104+
- Nx orchestrates task execution across packages with caching
106105
- Vite for testing with `vitest`
107106

108107
### Package Structure Pattern

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ We use [Volta](https://volta.sh/) to ensure we use consistent versions of node,
1919
Make sure to also enable [pnpm support in Volta](https://docs.volta.sh/advanced/pnpm) if you want to run the E2E tests
2020
locally.
2121

22-
`sentry-javascript` is a monorepo containing several packages, and we use `lerna` to manage them. To get started,
22+
`sentry-javascript` is a monorepo containing several packages, managed with Yarn workspaces and Nx. To get started,
2323
install all dependencies, and then perform an initial build, so TypeScript can read all of the linked type definitions.
2424

2525
```

lerna.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

nx.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
"production": ["default", "!{projectRoot}/test/**/*", "!{projectRoot}/**/*.md", "!{projectRoot}/*.tgz"]
1111
},
1212
"targetDefaults": {
13+
"build:dev": {
14+
"dependsOn": ["^build:transpile", "^build:types"]
15+
},
1316
"build:bundle": {
1417
"inputs": ["production", "^production"],
1518
"dependsOn": ["build:transpile"],
@@ -58,5 +61,8 @@
5861
}
5962
},
6063
"$schema": "./node_modules/nx/schemas/nx-schema.json",
61-
"cacheDirectory": ".nxcache"
64+
"cacheDirectory": ".nxcache",
65+
"tui": {
66+
"autoExit": true
67+
}
6268
}

package.json

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,49 @@
11
{
22
"private": true,
33
"scripts": {
4-
"build": "node ./scripts/verify-packages-versions.js && lerna run build:transpile,build:types,build:bundle",
5-
"build:bundle": "lerna run build:bundle",
6-
"build:dev": "lerna run build:types,build:transpile",
7-
"build:dev:filter": "lerna run build:dev --include-filtered-dependencies --include-filtered-dependents --scope",
8-
"build:transpile": "lerna run build:transpile",
9-
"build:types": "lerna run build:types",
10-
"build:watch": "lerna run build:watch",
11-
"build:dev:watch": "lerna run build:dev:watch",
12-
"build:types:watch": "ts-node scripts/build-types-watch.ts",
4+
"build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle",
5+
"build:bundle": "nx run-many -t build:bundle",
6+
"build:dev": "nx run-many -t build:types build:transpile",
7+
"build:dev:filter": "nx run-many -t build:dev -p",
8+
"build:transpile": "nx run-many -t build:transpile",
9+
"build:types": "nx run-many -t build:types",
10+
"build:watch": "nx run-many -t build:watch",
11+
"build:dev:watch": "nx run-many -t build:dev:watch",
1312
"build:tarball": "run-s clean:tarballs build:tarballs",
14-
"build:tarballs": "lerna run build:tarball",
13+
"build:tarballs": "nx run-many -t build:tarball",
1514
"changelog": "ts-node ./scripts/get-commit-list.ts",
1615
"generate-changelog": "ts-node ./scripts/generate-changelog.ts",
17-
"circularDepCheck": "lerna run circularDepCheck",
16+
"circularDepCheck": "nx run-many -t circularDepCheck",
1817
"clean": "run-s clean:build clean:caches",
19-
"clean:build": "lerna run clean",
18+
"clean:build": "nx run-many -t clean",
2019
"clean:caches": "yarn rimraf eslintcache .nxcache .nx",
21-
"clean:deps": "lerna clean --yes && rm -rf node_modules && yarn",
20+
"clean:deps": "rimraf packages/*/node_modules dev-packages/*/node_modules && rm -rf node_modules && yarn",
2221
"clean:tarballs": "rimraf {packages,dev-packages}/*/*.tgz",
2322
"clean:watchman": "watchman watch-del \".\"",
2423
"clean:all": "run-s clean:build clean:tarballs clean:caches clean:deps clean:watchman",
25-
"fix": "run-s fix:oxfmt fix:lerna",
26-
"fix:lerna": "lerna run fix",
24+
"fix": "run-s fix:oxfmt fix:eslint",
25+
"fix:eslint": "nx run-many -t fix",
2726
"fix:oxfmt": "oxfmt . --write",
2827
"format:check": "oxfmt . --check",
2928
"format": "oxfmt . --write",
30-
"lint": "run-s lint:oxfmt lint:lerna",
31-
"lint:lerna": "lerna run lint",
29+
"lint": "run-s lint:oxfmt lint:eslint",
30+
"lint:eslint": "nx run-many -t lint",
3231
"lint:oxfmt": "oxfmt . --check",
33-
"lint:es-compatibility": "lerna run lint:es-compatibility",
32+
"lint:es-compatibility": "nx run-many -t lint:es-compatibility",
3433
"dedupe-deps:check": "yarn-deduplicate yarn.lock --list --fail",
3534
"dedupe-deps:fix": "yarn-deduplicate yarn.lock",
36-
"postpublish": "lerna run --stream --concurrency 1 postpublish",
37-
"test": "lerna run --ignore \"@sentry-internal/{browser-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests}\" test",
38-
"test:unit": "lerna run --ignore \"@sentry-internal/{browser-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests}\" test:unit",
39-
"test:update-snapshots": "lerna run test:update-snapshots",
35+
"postpublish": "nx run-many -t postpublish --parallel=1",
36+
"test": "nx run-many -t test --exclude \"@sentry-internal/{browser-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests}\"",
37+
"test:scripts": "vitest run scripts/bump-version.test.ts",
38+
"test:unit": "nx run-many -t test:unit --exclude \"@sentry-internal/{browser-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests}\"",
39+
"test:update-snapshots": "nx run-many -t test:update-snapshots",
4040
"test:pr": "nx affected -t test --exclude \"@sentry-internal/{browser-integration-tests,e2e-tests,integration-shims,node-integration-tests,node-core-integration-tests,cloudflare-integration-tests}\"",
4141
"test:pr:browser": "UNIT_TEST_ENV=browser ts-node ./scripts/ci-unit-tests.ts --affected",
4242
"test:pr:node": "UNIT_TEST_ENV=node ts-node ./scripts/ci-unit-tests.ts --affected",
4343
"test:ci:browser": "UNIT_TEST_ENV=browser ts-node ./scripts/ci-unit-tests.ts",
4444
"test:ci:node": "UNIT_TEST_ENV=node ts-node ./scripts/ci-unit-tests.ts",
45-
"test:ci:bun": "lerna run test --scope @sentry/bun",
46-
"yalc:publish": "lerna run yalc:publish"
45+
"test:ci:bun": "nx run-many -t test -p @sentry/bun",
46+
"yalc:publish": "nx run-many -t yalc:publish"
4747
},
4848
"volta": {
4949
"node": "20.19.2",
@@ -127,7 +127,7 @@
127127
"es-check": "^7.2.1",
128128
"eslint": "8.57.0",
129129
"jsdom": "^21.1.2",
130-
"lerna": "8.2.4",
130+
"nx": "22.5.0",
131131
"madge": "8.0.0",
132132
"nodemon": "^3.1.10",
133133
"npm-run-all2": "^6.2.0",
@@ -146,8 +146,7 @@
146146
},
147147
"//_resolutions_comment": [
148148
"Because new versions of strip-ansi, string-width, and wrap-ansi are ESM only packages,",
149-
"we need to resolve them to the CommonJS versions.",
150-
"This is a temporary solution until we can upgrade to a version of lerna that supports ESM packages"
149+
"we need to resolve them to the CommonJS versions."
151150
],
152151
"resolutions": {
153152
"gauge/strip-ansi": "6.0.1",

0 commit comments

Comments
 (0)