Skip to content

Commit ce665e2

Browse files
authored
ref(build): Run repo-level builds in parallel (#5094)
This parallelizes our repo-level build yarn scripts where possible, in order to make them run a bit faster. In the end, the time savings isn't enormous, but still worthwhile: in a series of 10 time trials on GHA, the old build averaged ~9 minutes, while the new one averaged a bit over 8 minutes. (The time savings isn't that dramatic because the current lack of parallelity at the repo level isn't the biggest driver of our slow build speed; that would be the lack of parallelity at the individual package level, a problem which will be tackled in future PRs. Doing this now will let us take full advantage of that future work.) The over-arching goal here was to make as few tasks as possible have to wait on other tasks. Simply because of computing power, it isn't realistic to run _all_ tasks, for the entire repo, simultaneously. But the closer we can get to maxing out the theoretical potential for infinite parallelization, the better off we'll be, because then the only constraint does become the build runner. In order to accomplish this maximum-possible parallelization, a few things had to be considered: - Is there any interdependency between packages which means that a particular task can't be done in all packages simultaneously? - Is there any interdependency between tasks within a package that means that they can't be done simultaneously? - How do we make sure that at both the repo and package level, `yarn build:dev` builds only what's needed for local development and testing and `yarn build` builds everything? - Is there a way to organize things such that it works for every package, even ones with non-standard build setups? After investigation, it turned out that the key constraints were: - Types can't be built entirely in parallel across packages, because `tsc` checks that imports are being used correctly, which it can't do if types for the packages exporting those imports aren't yet themselves built. - Rollup and bundle builds can happen in parallel across packages, because each individual package's tasks are independent of the same tasks in other packages. Further, type-, rollup-, and bundle-building as overall process are also independent (so, for example, rollup builds don't have to wait on type builds). - Some packages have build tasks in addition to types, rollup, and bundles, and in some cases those tasks can't happen until after the rest of the build completes. - Some packages (angular and ember) have their own build commands, and don't have types, rollup, or bundle builds. To solve these constraints, the build system now follows these principles: - Every build task, in every package, is now represented in its package in exactly one of four scripts: `yarn build:types`, `yarn build:rollup`, `yarn build:bundle`, and a new `yarn build:extras`. Tasks can be parts of other package-level scripts (types and rollup builds together forming each package's `yarn build:dev`, for example), but as long as every task is in one of the canonical four, running those canonical scripts in every package that has them means we're guaranteed not to miss anything. - Types are build using lerna's `--stream` option, now with no limit on concurrency, in order to parallelize where possible without breaking dependency ordering. - Types are built independently of the other three kinds of tasks, since everything else _can_ be fully parallelized. This means not using package-level `yarn build` or `yarn build:dev` commands in the repo-level build, since they tie other build tasks to types build tasks. - To make things as easy as possible to reason about, not just types, but all four task kinds are therefore addressed separately by the repo-level build. - Angular and ember's build tasks are each aliased to a `yarn build:extras` script, so as not to be left out. - Because some "extras" tasks can't be done until types, rollup, and/or bundle tasks are done, make it so all "extras" tasks are held until the other three kinds have finished. This does push a few later than need be, but it's worth it in order to standardize the logic. - All of these principles are duplicated at the package level. For the visual learners among us, there is diagram illustrating this in the PR description. Oh, and while I was in there, I got rid of `yarn build:dev:filter`. It doesn't fit the new system, and no one uses it (not even me, and I made it up).
1 parent fa7e3b7 commit ce665e2

File tree

7 files changed

+20
-8
lines changed

7 files changed

+20
-8
lines changed

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"private": true,
33
"scripts": {
4-
"build": "node ./scripts/verify-packages-versions.js && lerna run --stream --concurrency 1 --sort build",
4+
"build": "node ./scripts/verify-packages-versions.js && yarn run-p build:rollup build:types build:bundle && yarn build:extras",
55
"build:bundle": "lerna run --parallel build:bundle",
6-
"build:dev": "lerna run --stream --concurrency 1 --sort build:dev",
7-
"build:dev:filter": "lerna run --stream --concurrency 1 --sort build:dev --include-filtered-dependencies --include-filtered-dependents --scope",
8-
"build:rollup": "lerna run --stream --concurrency 1 --sort build:rollup",
9-
"build:types": "lerna run --stream --concurrency 1 --sort build:types",
6+
"build:dev": "run-p build:types build:rollup",
7+
"build:extras": "lerna run --parallel build:extras",
8+
"build:rollup": "lerna run --parallel build:rollup",
9+
"build:types": "lerna run --stream build:types",
1010
"build:watch": "lerna run --parallel build:watch",
1111
"build:dev:watch": "lerna run --parallel build:dev:watch",
1212
"build:types:watch": "ts-node scripts/build-types-watch.ts",

packages/angular/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"build": "yarn build:ngc",
4242
"build:ngc": "ng build --prod",
4343
"build:dev": "run-s build",
44+
"build:extras": "yarn build",
4445
"build:watch": "run-p build:ngc:watch",
4546
"build:ngc:watch": "ng build --prod --watch",
4647
"build:npm": "npm pack ./build",

packages/ember/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
},
1919
"scripts": {
2020
"build": "ember build --environment=production",
21+
"build:extras": "yarn build",
2122
"build:npm": "ember ts:precompile && npm pack && ember ts:clean",
2223
"clean": "yarn rimraf sentry-ember-*.tgz",
2324
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",

packages/gatsby/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@
3535
"react": "^18.0.0"
3636
},
3737
"scripts": {
38-
"build": "run-p build:rollup build:types build:plugin",
38+
"build": "run-p build:rollup build:types && yarn build:extras",
3939
"build:dev": "run-s build",
40+
"build:extras": "yarn build:plugin",
4041
"build:plugin": "tsc -p tsconfig.plugin.json",
4142
"build:rollup": "rollup -c rollup.npm.config.js",
4243
"build:types": "tsc -p tsconfig.types.json",

packages/serverless/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@
3838
"read-pkg": "^5.2.0"
3939
},
4040
"scripts": {
41-
"build": "run-p build:rollup build:types && yarn build:awslambda-layer",
41+
"build": "run-p build:rollup build:types && yarn build:extras",
4242
"build:awslambda-layer": "node scripts/build-awslambda-layer.js",
4343
"build:dev": "run-p build:rollup build:types",
44+
"build:extras": "yarn build:awslambda-layer",
4445
"build:rollup": "rollup -c rollup.npm.config.js",
4546
"build:types": "tsc -p tsconfig.types.json",
4647
"build:watch": "run-p build:rollup:watch build:types:watch",

packages/tracing/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
"@types/express": "^4.17.1"
2727
},
2828
"scripts": {
29-
"build": "run-p build:rollup build:types build:bundle && ts-node ../../scripts/prepack.ts --bundles #necessary for integration tests",
29+
"build": "run-p build:rollup build:types build:bundle && yarn build:extras #necessary for integration tests",
3030
"build:bundle": "rollup --config rollup.bundle.config.js",
3131
"build:dev": "run-p build:rollup build:types",
32+
"build:extras": "yarn build:prepack",
33+
"build:prepack": "ts-node ../../scripts/prepack.ts --bundles",
3234
"build:rollup": "rollup -c rollup.npm.config.js",
3335
"build:types": "tsc -p tsconfig.types.json",
3436
"build:watch": "run-p build:rollup:watch build:bundle:watch build:types:watch",

packages/tracing/tsconfig.types.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
{
22
"extends": "./tsconfig.json",
33

4+
// We don't need types for this because we don't ship it in our npm bundle. Skipping it here also lets us get around
5+
// the fact that it introduces a dependency on `@sentry/browser` which doesn't exist anywhere else in the SDK, which
6+
// then prevents us from building that and this at the same time when doing a parallellized build from the repo root
7+
// level.
8+
"exclude": ["src/index.bundle.ts"],
9+
410
"compilerOptions": {
511
"declaration": true,
612
"declarationMap": true,

0 commit comments

Comments
 (0)