authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-08-23 05:36:09-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-23 05:36:09-07:00
log25dcee00a6e12db2781a17b326e6e34de0d4ced7
treed12c2e7bcbe33ff826a1c232f0f747fea602ee6d
parentf70eeeeb06d6d96f292be7eef1ed8948103e68dc
signature Signed by PGP key B5690EEEBB952194

perf(ci): speed up release builds and Windows packaging (#7975)


6 files changed, 251 insertions(+), 120 deletions(-)

.github/workflows/release.yml+63-19
......@@ -100,9 +100,6 @@ jobs:
100100 cache: true
101101 run-install: true
102102
103 - name: Ensure Electron runtime is installed
104 run: vp run --filter @t3tools/desktop ensure:electron
105
106103 - id: release_meta
107104 name: Resolve release version
108105 shell: bash
......@@ -157,6 +154,40 @@ jobs:
157154 fi
158155 fi
159156
157 - id: previous_tag
158 name: Resolve previous release tag
159 run: |
160 node scripts/resolve-previous-release-tag.ts \
161 --channel "${{ steps.release_meta.outputs.release_channel }}" \
162 --current-tag "${{ steps.release_meta.outputs.tag }}" \
163 --github-output
164
165 quality:
166 name: Release quality checks
167 needs: [preflight]
168 if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }}
169 runs-on: blacksmith-8vcpu-ubuntu-2404
170 timeout-minutes: 10
171 steps:
172 - name: Checkout
173 uses: actions/checkout@v6
174 with:
175 ref: ${{ needs.preflight.outputs.ref }}
176 sparse-checkout: |
177 /*
178 !/.repos/
179 sparse-checkout-cone-mode: false
180
181 - name: Setup Vite+
182 uses: voidzero-dev/setup-vp@v1
183 with:
184 node-version-file: package.json
185 cache: true
186 run-install: true
187
188 - name: Ensure Electron runtime is installed
189 run: vp run --filter @t3tools/desktop ensure:electron
190
160191 - name: Check
161192 run: vp check
162193
......@@ -166,14 +197,6 @@ jobs:
166197 - name: Test
167198 run: vp run test
168199
169 - id: previous_tag
170 name: Resolve previous release tag
171 run: |
172 node scripts/resolve-previous-release-tag.ts \
173 --channel "${{ steps.release_meta.outputs.release_channel }}" \
174 --current-tag "${{ steps.release_meta.outputs.tag }}" \
175 --github-output
176
177200 relay_public_config:
178201 name: Resolve T3 Connect public config
179202 needs: preflight
......@@ -385,14 +408,34 @@ jobs:
385408 uses: voidzero-dev/setup-vp@v1
386409 with:
387410 node-version-file: package.json
388 cache: true
389 run-install: |
390 args:
391 - --filter=@t3tools/desktop...
392 - --filter=t3...
393 - --filter=@t3tools/scripts...
411 cache: ${{ matrix.platform != 'win' }}
412 run-install: false
413
414 - name: Resolve Windows package cache path
415 if: matrix.platform == 'win'
416 id: package_cache_path
417 shell: pwsh
418 run: '"path=$(vp pm cache dir)" >> $env:GITHUB_OUTPUT'
419
420 - name: Cache Windows packages
421 if: matrix.platform == 'win'
422 uses: actions/cache@v6
423 with:
424 path: ${{ steps.package_cache_path.outputs.path }}
425 key: windows-release-packages-v1-${{ matrix.arch }}-${{ hashFiles('pnpm-lock.yaml') }}
426
427 - name: Install desktop dependencies
428 run: vp install --filter=@t3tools/desktop... --filter=t3... --filter=@t3tools/scripts...
429
430 - name: Cache resource monitor
431 id: resource_monitor_cache
432 uses: actions/cache@v6
433 with:
434 path: native/resource-monitor/target/${{ matrix.rust_target }}/release/t3-resource-monitor${{ matrix.platform == 'win' && '.exe' || '' }}
435 key: resource-monitor-${{ matrix.rust_target }}-${{ hashFiles('native/resource-monitor/Cargo.lock', 'native/resource-monitor/Cargo.toml', 'native/resource-monitor/src/**') }}
394436
395437 - name: Setup Rust
438 if: steps.resource_monitor_cache.outputs.cache-hit != 'true'
396439 uses: dtolnay/rust-toolchain@stable
397440 with:
398441 targets: ${{ matrix.rust_target }}
......@@ -518,6 +561,7 @@ jobs:
518561 - name: Build desktop artifact
519562 shell: bash
520563 env:
564 T3CODE_DESKTOP_REUSE_RESOURCE_MONITOR: ${{ steps.resource_monitor_cache.outputs.cache-hit == 'true' }}
521565 CSC_LINK: ${{ secrets.CSC_LINK }}
522566 CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
523567 APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
......@@ -664,8 +708,8 @@ jobs:
664708
665709 publish_cli:
666710 name: Publish CLI to npm
667 needs: [preflight, relay_public_config, build]
668 if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' && needs.build.result == 'success' }}
711 needs: [preflight, relay_public_config, quality, build]
712 if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' && needs.relay_public_config.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success' }}
669713 runs-on: ubuntu-24.04 # blacksmith-8vcpu-ubuntu-2404
670714 timeout-minutes: 10
671715 permissions:
docs/operations/release.md+2-1
......@@ -11,7 +11,7 @@ This document covers the unified release workflow for stable and nightly desktop
1111 - push tag matching `v*.*.*` for stable releases
1212 - scheduled nightly check every three hours
1313 - manual `workflow_dispatch` for either channel
14- Runs quality gates first: lint, typecheck, test.
14- Runs lint, typecheck, and tests alongside artifact builds. Publishing waits for every check.
1515- Reads the shared production T3 Connect relay URL and Clerk client configuration before packaging clients.
1616- Builds four artifacts in parallel for both channels:
1717 - macOS `arm64` DMG
......@@ -365,6 +365,7 @@ Checklist:
3653654. Push tag.
3663665. Verify workflow steps:
367367 - preflight passes
368 - release quality checks pass
368369 - all matrix builds pass
369370 - `publish_cli` publishes the exact release version before the release job
370371 - release job uploads expected files
pnpm-lock.yaml+8-77
......@@ -38,6 +38,14 @@ catalogs:
3838 version: 0.2.2
3939
4040overrides:
41 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-darwin-arm64': '-'
42 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-darwin-x64': '-'
43 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-arm64': '-'
44 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-arm64-musl': '-'
45 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-x64': '-'
46 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-x64-musl': '-'
47 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-win32-arm64': '-'
48 '@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-win32-x64': '-'
4149 '@clerk/backend': 3.14.0
4250 '@clerk/clerk-js': 6.29.2
4351 '@clerk/clerk-js>@base-org/account': '-'
......@@ -960,50 +968,6 @@ packages:
960968 '@alchemy.run/node-utils@0.0.5':
961969 resolution: {integrity: sha512-5agdhQxWBodxa5hDRyjnpx91RTU3g+qd5fxYB7uNDCaOzB0XC47UU/KHR6zf6jhz/NXf61gJS+vhYwn8NHeRoQ==}
962970
963 '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.170':
964 resolution: {integrity: sha512-rwfgArIa5WI0QPNqFsRBgvtSI0mrtpynUm0oK6+l6/KX4hcgnYGEzciZR1bOeD9/7sSZlTdIgt+T9alKeZmXcg==}
965 cpu: [arm64]
966 os: [darwin]
967
968 '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.170':
969 resolution: {integrity: sha512-0e58h8UQMtsQxLGIv9r4foxfBFWKZ7NeDtoplLhuD7EwQonehomw1sBXCch77t/IfUS+q5vQ5zv+fOGmap5nLQ==}
970 cpu: [x64]
971 os: [darwin]
972
973 '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.170':
974 resolution: {integrity: sha512-SRYfQcsXlOq+CD/FqkQBTSHbaD++w73GnnO+NUV9adLYrca3kfetRwWT1iguY1cNS0l34dCR3rlzCPq78vg1Jg==}
975 cpu: [arm64]
976 os: [linux]
977 libc: [musl]
978
979 '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.170':
980 resolution: {integrity: sha512-gLbaFqcGppFJQd4DLNV4IXoeahejT/p2/M8bSSvRDbla9GOsBr1AxV5XLRyBn1e7xFGozZIAIQr3+1chp7NJgQ==}
981 cpu: [arm64]
982 os: [linux]
983 libc: [glibc]
984
985 '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.170':
986 resolution: {integrity: sha512-m4+I0qBEk7cxRKS+pL+eoWXbXTFOAo83fQ0tQvap4z/mDMm06IWJtEPoYTaMBwsp32GJWLkHWKbZSBCHZnp2DQ==}
987 cpu: [x64]
988 os: [linux]
989 libc: [musl]
990
991 '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.170':
992 resolution: {integrity: sha512-Xl/m7TaSC3T5IDBdHrZQ9fCQYyDmPELN34CL+MoyPIf7uSmuZnjE9fUOqDh2Rv26JxWssi1M6X+BBvVuKd6Cpg==}
993 cpu: [x64]
994 os: [linux]
995 libc: [glibc]
996
997 '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.170':
998 resolution: {integrity: sha512-IG+8isJNNJKbnnhO7m+PGhfVCg+XoQ/MDxGde5eigFI0WsEfitjuWSWwx82bT9ghxI1aa6qNvI+UPgPcZuo5Fg==}
999 cpu: [arm64]
1000 os: [win32]
1001
1002 '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.170':
1003 resolution: {integrity: sha512-7cuqSKbHVItPGVwRbd3A0BEJwcNtc7Fhoh6qHN4C6yrmjSrvdYYx3MLvq/VI768/RoG7mAMDxb+j7WfEfoP9BA==}
1004 cpu: [x64]
1005 os: [win32]
1006
1007971 '@anthropic-ai/claude-agent-sdk@0.3.170':
1008972 resolution: {integrity: sha512-pAvhfk+iTodXZ6RF18Kz7BEUWFjL7EcR3tKuhUNdPpE1NAYCR3mSHGbafi72JsrNwKEDIs7FU31z3fqhwy8QzA==}
1009973 engines: {node: '>=18.0.0'}
......@@ -10546,44 +10510,11 @@ snapshots:
1054610510
1054710511 '@alchemy.run/node-utils@0.0.5': {}
1054810512
10549 '@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.170':
10550 optional: true
10551
10552 '@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.170':
10553 optional: true
10554
10555 '@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.170':
10556 optional: true
10557
10558 '@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.170':
10559 optional: true
10560
10561 '@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.170':
10562 optional: true
10563
10564 '@anthropic-ai/claude-agent-sdk-linux-x64@0.3.170':
10565 optional: true
10566
10567 '@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.170':
10568 optional: true
10569
10570 '@anthropic-ai/claude-agent-sdk-win32-x64@0.3.170':
10571 optional: true
10572
1057310513 '@anthropic-ai/claude-agent-sdk@0.3.170(@anthropic-ai/sdk@0.93.0(zod@4.4.3))(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(zod@4.4.3)':
1057410514 dependencies:
1057510515 '@anthropic-ai/sdk': 0.93.0(zod@4.4.3)
1057610516 '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3)
1057710517 zod: 4.4.3
10578 optionalDependencies:
10579 '@anthropic-ai/claude-agent-sdk-darwin-arm64': 0.3.170
10580 '@anthropic-ai/claude-agent-sdk-darwin-x64': 0.3.170
10581 '@anthropic-ai/claude-agent-sdk-linux-arm64': 0.3.170
10582 '@anthropic-ai/claude-agent-sdk-linux-arm64-musl': 0.3.170
10583 '@anthropic-ai/claude-agent-sdk-linux-x64': 0.3.170
10584 '@anthropic-ai/claude-agent-sdk-linux-x64-musl': 0.3.170
10585 '@anthropic-ai/claude-agent-sdk-win32-arm64': 0.3.170
10586 '@anthropic-ai/claude-agent-sdk-win32-x64': 0.3.170
1058710518
1058810519 '@anthropic-ai/sdk@0.93.0(zod@4.4.3)':
1058910520 dependencies:
pnpm-workspace.yaml+9
......@@ -78,6 +78,15 @@ minimumReleaseAgeExclude:
7878 - "@legendapp/list@3.3.5"
7979
8080overrides:
81 # The SDK always receives the user's Claude executable, so its bundled binaries are unused.
82 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-darwin-arm64": "-"
83 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-darwin-x64": "-"
84 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-arm64": "-"
85 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "-"
86 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-x64": "-"
87 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-linux-x64-musl": "-"
88 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-win32-arm64": "-"
89 "@anthropic-ai/claude-agent-sdk>@anthropic-ai/claude-agent-sdk-win32-x64": "-"
8190 "@clerk/backend": "catalog:"
8291 "@clerk/clerk-js": "catalog:"
8392 "@clerk/clerk-js>@base-org/account": "-"
scripts/build-desktop-artifact.test.ts+119-1
......@@ -40,6 +40,7 @@ import {
4040 resolveDesktopUpdateChannel,
4141 resolveDesktopWebAssetBrand,
4242 resolveResourceMonitorRustTargets,
43 resolveWindowsServerAsarIgnoreGlobs,
4344 resourceMonitorExecutableName,
4445 resolveGitHubPublishConfig,
4546 resolveMockUpdateServerPort,
......@@ -47,6 +48,7 @@ import {
4748 resolvePackageManagerUserAgent,
4849 stageLinuxIconSize,
4950 stageDesktopDmgBackground,
51 stageResourceMonitor,
5052 STAGE_INSTALL_ARGS,
5153 ancestorNodeModulesPaths,
5254 copyDirectoryPreservingSymlinks,
......@@ -118,7 +120,7 @@ const makeWindowsPayloadFixture = Effect.fn("test.makeWindowsPayloadFixture")(fu
118120 yield* fs.writeFileString(nativePath, "native-binary");
119121
120122 const generatedAsarPath = path.join(tempDir, WINDOWS_SERVER_ASAR_RESOURCE);
121 yield* packWindowsServerAsar({ sourceDir, asarPath: generatedAsarPath });
123 yield* packWindowsServerAsar({ sourceDir, asarPath: generatedAsarPath, arch: "x64" });
122124
123125 const stageDistDir = path.join(tempDir, "dist");
124126 const packagedAppDir = path.join(stageDistDir, "win-unpacked");
......@@ -488,6 +490,121 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => {
488490 }).pipe(Effect.provide(ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })))),
489491 );
490492
493 it("excludes node-pty binaries for the other Windows architecture", () => {
494 assert.deepStrictEqual(resolveWindowsServerAsarIgnoreGlobs("x64"), [
495 ...WINDOWS_SERVER_ASAR_IGNORE_GLOBS,
496 "**/node_modules/node-pty/prebuilds/win32-arm64",
497 "**/node_modules/node-pty/prebuilds/win32-arm64/**",
498 "**/node_modules/node-pty/third_party/conpty/*/win10-arm64",
499 "**/node_modules/node-pty/third_party/conpty/*/win10-arm64/**",
500 ]);
501 assert.deepStrictEqual(resolveWindowsServerAsarIgnoreGlobs("arm64"), [
502 ...WINDOWS_SERVER_ASAR_IGNORE_GLOBS,
503 "**/node_modules/node-pty/prebuilds/win32-x64",
504 "**/node_modules/node-pty/prebuilds/win32-x64/**",
505 "**/node_modules/node-pty/third_party/conpty/*/win10-x64",
506 "**/node_modules/node-pty/third_party/conpty/*/win10-x64/**",
507 ]);
508 });
509
510 it.effect(
511 "keeps target and WSL native files while excluding the other Windows architecture",
512 () =>
513 Effect.scoped(
514 Effect.gen(function* () {
515 const fs = yield* FileSystem.FileSystem;
516 const path = yield* Path.Path;
517 const tempDir = yield* fs.makeTempDirectoryScoped({
518 prefix: "t3-windows-architecture-test-",
519 });
520 const sourceDir = path.join(tempDir, "server");
521 const nativeFiles = [
522 "node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe",
523 "node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe",
524 "node_modules/node-pty/prebuilds/linux-x64/pty.node",
525 "node_modules/node-pty/third_party/conpty/1.0.0/win10-x64/OpenConsole.exe",
526 "node_modules/node-pty/third_party/conpty/1.0.0/win10-arm64/OpenConsole.exe",
527 ];
528
529 for (const nativeFile of nativeFiles) {
530 const nativePath = path.join(sourceDir, nativeFile);
531 yield* fs.makeDirectory(path.dirname(nativePath), { recursive: true });
532 yield* fs.writeFileString(nativePath, "native");
533 }
534
535 const asarPath = path.join(tempDir, "server.asar");
536 yield* packWindowsServerAsar({ sourceDir, asarPath, arch: "x64" });
537 const unpackedRoot = `${asarPath}.unpacked`;
538
539 assert.isTrue(
540 yield* fs.exists(
541 path.join(
542 unpackedRoot,
543 "node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe",
544 ),
545 ),
546 );
547 assert.isTrue(
548 yield* fs.exists(
549 path.join(unpackedRoot, "node_modules/node-pty/prebuilds/linux-x64/pty.node"),
550 ),
551 );
552 assert.isFalse(
553 yield* fs.exists(
554 path.join(unpackedRoot, "node_modules/node-pty/prebuilds/win32-arm64"),
555 ),
556 );
557 assert.isFalse(
558 yield* fs.exists(
559 path.join(unpackedRoot, "node_modules/node-pty/third_party/conpty/1.0.0/win10-arm64"),
560 ),
561 );
562 }),
563 ),
564 );
565
566 it.effect("stages a cached resource monitor without invoking Cargo", () =>
567 Effect.scoped(
568 Effect.gen(function* () {
569 const fs = yield* FileSystem.FileSystem;
570 const path = yield* Path.Path;
571 const repoRoot = yield* fs.makeTempDirectoryScoped({
572 prefix: "t3-resource-monitor-cache-test-",
573 });
574 const binaryPath = path.join(
575 repoRoot,
576 "native/resource-monitor/target/x86_64-unknown-linux-gnu/release/t3-resource-monitor",
577 );
578 const stageResourcesDir = path.join(repoRoot, "stage");
579 yield* fs.makeDirectory(path.dirname(binaryPath), { recursive: true });
580 yield* fs.writeFileString(binaryPath, "cached monitor");
581
582 yield* stageResourceMonitor({
583 repoRoot,
584 stageResourcesDir,
585 platform: "linux",
586 arch: "x64",
587 verbose: false,
588 }).pipe(
589 Effect.provide(
590 ConfigProvider.layer(
591 ConfigProvider.fromEnv({
592 env: { T3CODE_DESKTOP_REUSE_RESOURCE_MONITOR: "true" },
593 }),
594 ),
595 ),
596 );
597
598 assert.equal(
599 yield* fs.readFileString(
600 path.join(stageResourcesDir, "resource-monitor/t3-resource-monitor"),
601 ),
602 "cached monitor",
603 );
604 }),
605 ),
606 );
607
491608 it.effect("validates every ASAR-unpacked native in the packaged Windows payload", () =>
492609 Effect.scoped(
493610 Effect.gen(function* () {
......@@ -504,6 +621,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => {
504621 yield* packWindowsServerAsar({
505622 sourceDir: fixture.sourceDir,
506623 asarPath: secondAsarPath,
624 arch: "x64",
507625 });
508626 const [firstAsar, secondAsar] = yield* Effect.all([
509627 fs.readFile(fixture.generatedAsarPath),
scripts/build-desktop-artifact.ts+50-22
......@@ -819,6 +819,21 @@ export const WINDOWS_SERVER_ASAR_IGNORE_GLOBS = [
819819 "**/node_modules/.bin",
820820 "**/node_modules/.bin/**",
821821] as const;
822
823export function resolveWindowsServerAsarIgnoreGlobs(arch: typeof BuildArch.Type) {
824 const unusedArch = arch === "arm64" ? "x64" : "arm64";
825 const unusedPrebuild = `**/node_modules/node-pty/prebuilds/win32-${unusedArch}`;
826 const unusedConpty = `**/node_modules/node-pty/third_party/conpty/*/win10-${unusedArch}`;
827
828 return [
829 ...WINDOWS_SERVER_ASAR_IGNORE_GLOBS,
830 unusedPrebuild,
831 `${unusedPrebuild}/**`,
832 unusedConpty,
833 `${unusedConpty}/**`,
834 ];
835}
836
822837export const WINDOWS_PACKAGED_PAYLOAD_FILE_LIMIT = 80;
823838export const WINDOWS_SERVER_RESOURCE_SOURCE_DIR = "apps/desktop/prod-resources/windows-server";
824839export const WINDOWS_SERVER_EXTRA_RESOURCES = [
......@@ -1643,7 +1658,7 @@ const verifyPackagedBundleIsSelfContained = Effect.fn("verifyPackagedBundleIsSel
16431658 },
16441659);
16451660
1646const stageResourceMonitor = Effect.fn("stageResourceMonitor")(function* (input: {
1661export const stageResourceMonitor = Effect.fn("stageResourceMonitor")(function* (input: {
16471662 readonly repoRoot: string;
16481663 readonly stageResourcesDir: string;
16491664 readonly platform: typeof BuildPlatform.Type;
......@@ -1655,28 +1670,33 @@ const stageResourceMonitor = Effect.fn("stageResourceMonitor")(function* (input:
16551670 const manifestPath = path.join(input.repoRoot, "native/resource-monitor/Cargo.toml");
16561671 const executableName = resourceMonitorExecutableName(input.platform);
16571672 const rustTargets = resolveResourceMonitorRustTargets(input.platform, input.arch);
1673 const reuseResourceMonitor = yield* Config.boolean("T3CODE_DESKTOP_REUSE_RESOURCE_MONITOR").pipe(
1674 Config.withDefault(false),
1675 );
16581676 const builtBinaries: string[] = [];
16591677
16601678 for (const rustTarget of rustTargets) {
1661 const spawnCommand = yield* resolveSpawnCommand("cargo", [
1662 "build",
1663 "--locked",
1664 "--release",
1665 "--manifest-path",
1666 manifestPath,
1667 "--target",
1668 rustTarget,
1669 ]);
1670 yield* runCommand(
1671 ChildProcess.make(spawnCommand.command, spawnCommand.args, {
1672 cwd: input.repoRoot,
1673 shell: spawnCommand.shell,
1674 }),
1675 {
1676 label: `cargo build resource monitor (${rustTarget})`,
1677 verbose: input.verbose,
1678 },
1679 );
1679 if (!reuseResourceMonitor) {
1680 const spawnCommand = yield* resolveSpawnCommand("cargo", [
1681 "build",
1682 "--locked",
1683 "--release",
1684 "--manifest-path",
1685 manifestPath,
1686 "--target",
1687 rustTarget,
1688 ]);
1689 yield* runCommand(
1690 ChildProcess.make(spawnCommand.command, spawnCommand.args, {
1691 cwd: input.repoRoot,
1692 shell: spawnCommand.shell,
1693 }),
1694 {
1695 label: `cargo build resource monitor (${rustTarget})`,
1696 verbose: input.verbose,
1697 },
1698 );
1699 }
16801700
16811701 const binaryPath = path.join(
16821702 input.repoRoot,
......@@ -1693,6 +1713,9 @@ const stageResourceMonitor = Effect.fn("stageResourceMonitor")(function* (input:
16931713 arch: input.arch,
16941714 });
16951715 }
1716 if (reuseResourceMonitor) {
1717 yield* Effect.log(`[desktop-artifact] Reusing cached resource monitor (${rustTarget}).`);
1718 }
16961719 builtBinaries.push(binaryPath);
16971720 }
16981721
......@@ -2253,6 +2276,7 @@ const stageWslNodePtyPrebuild = Effect.fn("stageWslNodePtyPrebuild")(function* (
22532276export const packWindowsServerAsar = Effect.fn("packWindowsServerAsar")(function* (input: {
22542277 readonly sourceDir: string;
22552278 readonly asarPath: string;
2279 readonly arch: typeof BuildArch.Type;
22562280}) {
22572281 const fs = yield* FileSystem.FileSystem;
22582282 yield* Effect.tryPromise({
......@@ -2260,7 +2284,7 @@ export const packWindowsServerAsar = Effect.fn("packWindowsServerAsar")(function
22602284 createPackageWithOptions(input.sourceDir, input.asarPath, {
22612285 dot: true,
22622286 unpack: WINDOWS_SERVER_ASAR_UNPACK_GLOB,
2263 globOptions: { ignore: [...WINDOWS_SERVER_ASAR_IGNORE_GLOBS] },
2287 globOptions: { ignore: resolveWindowsServerAsarIgnoreGlobs(input.arch) },
22642288 }),
22652289 catch: (cause) => new WindowsServerSidecarPackError({ asarPath: input.asarPath, cause }),
22662290 });
......@@ -2354,7 +2378,11 @@ export const stageWindowsServerSidecar = Effect.fn("stageWindowsServerSidecar")(
23542378
23552379 yield* Effect.log("[desktop-artifact] Packing server.asar...");
23562380 yield* fs.makeDirectory(path.dirname(input.asarPath), { recursive: true });
2357 yield* packWindowsServerAsar({ sourceDir: serverStageDir, asarPath: input.asarPath });
2381 yield* packWindowsServerAsar({
2382 sourceDir: serverStageDir,
2383 asarPath: input.asarPath,
2384 arch: input.arch,
2385 });
23582386 const packedStat = yield* fs.stat(input.asarPath);
23592387 yield* Effect.log(
23602388 `[desktop-artifact] Packed server.asar (${String(packedStat.size)} bytes) + unpacked natives.`,