Repository navigation
ci: move PR checks to GitHub-hosted 8-core runners - #343094
Michael Lively (Yoyokrazy) wants to merge 10 commits into
Conversation
Replace the 1ES self-hosted pools in pr.yml, pr-win32-test.yml and pr-node-modules.yml with the vscode-large-runners-ubuntu-8-core and vscode-large-runners-windows-8-core pools, and move the Linux test and CLI jobs from the standard 4-core runners to the 8-core pool. The Electron cache version includes the absolute cache path, so update the runner home directories in detect-missing-caches to the GitHub-hosted ones (/home/runner, C:\Users\runneradmin). Refs: microsoft/vscode-engineering#4273 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
1 open issue
What changed in this PR
Moves core PR checks from 1ES self-hosted pools to GitHub-hosted 8-core “vscode-large-runners” pools, and updates cache-detection logic/tests to align Electron cache versions with GitHub-hosted runner home directories.
Changes:
- Updated multiple PR workflows to run on
vscode-large-runners-*-8-corerunners. - Updated Electron cache path assumptions in
detect-missing-cachesto match GitHub-hosted runner home directories. - Updated
detectMissingCachestest runner labels to match the newruns-onvalues.
| File | Description |
|---|---|
| build/lib/test/detectMissingCaches.test.ts | Updates runner label expectations in tests to match new workflow runs-on labels. |
| .github/workflows/pr.yml | Moves compile/hygiene and Copilot PR jobs to GitHub-hosted 8-core runner pools. |
| .github/workflows/pr-win32-test.yml | Moves all Windows test jobs to GitHub-hosted 8-core Windows runner pool. |
| .github/workflows/pr-node-modules.yml | Moves warm/cache-related compile/Linux/Windows/Copilot jobs to GitHub-hosted 8-core pools. |
| .github/workflows/pr-linux-test.yml | Moves Linux test jobs from standard runners to GitHub-hosted 8-core pool. |
| .github/workflows/pr-linux-cli-test.yml | Moves Linux CLI test jobs from standard runners to GitHub-hosted 8-core pool. |
| .github/actions/detect-missing-caches/detect.ts | Updates Electron cache absolute paths to GitHub-hosted home directories for stable cache-version computation. |
Review effort: Lite
Temporary; will be removed before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Temporary; will be removed before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Temporary; will be removed before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Temporary; will be removed before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Temporary; will be removed before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Temporary; will be removed before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Temporary; will be removed before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the temporary diagnostics workflow and change the node_modules cache key prefixes so that every job installs dependencies on the new runners. Will be reverted before the PR is ready. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The cache-miss path was validated in run 39539559733. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Results: PR checks on the GitHub-hosted 8-core poolsSummary: Linux works well on Runs
All three runs used the full Agent Host E2E profile, because workflow changes count as an infrastructure change. Per-job durations (minutes)The new-pool median is over runs 1 and 3 (cache hit). The 1ES-era median is over 11 recent successful
The Linux Agent Host E2E step dropped from 7.3 min (4-core) to 4.8 min.
|
| Pool | npm ci |
1ES / standard baseline (from the issue) |
|---|---|---|
| ubuntu-8 | 2.9–5.2 min (Compile 5.2) | 3–5 min |
| windows-8 | 18.5–24.4 min (median about 19.7) | about 12.5 min |
Both pools build all native modules from scratch. On Windows that's the windows-2025-vs2026 image with VS 2026, which build/npm/preinstall.ts already detects. checkNativeOptionalDeps.ts isn't part of the PR jobs, but every test that loads native modules passed.
Runner queue time (job created → started)
| Pool | Median | Max | Jobs |
|---|---|---|---|
| ubuntu-8 | 0.08 min | 0.10 min | 39 |
| windows-8 | 2.0 min | 3.4 min | 24 |
| 1ES ubuntu (baseline) | 0.22 min | 0.32 min | 17 |
| 1ES windows (baseline) | 0.18 min | 0.32 min | 80 |
standard ubuntu-24.04 (baseline) |
0.07 min | 0.33 min | 255 |
Windows 8-core runners take about 2 min to start when no runner is idle. A runner that was just released starts in about 0.05 min.
Windows Agent Host E2E: root cause
I investigated with temporary workflows on this PR (all removed). They used a handful of short jobs on the 8-core pool and 1ES. No pool configuration was changed.
- Disk layout: the 8-core Windows runner has a single "Virtual_Disk NVMe Premium SSD"
C:(440 GB) and no temp disk, so the workspace isC:\a\vscode\vscode. 1ES (D8ds_v5) has the workspace on a local temp SSD (D:\a\_work). Standardwindows-latestalso has aD:temp disk. - Ruled out: Defender real-time scanning (off on all three), VBS/HVCI (off), CPU (AMD EPYC 9V74 vs Xeon 8573C, both 4C/8T, with similar single-thread loops), and process spawn cost (30–37 ms for warm
node.exeon all three). CPU-bound steps are faster on the new runner: Electron unit tests 9.1 vs 10.8 min, node unit 5.2 vs 6.2. - Bottleneck: Agent Host E2E runs 6 suites in parallel and does about 700–1,100 small writes/s (about 9 KB each, about 6–9 MB/s). On 1ES that averages 0.5–4 ms per write at 31–52% CPU. On the 8-core runner it averages 7–20 ms per write with a queue depth of 6–7, while the CPU sits at 14–20%. The tests then hit their 20–30 s
createSession/createChat/subscribetimeouts. A freshly provisioned VM adds background I/O on the same disk (Defender engine about 1.9 GB read+write, Windows servicing, Search indexer). - Mitigations tried in-job (Agent Host E2E duration; 1ES ran the same experiment in 10.2 and 16.9 min):
| Variant | Result |
|---|---|
| Control | 32 min ❌ / 30 min timeout ❌ |
--jobs 3 |
24.9 min ❌ |
TEMP on a ReFS Dev Drive VHDX |
25.8 min ✅ / 35.3 min ❌ |
Dev Drive mounted at the workspace + TEMP |
25.8 min ✅ (checkout 12 s, node_modules restore 59 s vs 3–4 min) |
Disk flushes suppressed (IOCTL_DISK_SET_CACHE_SETTING, power-protected) |
26.2 min ❌ (fsync 1.4 → 0.5 ms, but the step didn't get faster) |
RAM disk via the iSCSI Target ramdisk: feature |
not viable: the feature install alone takes 2.6 min, and the loopback portal fails |
None of these brings Windows Agent Host E2E back to 1ES speed or makes it reliable, so this PR doesn't include them.
Other platform checks
- Ubuntu 22.04 → 24.04 (Compile, Copilot): no changes needed. The Copilot extension-host tests run fine under
xvfb-runwithout the AppArmor userns workaround. - Windows Server 2022 → 2025 (
windows-2025-vs2026):npm cibuilds the native modules with VS 2026. The Copilot Windows job (setup-python 3.12, .NET 10, setuptools) passes on both cache paths. - WSL2 / nested virtualization: works.
wslDevContainer.ps1imports the WSL2 distro and Windows smoke shard 1 passes (WSL setup 2.8 vs 1.5 min on 1ES). - Disk layout: workspace on
C:(see above). On a cache hit, extracting node_modules takes 2.9–3.8 min vs 1.3 min on 1ES. That's the main reason the other Windows jobs are 0.5–1.5 min slower. - Electron cache:
actions/cacheincludes the absolute path in the cache version, so the Electron cache thatpr-node-modules.ymlsaved from 1ES (/home/cloudtest,C:\Users\cloudtest) could never be restored on GitHub-hosted runners. The Linux test jobs have been downloading Electron every time since they moved toubuntu-24.04. This PR moves the warming jobs and updatesdetect-missing-caches, so after merge both OSes get Electron cache hits. - node_modules cache key: unchanged (reasons are in the PR description). Old-image caches restored fine on the new images in runs 1 and 3, and the miss path works on both pools (run 2).
Options for Windows Agent Host E2E (need a decision)
- Use a Windows pool with local temp storage for at least the job that runs Agent Host E2E. That's a pool or VM-SKU decision. I didn't change any pool configuration.
- Try the 16-core Windows pool for that job: a 600 GB disk means a higher Premium SSD IOPS tier. It's out of scope here because those pools are used for experiments.
- Make the suites tolerate slower disks on Windows: longer per-request timeouts, or use a RAM-backed temp directory once Windows has a practical way to create one (Linux already uses tmpfs,
splitstorage). Accept a longer Windows long pole. Combined with ci: run Agent Host E2E tests in their own job on Windows #342735, Agent Host E2E would become its own about 32-min Windows job. - Separately, consider the Dev Drive workspace for all Windows jobs: it cut node_modules restore from 3–4 min to 59 s. It's not in this PR because it changes the filesystem the Windows tests run on (ReFS), and only Agent Host E2E has been validated on it.
Follow-ups (not in this PR)
codeql.yml, component-fixtures.yml, telemetry.yml, monaco-editor.yml, copilot-setup-steps.yml (vscode-large-runners), chat-perf.yml, sessions-e2e.yml, css-order-scan.yml, chat-lib-package.yml, and the chat-lib jobs in pr.yml (their required check names would need to change first).
Update: re-run and 1ES comparisonI re-ran the failed job and Windows / Electron passed on attempt 2: Agent Host E2E took 26.6 min, the whole job 38.8 min. All checks are green now. The Windows Agent Host E2E slowdown is caused by this PR's runner change; it isn't a flake. The comparison below uses every other PR's 1ES
The
|
Update: Windows Agent Host E2E can run on the 8-core pool if the suites are split across runnersCorrection: I wrote earlier that 1ES is faster because it has a local temp SSD. That's wrong: on 1ES, Agent Host E2E's disk traffic goes to Fix: split the suites across runners. With 2 suites per runner on Full tables: https://github.com/microsoft/vscode-engineering/issues/4273#issuecomment-6325648086 For this PR: Windows / Electron shouldn't move to the 8-core pool until #342735 (Agent Host E2E in its own job) also splits it into 3 jobs of 2 suites on Windows. Until then, keep the Windows 1ES pool, or merge only the Linux changes. Addendum: one runner, 2 suites at a time (run 39672938507,
|

Moves the core PR checks off the 1ES self-hosted pools and onto the GitHub-hosted larger-runner production pools. Tracking: microsoft/vscode-engineering#4273.
Changes
pr.ymlubuntu-22.04vscode-large-runners-ubuntu-8-corepr.ymlwindows-2022vscode-large-runners-windows-8-corepr-win32-test.ymlwindows-2022vscode-large-runners-windows-8-corepr-node-modules.ymlubuntu-22.04vscode-large-runners-ubuntu-8-corepr-node-modules.ymlwindows-2022vscode-large-runners-windows-8-corepr-linux-test.ymlubuntu-24.04(4-core)vscode-large-runners-ubuntu-8-corepr-linux-cli-test.ymlubuntu-24.04(4-core)vscode-large-runners-ubuntu-8-coredetect-missing-caches/detect.ts(+ test)/home/cloudtest,C:\Users\cloudtest)/home/runner,C:\Users\runneradmin)The diff is almost entirely
runs-onlines so it rebases cleanly against #342735.Why
detect.tschanges:actions/cacheputs the absolute cache path into the cache version.setup-electroncaches$HOME/.cache/electron(Linux) and%LOCALAPPDATA%\electron\Cache(Windows), so the Electron cache thatpr-node-modules.ymlsaves from 1ES (/home/cloudtest) can't be restored on GitHub-hosted runners (/home/runner). The Linux test jobs have been missing this cache since they moved toubuntu-24.04. After this change the warming jobs and the test jobs run on the same images, anddetect.tshas to compute the version from the new paths, or the Linux and Windows warming jobs would run on every push to main.Assumptions
runs-on(self-hosted,1ES.Pool=…,JobId=…) moves to the 8-core production pools. TheJobIdlabels were 1ES-specific and are dropped.pr-linux-test.ymlandpr-linux-cli-test.yml.changes(Detect Changes),required-checks, and the pr-node-modulescachesjob: they finish in seconds.ubuntu-latest/windows-latest.macos-26-xlarge): fixed size.node_modules-linuxonubuntu-24.04). Changing the key would force every PR to runnpm cion every job until main re-warms the caches (about 12.5 min per Windows job). The keys include everypackage-lock.json, so the old-image entries are replaced with the next dependency change after this merges. The cache-miss (npm ci) path was validated on both new pools with a temporary key-prefix commit, which was reverted (see Validation).pr-node-modules.ymlonly runs on push to main, so its move takes effect after merge. Until main re-warms the caches, Windows PR jobs miss the Electron cache (different cache path) and download Electron instead. After the merge, both OSes get Electron cache hits; the Linux test jobs have been missing it since they moved toubuntu-24.04.Follow-ups (not in this PR)
Other workflows still on standard runners:
codeql.yml,component-fixtures.yml,telemetry.yml,monaco-editor.yml,copilot-setup-steps.yml(vscode-large-runners),chat-perf.yml,sessions-e2e.yml,css-order-scan.yml,chat-lib-package.yml, and the chat-lib jobs inpr.yml(the required check names need to change first).Validation
782bbf2)Mission Control WPSEPERM flake, same as #341529)4eaff64, temporary key-prefix change, reverted in6232879)npm cion both pools)6232879, final; same tree as782bbf2)node --test build/lib/test/detectMissingCaches.test.ts: passed locally (4/4). Compile & Hygiene also runs the build typecheck and the build-script tests.782bbf2.