Skip to content

Commit 8dd75a3

Browse files
ci: cache the Linux capture helpers and test the new crates
Release builds compiled the KDE and Hyprland helpers unconditionally while only installing Rust on a resource-monitor cache miss. Cache both binaries keyed on their crate sources, skip the build on a hit, and keep the toolchain step when either cache misses. The Rust CI job now formats and tests all three crates. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent c4000a3 commit 8dd75a3

3 files changed

Lines changed: 69 additions & 37 deletions

File tree

.github/workflows/ci.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,17 @@ jobs:
198198
with:
199199
components: rustfmt
200200

201-
- name: Check resource monitor formatting
202-
run: cargo fmt --manifest-path native/resource-monitor/Cargo.toml -- --check
201+
- name: Check Rust formatting
202+
run: |
203+
for crate in resource-monitor kde-snap-shot hyprland-snap-shot; do
204+
cargo fmt --manifest-path "native/$crate/Cargo.toml" -- --check
205+
done
203206
204-
- name: Test resource monitor
205-
run: cargo test --locked --manifest-path native/resource-monitor/Cargo.toml
207+
- name: Test Rust crates
208+
run: |
209+
for crate in resource-monitor kde-snap-shot hyprland-snap-shot; do
210+
cargo test --locked --manifest-path "native/$crate/Cargo.toml"
211+
done
206212
207213
# The static analysis below needs a macOS runner, which bills ~6.7x a Linux
208214
# minute, so gate it on the native sources it actually lints instead of paying

.github/workflows/release.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,18 @@ jobs:
487487
path: native/resource-monitor/target/${{ matrix.rust_target }}/release/t3-resource-monitor${{ matrix.platform == 'win' && '.exe' || '' }}
488488
key: resource-monitor-${{ matrix.rust_target }}-${{ hashFiles('native/resource-monitor/Cargo.lock', 'native/resource-monitor/Cargo.toml', 'native/resource-monitor/src/**') }}
489489

490+
- name: Cache Linux capture helpers
491+
if: matrix.platform == 'linux'
492+
id: capture_helper_cache
493+
uses: actions/cache@v6
494+
with:
495+
path: |
496+
native/kde-snap-shot/target/${{ matrix.rust_target }}/release/t3-kde-snap-shot
497+
native/hyprland-snap-shot/target/${{ matrix.rust_target }}/release/t3-hyprland-snap-shot
498+
key: linux-capture-helpers-${{ matrix.rust_target }}-${{ hashFiles('native/kde-snap-shot/Cargo.lock', 'native/kde-snap-shot/Cargo.toml', 'native/kde-snap-shot/src/**', 'native/hyprland-snap-shot/Cargo.lock', 'native/hyprland-snap-shot/Cargo.toml', 'native/hyprland-snap-shot/src/**', 'native/hyprland-snap-shot/protocols/**') }}
499+
490500
- name: Setup Rust
491-
if: steps.resource_monitor_cache.outputs.cache-hit != 'true'
501+
if: steps.resource_monitor_cache.outputs.cache-hit != 'true' || (matrix.platform == 'linux' && steps.capture_helper_cache.outputs.cache-hit != 'true')
492502
uses: dtolnay/rust-toolchain@stable
493503
with:
494504
targets: ${{ matrix.rust_target }}
@@ -620,6 +630,7 @@ jobs:
620630
env:
621631
pnpm_config_cache_dir: ${{ runner.temp }}/pnpm-metadata
622632
T3CODE_DESKTOP_REUSE_RESOURCE_MONITOR: ${{ steps.resource_monitor_cache.outputs.cache-hit == 'true' }}
633+
T3CODE_DESKTOP_REUSE_LINUX_CAPTURE_HELPERS: ${{ steps.capture_helper_cache.outputs.cache-hit == 'true' }}
623634
CSC_LINK: ${{ secrets.CSC_LINK }}
624635
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
625636
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}

