Skip to content

Commit abc2d31

Browse files
authored
Speed up CI from ~11m to under 3m (#96)
## 🥞 Stacked PR Use this [link](https://github.com/databricks/sdk-js/pull/96/files) to review incremental changes. - [**stack/speed-up-ci**](#96) [[Files changed](https://github.com/databricks/sdk-js/pull/96/files)] ## Summary Cuts the CI gate wall time from ~10m 49s to ~2m 27s (−77%) by removing redundant build work between jobs and sharding the lint, typecheck, and build jobs across four package-name ranges. ## Why CI on this repo has 60+ packages and was taking over 10 minutes end-to-end, which is painful for iteration. Two compounding problems: 1. **Every non-build job reran the full build.** Each of `lint`, `typecheck`, `test`, and `test-browser` ran `npm run build` as its first step, which builds all 63 packages (~3m 51s on the CI runners). Turbo's task graph already declares `lint/typecheck/test.dependsOn: ["^build"]`, which means Turbo will build only the upstream packages each task actually needs (usually `core`, `databricks`, `auth` — 3 packages, ~30s). The explicit build step was pure duplicate work. 2. **Lint, typecheck, and build were single jobs processing 62 packages on one runner.** Turbo parallelizes tasks within a job, but a CI runner has limited cores, so ESLint in particular saturated at ~5m 27s wall time. Nothing was sharing the load across additional runners. A Turbo remote cache would solve both by sharing cached task outputs across jobs and across runs, but the infra to host one isn't set up for this repo, so this PR takes a simpler route that uses only what we already have. ## What changed ### Interface changes - **`npm run checks`** — New root script that runs `turbo run lint format:check` in a single invocation, so local dev has a one-liner for both pre-commit checks. ### Behavioral changes None for anything the SDK exposes. Only CI runtime and parallelism change. ### Internal changes - **Removed the redundant `Build packages` step** from the `lint`, `typecheck`, `test`, and `test-browser` jobs. Each of these tasks has `dependsOn: ["^build"]` in `turbo.json`, so Turbo now builds only the ~3 upstream packages each task needs. The dedicated `build` job still exercises a full build of every package. - **Sharded `lint`, `typecheck`, and `build` across four package-name ranges** using a GitHub Actions matrix: `[a-c]*`, `[d-l]*`, `[m-r]*`, `[s-z]*`. The four ranges cover all of a-z, so a new package added under any letter is picked up automatically. The `build` job additionally keeps its existing `node-version: ['22', '24']` matrix, so sharding multiplies it into 8 build jobs. - **Shard dispatch reuses the existing npm scripts** with the filter appended as a CLI argument: `npm run <script> -- --filter='@databricks/sdk-${{ matrix.shard }}'`. npm appends args after `--` verbatim to the script command, so turbo receives `--filter=<value>` as its own flag before it parses any task-args separator. ## How is this tested? Ran the workflow on this branch and measured: | Stage | Gate wall time | | --- | --- | | Before any changes | ~10m 49s | | After removing redundant build steps | 6m 45s (−38%) | | After sharding lint only | 5m 40s (−48%) | | After sharding lint + typecheck + build | **2m 27s (−77%)** | Latest green run: https://github.com/databricks/sdk-js/actions/runs/24778267054. The slowest individual shard is `Lint ([s-z]*)` at ~2m 18s; the remaining gate time is GitHub Actions runner startup and `npm ci`. Further reductions would need a remote Turbo cache or more shards (diminishing returns — startup alone is ~30s). Also verified locally that the four shards together cover exactly the 62 lintable packages (union of `turbo run lint --filter=...` across the four ranges equals the full package list).
1 parent 4b26764 commit abc2d31

2 files changed

Lines changed: 19 additions & 22 deletions

File tree

.github/workflows/ci.yml

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@ concurrency:
1717

1818
jobs:
1919
lint:
20-
name: Lint
20+
name: Lint (${{ matrix.shard }})
2121
runs-on:
2222
group: databricks-protected-runner-group
2323
labels: linux-ubuntu-latest
24+
strategy:
25+
fail-fast: false
26+
matrix:
27+
# Shards partition packages by the first letter after `@databricks/sdk-`.
28+
# Together the four ranges cover a-z.
29+
shard: ['[a-c]*', '[d-l]*', '[m-r]*', '[s-z]*']
2430
steps:
2531
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
2632

@@ -43,20 +49,18 @@ jobs:
4349
- name: Install dependencies
4450
run: jf npm ci
4551

46-
- name: Build packages
47-
run: npm run build
48-
49-
- name: Run ESLint
50-
run: npm run lint
51-
52-
- name: Check formatting
53-
run: npm run format:check
52+
- name: Run lint and format checks
53+
run: npm run checks -- --filter='@databricks/sdk-${{ matrix.shard }}'
5454

5555
typecheck:
56-
name: Type Check
56+
name: Type Check (${{ matrix.shard }})
5757
runs-on:
5858
group: databricks-protected-runner-group
5959
labels: linux-ubuntu-latest
60+
strategy:
61+
fail-fast: false
62+
matrix:
63+
shard: ['[a-c]*', '[d-l]*', '[m-r]*', '[s-z]*']
6064
steps:
6165
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
6266

@@ -79,11 +83,8 @@ jobs:
7983
- name: Install dependencies
8084
run: jf npm ci
8185

82-
- name: Build packages
83-
run: npm run build
84-
8586
- name: Run type check
86-
run: npm run typecheck
87+
run: npm run typecheck -- --filter='@databricks/sdk-${{ matrix.shard }}'
8788

8889
test:
8990
name: Test (Node.js ${{ matrix.node-version }})
@@ -116,9 +117,6 @@ jobs:
116117
- name: Install dependencies
117118
run: jf npm ci
118119

119-
- name: Build packages
120-
run: npm run build
121-
122120
- name: Run tests
123121
run: npm test
124122

@@ -153,24 +151,22 @@ jobs:
153151
- name: Install dependencies
154152
run: jf npm ci
155153

156-
- name: Build packages
157-
run: npm run build
158-
159154
- name: Install Playwright browsers
160155
run: npx playwright install chromium --with-deps
161156

162157
- name: Run browser tests
163158
run: npm run test:browser
164159

165160
build:
166-
name: Build (Node.js ${{ matrix.node-version }})
161+
name: Build (Node.js ${{ matrix.node-version }}, ${{ matrix.shard }})
167162
runs-on:
168163
group: databricks-protected-runner-group
169164
labels: linux-ubuntu-latest
170165
strategy:
171166
fail-fast: false
172167
matrix:
173168
node-version: ['22', '24']
169+
shard: ['[a-c]*', '[d-l]*', '[m-r]*', '[s-z]*']
174170
steps:
175171
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
176172

@@ -194,7 +190,7 @@ jobs:
194190
run: jf npm ci
195191

196192
- name: Build
197-
run: npm run build
193+
run: npm run build -- --filter='@databricks/sdk-${{ matrix.shard }}'
198194

199195
# This job gates merging. It depends on all CI jobs so that branch protection
200196
# only needs to reference this single check. When adding new jobs, append

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"lint:fix": "turbo run lint:fix",
1616
"format": "turbo run format",
1717
"format:check": "turbo run format:check",
18+
"checks": "turbo run lint format:check",
1819
"typecheck": "turbo run typecheck",
1920
"clean": "turbo run clean"
2021
},

0 commit comments

Comments
 (0)