Skip to content

Commit 9bb5a87

Browse files
mattKorwelabhipatel12
authored andcommitted
Improve CI Times by 70% (#8530)
1 parent eb82b86 commit 9bb5a87

File tree

14 files changed

+858
-304
lines changed

14 files changed

+858
-304
lines changed

.github/workflows/ci.yml

Lines changed: 176 additions & 258 deletions
Large diffs are not rendered by default.

.github/workflows/e2e.yml

Lines changed: 212 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,34 +15,72 @@ on:
1515
merge_group:
1616

1717
jobs:
18-
e2e-test:
19-
name: 'E2E Test (${{ matrix.os }}) - ${{ matrix.sandbox }}'
20-
# This condition ensures the job runs for pushes to main, merge groups,
21-
# PRs from the base repo, OR PRs from forks with the correct label.
18+
merge_queue_skipper:
19+
name: 'Merge Queue Skipper'
20+
runs-on: 'ubuntu-latest'
21+
outputs:
22+
skip: '${{ steps.skipper.outputs.skip }}'
23+
steps:
24+
- name: 'Check if skip'
25+
id: 'skipper'
26+
uses: 'fkirc/skip-duplicate-actions@f75f66ce1886f00957d99748a42c724f4330bdcf' # ratchet:fkirc/skip-duplicate-actions@v5
27+
with:
28+
concurrent_skipping: 'never'
29+
skip_after_successful_duplicate: 'true'
30+
paths_ignore: '["**.md", "docs/**"]'
31+
do_not_skip: '["push", "workflow_dispatch", "schedule"]'
32+
33+
build:
34+
name: 'Build Project'
35+
runs-on: 'gemini-cli-ubuntu-16-core'
36+
needs: 'merge_queue_skipper'
37+
if: "needs.merge_queue_skipper.outputs.skip != 'true'"
38+
steps:
39+
- name: 'Checkout'
40+
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
41+
42+
- name: 'Set up Node.js'
43+
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
44+
with:
45+
node-version-file: '.nvmrc'
46+
cache: 'npm'
47+
48+
- name: 'Install dependencies'
49+
run: 'npm ci'
50+
51+
- name: 'Build project'
52+
run: 'npm run build'
53+
54+
- name: 'Archive build artifacts'
55+
run: 'tar -cvf build-artifacts.tar bundle/ node_modules/ packages/ package.json npm-shrinkwrap.json'
56+
57+
- name: 'Upload build artifacts'
58+
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02'
59+
with:
60+
name: 'build-artifacts'
61+
path: 'build-artifacts.tar'
62+
63+
e2e_linux:
64+
name: 'E2E Test (Linux) - ${{ matrix.sandbox }}'
65+
needs:
66+
- 'merge_queue_skipper'
67+
- 'build'
2268
if: |
23-
github.event_name == 'push' ||
24-
github.event_name == 'merge_group' ||
25-
(github.event.pull_request.head.repo.full_name == github.repository) ||
26-
(github.event.label.name == 'maintainer:e2e:ok')
27-
runs-on: '${{ matrix.os }}'
69+
needs.merge_queue_skipper.outputs.skip != 'true' && (
70+
github.event_name == 'push' ||
71+
github.event_name == 'merge_group' ||
72+
(github.event.pull_request.head.repo.full_name == github.repository) ||
73+
(github.event.label.name == 'maintainer:e2e:ok')
74+
)
75+
runs-on: 'gemini-cli-ubuntu-16-core'
2876
strategy:
2977
fail-fast: false
3078
matrix:
31-
os:
32-
- 'ubuntu-latest'
33-
- 'macos-latest'
34-
- 'gemini-cli-windows-16-core'
3579
sandbox:
3680
- 'sandbox:none'
3781
- 'sandbox:docker'
3882
node-version:
3983
- '20.x'
40-
exclude:
41-
# Docker tests are not supported on macOS or Windows
42-
- os: 'macos-latest'
43-
sandbox: 'sandbox:docker'
44-
- os: 'gemini-cli-windows-16-core'
45-
sandbox: 'sandbox:docker'
4684

4785
steps:
4886
- name: 'Checkout (fork)'
@@ -56,22 +94,22 @@ jobs:
5694
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
5795
if: "github.event_name != 'pull_request_target'"
5896

97+
- name: 'Download build artifacts'
98+
uses: 'actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093'
99+
with:
100+
name: 'build-artifacts'
101+
path: '.'
102+
103+
- name: 'Extract build artifacts'
104+
run: 'tar -xvf build-artifacts.tar'
105+
59106
- name: 'Set up Node.js ${{ matrix.node-version }}'
60107
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
61108
with:
62109
node-version: '${{ matrix.node-version }}'
63110

64-
- name: 'Install dependencies'
65-
run: |-
66-
npm ci
67-
68-
- name: 'Build project'
69-
run: |-
70-
npm run build
71-
72111
- name: 'Set up Docker'
73-
if: |-
74-
matrix.os == 'ubuntu-latest' && matrix.sandbox == 'sandbox:docker'
112+
if: "matrix.sandbox == 'sandbox:docker'"
75113
uses: 'docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435' # ratchet:docker/setup-buildx-action@v3
76114

77115
- name: 'Run E2E tests'
@@ -80,6 +118,149 @@ jobs:
80118
KEEP_OUTPUT: 'true'
81119
SANDBOX: '${{ matrix.sandbox }}'
82120
VERBOSE: 'true'
121+
GEMINI_SANDBOX: 'docker'
83122
shell: 'bash'
84-
run: |-
85-
npm run "test:integration:${SANDBOX}"
123+
run: |
124+
if [[ "${{ matrix.sandbox }}" == "sandbox:docker" ]]; then
125+
npm run build:sandbox
126+
fi
127+
npx vitest run --root ./integration-tests
128+
129+
e2e_slow_platforms:
130+
name: 'Slow E2E - Mac'
131+
needs:
132+
- 'merge_queue_skipper'
133+
- 'build'
134+
if: |
135+
needs.merge_queue_skipper.outputs.skip != 'true' && (
136+
github.event_name == 'push' ||
137+
github.event_name == 'merge_group' ||
138+
(github.event.pull_request.head.repo.full_name == github.repository) ||
139+
(github.event.label.name == 'maintainer:e2e:ok')
140+
)
141+
runs-on: '${{ matrix.os }}'
142+
continue-on-error: true
143+
strategy:
144+
fail-fast: false
145+
matrix:
146+
os:
147+
- 'macos-latest'
148+
node-version:
149+
- '20.x'
150+
151+
steps:
152+
- name: 'Checkout (fork)'
153+
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
154+
if: "github.event_name == 'pull_request_target'"
155+
with:
156+
ref: '${{ github.event.pull_request.head.sha }}'
157+
repository: '${{ github.event.pull_request.head.repo.full_name }}'
158+
159+
- name: 'Checkout (internal)'
160+
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
161+
if: "github.event_name != 'pull_request_target'"
162+
163+
- name: 'Download build artifacts'
164+
uses: 'actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093'
165+
with:
166+
name: 'build-artifacts'
167+
path: '.'
168+
169+
- name: 'Extract build artifacts'
170+
run: 'tar -xvf build-artifacts.tar'
171+
172+
- name: 'Set up Node.js ${{ matrix.node-version }}'
173+
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
174+
with:
175+
node-version: '${{ matrix.node-version }}'
176+
177+
- name: 'Fix rollup optional dependencies on macOS'
178+
if: "runner.os == 'macOS'"
179+
run: |
180+
npm cache clean --force
181+
npm install --no-save @rollup/rollup-darwin-arm64 || true
182+
183+
- name: 'Run E2E tests (non-Windows)'
184+
if: "runner.os != 'Windows'"
185+
env:
186+
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
187+
KEEP_OUTPUT: 'true'
188+
SANDBOX: 'sandbox:none'
189+
VERBOSE: 'true'
190+
run: 'npx vitest run --root ./integration-tests'
191+
192+
e2e_windows:
193+
name: 'Slow E2E - Win'
194+
if: "needs.merge_queue_skipper.outputs.skip != 'true'"
195+
needs:
196+
- 'merge_queue_skipper'
197+
runs-on: 'gemini-cli-windows-16-core'
198+
continue-on-error: true
199+
200+
steps:
201+
- name: 'Checkout (fork)'
202+
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
203+
if: "github.event_name == 'pull_request_target'"
204+
with:
205+
ref: '${{ github.event.pull_request.head.sha }}'
206+
repository: '${{ github.event.pull_request.head.repo.full_name }}'
207+
208+
- name: 'Checkout (internal)'
209+
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
210+
if: "github.event_name != 'pull_request_target'"
211+
212+
- name: 'Set up Node.js 20.x'
213+
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
214+
with:
215+
node-version: '20.x'
216+
cache: 'npm'
217+
218+
- name: 'Configure Windows Defender exclusions'
219+
run: |
220+
Add-MpPreference -ExclusionPath $env:GITHUB_WORKSPACE -Force
221+
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE\node_modules" -Force
222+
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE\packages" -Force
223+
Add-MpPreference -ExclusionPath "$env:TEMP" -Force
224+
shell: 'pwsh'
225+
226+
- name: 'Configure npm for Windows performance'
227+
run: |
228+
npm config set progress false
229+
npm config set audit false
230+
npm config set fund false
231+
npm config set loglevel error
232+
npm config set maxsockets 32
233+
npm config set registry https://registry.npmjs.org/
234+
shell: 'pwsh'
235+
236+
- name: 'Install dependencies'
237+
run: 'npm ci'
238+
shell: 'pwsh'
239+
240+
- name: 'Run E2E tests'
241+
env:
242+
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
243+
KEEP_OUTPUT: 'true'
244+
SANDBOX: 'sandbox:none'
245+
VERBOSE: 'true'
246+
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
247+
UV_THREADPOOL_SIZE: '32'
248+
NODE_ENV: 'test'
249+
shell: 'pwsh'
250+
run: 'npx vitest run --root ./integration-tests'
251+
252+
e2e:
253+
name: 'E2E'
254+
if: 'always()'
255+
needs:
256+
- 'merge_queue_skipper'
257+
- 'e2e_linux'
258+
runs-on: 'gemini-cli-ubuntu-16-core'
259+
steps:
260+
- name: 'Check E2E test results'
261+
run: |
262+
if [[ ${{ needs.e2e_linux.result }} != 'success' ]]; then
263+
echo "The required E2E test job failed."
264+
exit 1
265+
fi
266+
echo "All required E2E test jobs passed!"

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
},
1313
"[javascript]": {
1414
"editor.defaultFormatter": "esbenp.prettier-vscode"
15-
}
15+
},
16+
"vitest.disableWorkspaceWarning": true
1617
}

esbuild.config.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import esbuild from 'esbuild';
87
import path from 'node:path';
98
import { fileURLToPath } from 'node:url';
109
import { createRequire } from 'node:module';
1110
import { writeFileSync } from 'node:fs';
1211

12+
let esbuild;
13+
try {
14+
esbuild = (await import('esbuild')).default;
15+
} catch (_error) {
16+
console.warn('esbuild not available, skipping bundle step');
17+
process.exit(0);
18+
}
19+
1320
const __filename = fileURLToPath(import.meta.url);
1421
const __dirname = path.dirname(__filename);
1522
const require = createRequire(import.meta.url);

integration-tests/vitest.config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export default defineConfig({
1313
reporters: ['default'],
1414
include: ['**/*.test.ts'],
1515
retry: 2,
16-
fileParallelism: false,
16+
fileParallelism: true,
17+
poolOptions: {
18+
threads: {
19+
minThreads: 8,
20+
maxThreads: 16,
21+
},
22+
},
1723
},
1824
});

0 commit comments

Comments
 (0)