Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[build]
# Keep intermediate artifacts outside the checkout so every clone and worktree
# on a machine shares one copy instead of each rebuilding the dependency graph.
# {cargo-cache-home} expands to CARGO_HOME, so this is portable: no absolute
# path, no assumption about where the repo lives. Cargo does not expand ~ or
# $HOME, and target-dir does not support templating, so build-dir is the only
# form that gets this.
#
# Final artifacts still land in <checkout>/target, so anything locating a built
# binary by path keeps working.
build-dir = "{cargo-cache-home}/build/browseros"
69 changes: 69 additions & 0 deletions .github/workflows/rust-cache-bust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Rust Cache Bust

# The shared cargo build directory is cached as an extra `cache-directories`
# entry, and rust-cache prunes only workspace target dirs, never extra ones. So
# that entry is cached wholesale and accumulates artifacts for dependencies and
# profiles that no longer exist. Left alone it grows against the repository's
# 10GB Actions cache allowance and evicts entries that are still wanted.
#
# Dropping it on a schedule keeps that bounded. The next warm run rebuilds it
# from scratch, so the only cost is one cold Rust compile.
on:
schedule:
# 1st and 15th, so roughly fortnightly. Ahead of the Monday 06:00 warm run
# rather than alongside it, and the warm workflow is dispatched below in any
# case so a fresh cache does not wait for the next merge.
- cron: "0 5 1,15 * *"
workflow_dispatch:

permissions:
actions: write

concurrency:
group: rust-cache-bust
cancel-in-progress: false

jobs:
bust:
name: Drop Rust caches
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Delete Rust caches
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
# rust-cache prefixes every key it writes with `prefix-key`, which is
# left at its default. Matching on that keeps Turbo and any other
# cache in this repository untouched.
ids="$(gh api --paginate "/repos/$REPO/actions/caches?per_page=100" \
--jq '.actions_caches[] | select(.key | startswith("v0-rust")) | .id')"

if [ -z "$ids" ]; then
echo "No Rust caches to drop."
echo "No Rust caches to drop." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi

count=0
while read -r id; do
[ -n "$id" ] || continue
gh api -X DELETE "/repos/$REPO/actions/caches/$id"
count=$((count + 1))
done <<< "$ids"

echo "Dropped $count Rust cache entries."
echo "Dropped $count Rust cache entries." >> "$GITHUB_STEP_SUMMARY"

- name: Request a fresh warm run
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
# Rebuild immediately rather than leaving every branch cold until the
# next merge or the Monday schedule.
gh workflow run turbo-cache-warm.yml --repo "$REPO" --ref main
echo "Dispatched Turbo Cache Warm on main." >> "$GITHUB_STEP_SUMMARY"
8 changes: 8 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ jobs:
uses: Swatinem/rust-cache@v2
with:
workspaces: packages/browseros-agent
# Without this the key embeds GITHUB_JOB, so the warm cache produced
# on main by a differently named job could never be restored here.
shared-key: browseros-agent
# Intermediate artifacts live outside the checkout so worktrees can
# share them, and rust-cache only saves workspace target dirs plus the
# registry and git caches by default. Name the build dir explicitly or
# every run would recompile the dependency graph from scratch.
cache-directories: ~/.cargo/build/browseros

- name: Install dependencies
run: bun ci
Expand Down
45 changes: 41 additions & 4 deletions .github/workflows/turbo-cache-warm.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
name: Turbo Cache Warm

# Populates the Turbo cache on `main` so PR branches inherit warm cache.
# GitHub Actions caches restore only from the same branch or the base/default
# branch, so without a run on `main` every PR would start cold. Neither the
# Tests nor Code Quality workflows run on `main`, so this is that run.
# Populates the Turbo and Rust caches on `main` so PR branches inherit warm
# cache. GitHub Actions caches restore only from the same branch or the
# base/default branch, so without a run on `main` every PR would start cold.
# Neither the Tests nor Code Quality workflows run on `main`, so this is that
# run.
on:
push:
branches: [main]
paths:
- .github/workflows/turbo-cache-warm.yml
- .cargo/config.toml
- packages/browseros-agent/**
schedule:
# Weekly full warm to backstop GitHub's 7-day unused-cache eviction for
Expand Down Expand Up @@ -63,3 +65,38 @@ jobs:
# Per-merge: warm only what this merge changed.
bunx turbo run typecheck --affected
fi

warm-rust:
name: Warm Rust cache
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Checkout code
uses: actions/checkout@v7

- name: Setup Rust
# Pinned to match the Tests workflow. A different toolchain hashes into
# a different cache key, which would warm a cache nothing else reads.
uses: dtolnay/rust-toolchain@1.95.0
with:
components: clippy,rustfmt

- name: Cache Rust build
uses: Swatinem/rust-cache@v2
with:
workspaces: packages/browseros-agent
# Must match the Tests workflow exactly. Without it the key embeds
# GITHUB_JOB and this cache would be unreadable there.
shared-key: browseros-agent
cache-directories: ~/.cargo/build/browseros
# Save even though nothing here is a pass/fail gate; warming is the
# entire point of the job.
save-if: "true"

- name: Warm Rust cache
# Mirrors what the Rust suites compile: test binaries and clippy's
# separate artifacts. -D warnings is deliberately omitted, since this
# job exists to populate a cache, not to gate on lints.
run: |
cargo test --workspace --locked --no-run
cargo clippy --workspace --all-targets --locked
Loading