scripts/build-desktop-artifact.ts

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,16 +1767,19 @@ export const preflightLinuxDesktopBuild = Effect.fn("preflightLinuxDesktopBuild"
17671767
const reuseResourceMonitor = yield* Config.boolean("T3CODE_DESKTOP_REUSE_RESOURCE_MONITOR").pipe(
17681768
Config.withDefault(false),
17691769
);
1770+
const reuseCaptureHelpers = yield* Config.boolean(
1771+
"T3CODE_DESKTOP_REUSE_LINUX_CAPTURE_HELPERS",
1772+
).pipe(Config.withDefault(false));
1773+
// Rust is only optional when every Linux Rust artifact comes from a cache.
1774+
const needsRust = !reuseResourceMonitor || !reuseCaptureHelpers;
17701775
const rustTarget = resolveResourceMonitorRustTargets("linux", arch)[0]!;
17711776

17721777
const checks = yield* Effect.all(
17731778
{
1774-
cargo: reuseResourceMonitor
1775-
? Effect.succeed(true)
1776-
: desktopBuildProbeSucceeds(ChildProcess.make("cargo", ["--version"]), "cargo"),
1777-
"rust-target": reuseResourceMonitor
1778-
? Effect.succeed(true)
1779-
: rustTargetIsInstalled(rustTarget),
1779+
cargo: needsRust
1780+
? desktopBuildProbeSucceeds(ChildProcess.make("cargo", ["--version"]), "cargo")
1781+
: Effect.succeed(true),
1782+
"rust-target": needsRust ? rustTargetIsInstalled(rustTarget) : Effect.succeed(true),
17801783
cc: desktopBuildProbeSucceeds(ChildProcess.make("cc", ["--version"]), "cc"),
17811784
make: desktopBuildProbeSucceeds(ChildProcess.make("make", ["--version"]), "make"),
17821785
libsecret: desktopBuildProbeSucceeds(
@@ -2176,37 +2179,49 @@ export const stageLinuxCaptureHelper = Effect.fn("stageLinuxCaptureHelper")(func
21762179
const fs = yield* FileSystem.FileSystem;
21772180
const path = yield* Path.Path;
21782181
const [rustTarget] = resolveResourceMonitorRustTargets("linux", input.arch);
2179-
const spawnCommand = yield* resolveSpawnCommand("cargo", [
2180-
"build",
2181-
"--locked",
2182-
"--release",
2183-
"--manifest-path",
2184-
path.join(input.repoRoot, `native/${input.backend}-snap-shot/Cargo.toml`),
2185-
"--target",
2182+
// Release CI restores these binaries from a cache keyed on the crate sources and
2183+
// skips the Rust toolchain on a hit, so the build must be skippable too.
2184+
const reuseHelpers = yield* Config.boolean("T3CODE_DESKTOP_REUSE_LINUX_CAPTURE_HELPERS").pipe(
2185+
Config.withDefault(false),
2186+
);
2187+
const binaryPath = path.join(
2188+
input.repoRoot,
2189+
`native/${input.backend}-snap-shot/target`,
21862190
rustTarget!,
2187-
]);
2188-
yield* runCommand(
2189-
ChildProcess.make(spawnCommand.command, spawnCommand.args, {
2190-
cwd: input.repoRoot,
2191-
shell: spawnCommand.shell,
2192-
}),
2193-
{
2194-
label: `cargo build ${input.backend} capture helper (${rustTarget})`,
2195-
verbose: input.verbose,
2196-
},
2191+
`release/t3-${input.backend}-snap-shot`,
21972192
);
2193+
if (!reuseHelpers) {
2194+
const spawnCommand = yield* resolveSpawnCommand("cargo", [
2195+
"build",
2196+
"--locked",
2197+
"--release",
2198+
"--manifest-path",
2199+
path.join(input.repoRoot, `native/${input.backend}-snap-shot/Cargo.toml`),
2200+
"--target",
2201+
rustTarget!,
2202+
]);
2203+
yield* runCommand(
2204+
ChildProcess.make(spawnCommand.command, spawnCommand.args, {
2205+
cwd: input.repoRoot,
2206+
shell: spawnCommand.shell,
2207+
}),
2208+
{
2209+
label: `cargo build ${input.backend} capture helper (${rustTarget})`,
2210+
verbose: input.verbose,
2211+
},
2212+
);
2213+
} else if (!(yield* fs.exists(binaryPath))) {
2214+
return yield* new ResourceMonitorBuildOutputMissingError({
2215+
binaryPath,
2216+
rustTarget: rustTarget!,
2217+
platform: "linux",
2218+
arch: input.arch,
2219+
});
2220+
}
21982221
const destination = path.join(input.stageResourcesDir, `${input.backend}-capture`);
21992222
yield* fs.makeDirectory(destination, { recursive: true });
22002223
const executable = path.join(destination, `t3-${input.backend}-snap-shot`);
2201-
yield* fs.copyFile(
2202-
path.join(
2203-
input.repoRoot,
2204-
`native/${input.backend}-snap-shot/target`,
2205-
rustTarget!,
2206-
`release/t3-${input.backend}-snap-shot`,
2207-
),
2208-
executable,
2209-
);
2224+
yield* fs.copyFile(binaryPath, executable);
22102225
yield* fs.chmod(executable, 0o755);
22112226
if (input.backend === "hyprland") {
22122227
// The official protocol XML includes the BSD notices required with binary distribution.

0 commit comments

Comments
 (0)