diff --git a/.github/workflows/cache-warm.yml b/.github/workflows/cache-warm.yml new file mode 100644 index 000000000..f5ff88334 --- /dev/null +++ b/.github/workflows/cache-warm.yml @@ -0,0 +1,102 @@ +name: Warm CI cache + +# WHY THIS EXISTS +# --------------- +# The `Tests` workflow (test.yml) runs ONLY on pull_request + version tags — +# never on push to main. GitHub Actions cache scoping means a run can only +# restore caches saved on its OWN branch or on the DEFAULT branch (main); one +# PR can never read another PR's cache. So with nothing running the cache- +# producing build on main, no main-scoped cache ever existed, and every PR +# started cold: +# - Swatinem/rust-cache in test.yml has `save-if: refs/heads/main`, but +# test.yml never runs on main → it never saved target/. +# - sccache (now a persisted disk cache, v0.5.1179) likewise only saw +# PR-scoped saves, invisible to other PRs. +# Result: cargo-test recompiled the whole dependency graph cold every run +# (~90-103 min), tipping over its timeout on perry-runtime/perry-codegen PRs. +# +# This workflow runs the cache-producing build ONCE per main merge so the +# main-scoped rust-cache (target/) and sccache disk cache exist for every PR +# to restore. It uses the SAME shared-key / sccache key prefix as test.yml's +# jobs, so those jobs warm-restore from here. It is best-effort +# (continue-on-error), never a gate. +on: + push: + branches: [main] + paths: + - 'crates/**' + - 'Cargo.toml' + - 'Cargo.lock' + - '.github/workflows/cache-warm.yml' + workflow_dispatch: + +concurrency: + # Only the latest main commit needs a warm cache; cancel older in-flight warms. + group: cache-warm-${{ github.ref }} + cancel-in-progress: true + +jobs: + warm: + runs-on: ubuntu-latest + # Best-effort cache population — must never block or fail anything. + continue-on-error: true + # Comfortably above the cold first run; later runs are far shorter. + timeout-minutes: 120 + env: + RUSTC_WRAPPER: sccache + # Mirror test.yml's sccache config EXACTLY (local disk cache, NOT the GHA + # backend) so the cache this job saves is byte-compatible with what the + # cargo-test / api-docs-drift / compiler-output-regression jobs restore. + SCCACHE_GHA_ENABLED: "false" + SCCACHE_DIR: ${{ github.workspace }}/.sccache + SCCACHE_CACHE_SIZE: "12G" + CARGO_INCREMENTAL: "0" + # Keep artifacts small so building the heavy crates' test binaries does + # not exhaust the shared-runner disk (same reason test.yml sets these). + CARGO_PROFILE_TEST_DEBUG: "0" + CARGO_PROFILE_DEV_DEBUG: "0" + CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS: "-C linker-features=-lld" + steps: + - uses: actions/checkout@v6 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.10 + + # Save the sccache disk cache under the SAME prefix test.yml restores + # (`sccache--perry-`). This runs on main, so the saved entry is + # main-scoped → restorable by every PR. run_id keeps the key unique. + - name: Cache sccache objects + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}/.sccache + key: sccache-${{ runner.os }}-perry-warm-${{ github.run_id }} + restore-keys: | + sccache-${{ runner.os }}-perry- + + # Same shared-key as test.yml; save-if true because this only runs on main. + - uses: Swatinem/rust-cache@v2 + with: + shared-key: "${{ runner.os }}-perry" + save-if: "true" + + # Compile (do NOT run) the test binaries of the heaviest crates. This + # pulls in essentially the entire third-party dependency graph plus the + # big first-party crates — the bulk of cargo-test's compile time — so the + # cheap ext-* crates that follow in cargo-test reuse the cached units. + # `--no-run` skips execution (this is a cache warm, not a test run); the + # per-crate prune keeps target/ under the runner's disk budget. + - name: Warm build (heavy crates) + run: | + for pkg in perry-runtime perry-stdlib perry-codegen perry; do + echo "::group::cargo test -p $pkg --no-run" + cargo test -p "$pkg" --no-run + echo "::endgroup::" + find target/debug/deps -maxdepth 1 -type f -perm -111 ! -name '*.so' -delete || true + done + + - name: sccache stats + if: always() + run: sccache --show-stats || true diff --git a/CHANGELOG.md b/CHANGELOG.md index d3abe8f7c..41e622c6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +## v0.5.1180 — ci: warm the main-scoped CI cache so PRs stop building cold + +Follow-up to v0.5.1179. Moving sccache to a persisted disk cache was necessary +but not sufficient: `test.yml` runs only on pull_request + version tags, never +on push to main. GitHub Actions cache scoping lets a run restore caches from its +own branch or the default branch (main) — but never another PR's — so with +nothing running the cache-producing build on main, no main-scoped cache ever +existed and every PR started cold. (The same flaw silently disabled +`Swatinem/rust-cache`: its `save-if: refs/heads/main` never fired because +test.yml doesn't run on main, so target/ was never saved either.) + +New `cache-warm.yml`: on every push to main that touches Rust (`crates/**`, +`Cargo.toml`, `Cargo.lock`), compile — `--no-run` — the test binaries of the +heaviest crates (`perry-runtime`, `perry-stdlib`, `perry-codegen`, `perry`), +which pull in essentially the whole dependency graph. It saves under the SAME +`rust-cache` shared-key (`-perry`) and sccache key prefix +(`sccache--perry-`) that test.yml's jobs restore, so the main-scoped caches +now exist for every PR to pick up. The job is `continue-on-error` (a cache warm, +never a gate), prunes test binaries between crates to stay within the runner +disk budget, and uses `concurrency` to cancel superseded warms. + +Expected effect: after the first warm run lands on main, PR `cargo-test` should +restore a warm cache and run ~50-60 min instead of ~90-103 min cold. No +production code changes. + ## v0.5.1179 — ci: move sccache off the GHA backend onto a persisted disk cache (fix cargo-test timeouts) The `cargo-test` gate was timing out at its 120-min cap on PRs that touch diff --git a/CLAUDE.md b/CLAUDE.md index aa7d00e8b..c77fd6639 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Perry is a native TypeScript compiler written in Rust that compiles TypeScript source code directly to native executables. It uses SWC for TypeScript parsing and LLVM for code generation. -**Current Version:** 0.5.1179 +**Current Version:** 0.5.1180 ## TypeScript Parity Status diff --git a/Cargo.lock b/Cargo.lock index 90badcca3..91d41f35c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5283,7 +5283,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perry" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "base64", @@ -5340,14 +5340,14 @@ dependencies = [ [[package]] name = "perry-api-manifest" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "serde", ] [[package]] name = "perry-audio-miniaudio" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "cc", "libc", @@ -5355,7 +5355,7 @@ dependencies = [ [[package]] name = "perry-codegen" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "log", @@ -5370,7 +5370,7 @@ dependencies = [ [[package]] name = "perry-codegen-arkts" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-hir", @@ -5379,7 +5379,7 @@ dependencies = [ [[package]] name = "perry-codegen-glance" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-hir", @@ -5387,7 +5387,7 @@ dependencies = [ [[package]] name = "perry-codegen-js" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-dispatch", @@ -5397,7 +5397,7 @@ dependencies = [ [[package]] name = "perry-codegen-swiftui" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-hir", @@ -5406,7 +5406,7 @@ dependencies = [ [[package]] name = "perry-codegen-wasm" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "base64", @@ -5419,7 +5419,7 @@ dependencies = [ [[package]] name = "perry-codegen-wear-tiles" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-hir", @@ -5427,7 +5427,7 @@ dependencies = [ [[package]] name = "perry-container-compose" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "async-trait", @@ -5456,14 +5456,14 @@ dependencies = [ [[package]] name = "perry-container-e2e" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", ] [[package]] name = "perry-diagnostics" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "serde", "serde_json", @@ -5471,7 +5471,7 @@ dependencies = [ [[package]] name = "perry-dispatch" -version = "0.5.1179" +version = "0.5.1180" [[package]] name = "perry-doc-fixture-my-bindings" @@ -5482,7 +5482,7 @@ dependencies = [ [[package]] name = "perry-doc-tests" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "clap", @@ -5497,14 +5497,14 @@ dependencies = [ [[package]] name = "perry-ext-ads" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-argon2" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "argon2", "perry-ffi", @@ -5512,7 +5512,7 @@ dependencies = [ [[package]] name = "perry-ext-axios" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "reqwest", @@ -5521,7 +5521,7 @@ dependencies = [ [[package]] name = "perry-ext-bcrypt" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "bcrypt", "perry-ffi", @@ -5529,7 +5529,7 @@ dependencies = [ [[package]] name = "perry-ext-better-sqlite3" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "rusqlite", @@ -5537,7 +5537,7 @@ dependencies = [ [[package]] name = "perry-ext-cheerio" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "scraper", @@ -5545,7 +5545,7 @@ dependencies = [ [[package]] name = "perry-ext-commander" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "perry-runtime", @@ -5553,7 +5553,7 @@ dependencies = [ [[package]] name = "perry-ext-cron" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "chrono", "cron 0.16.0", @@ -5563,7 +5563,7 @@ dependencies = [ [[package]] name = "perry-ext-dayjs" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "chrono", "perry-ffi", @@ -5571,7 +5571,7 @@ dependencies = [ [[package]] name = "perry-ext-decimal" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "rust_decimal", @@ -5579,7 +5579,7 @@ dependencies = [ [[package]] name = "perry-ext-dotenv" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "serde_json", @@ -5587,7 +5587,7 @@ dependencies = [ [[package]] name = "perry-ext-ethers" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "rand 0.8.6", @@ -5595,7 +5595,7 @@ dependencies = [ [[package]] name = "perry-ext-events" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "perry-runtime", @@ -5603,14 +5603,14 @@ dependencies = [ [[package]] name = "perry-ext-exponential-backoff" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-fastify" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "bytes", "http-body-util", @@ -5627,7 +5627,7 @@ dependencies = [ [[package]] name = "perry-ext-fetch" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "lazy_static", "perry-ffi", @@ -5639,7 +5639,7 @@ dependencies = [ [[package]] name = "perry-ext-http" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "lazy_static", "perry-ext-http-server", @@ -5652,7 +5652,7 @@ dependencies = [ [[package]] name = "perry-ext-http-server" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "bytes", "h2", @@ -5675,7 +5675,7 @@ dependencies = [ [[package]] name = "perry-ext-ioredis" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "lazy_static", "perry-ffi", @@ -5685,7 +5685,7 @@ dependencies = [ [[package]] name = "perry-ext-jsonwebtoken" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "jsonwebtoken", @@ -5696,7 +5696,7 @@ dependencies = [ [[package]] name = "perry-ext-lru-cache" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "lru", "perry-ffi", @@ -5704,7 +5704,7 @@ dependencies = [ [[package]] name = "perry-ext-moment" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "chrono", "perry-ffi", @@ -5712,7 +5712,7 @@ dependencies = [ [[package]] name = "perry-ext-mongodb" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "bson", "futures-util", @@ -5724,7 +5724,7 @@ dependencies = [ [[package]] name = "perry-ext-mysql2" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "chrono", "perry-ffi", @@ -5734,7 +5734,7 @@ dependencies = [ [[package]] name = "perry-ext-nanoid" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "nanoid", "perry-ffi", @@ -5743,7 +5743,7 @@ dependencies = [ [[package]] name = "perry-ext-net" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "perry-runtime", @@ -5755,7 +5755,7 @@ dependencies = [ [[package]] name = "perry-ext-nodemailer" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "lettre", "perry-ffi", @@ -5765,7 +5765,7 @@ dependencies = [ [[package]] name = "perry-ext-pdf" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "printpdf", @@ -5773,7 +5773,7 @@ dependencies = [ [[package]] name = "perry-ext-pg" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "sqlx", @@ -5782,7 +5782,7 @@ dependencies = [ [[package]] name = "perry-ext-ratelimit" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "governor", "perry-ffi", @@ -5790,7 +5790,7 @@ dependencies = [ [[package]] name = "perry-ext-sharp" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "image", @@ -5799,14 +5799,14 @@ dependencies = [ [[package]] name = "perry-ext-slugify" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", ] [[package]] name = "perry-ext-streams" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "lazy_static", "perry-ffi", @@ -5815,7 +5815,7 @@ dependencies = [ [[package]] name = "perry-ext-uuid" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "uuid", @@ -5823,7 +5823,7 @@ dependencies = [ [[package]] name = "perry-ext-validator" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ffi", "regex", @@ -5833,7 +5833,7 @@ dependencies = [ [[package]] name = "perry-ext-ws" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "futures-util", "lazy_static", @@ -5845,7 +5845,7 @@ dependencies = [ [[package]] name = "perry-ext-zlib" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "brotli", "flate2", @@ -5854,7 +5854,7 @@ dependencies = [ [[package]] name = "perry-ffi" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "dashmap", "once_cell", @@ -5863,7 +5863,7 @@ dependencies = [ [[package]] name = "perry-hir" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-api-manifest", @@ -5881,7 +5881,7 @@ dependencies = [ [[package]] name = "perry-parser" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-diagnostics", @@ -5893,7 +5893,7 @@ dependencies = [ [[package]] name = "perry-runtime" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "base64", @@ -5925,7 +5925,7 @@ dependencies = [ [[package]] name = "perry-stdlib" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "aes 0.8.4", "aes-gcm", @@ -6017,7 +6017,7 @@ dependencies = [ [[package]] name = "perry-transform" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "perry-hir", @@ -6027,7 +6027,7 @@ dependencies = [ [[package]] name = "perry-types" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "anyhow", "thiserror 1.0.69", @@ -6035,14 +6035,14 @@ dependencies = [ [[package]] name = "perry-ui" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ui-model", ] [[package]] name = "perry-ui-android" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "itoa", @@ -6059,7 +6059,7 @@ dependencies = [ [[package]] name = "perry-ui-geisterhand" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "rand 0.8.6", "serde", @@ -6069,7 +6069,7 @@ dependencies = [ [[package]] name = "perry-ui-gtk4" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "cairo-rs", @@ -6092,7 +6092,7 @@ dependencies = [ [[package]] name = "perry-ui-ios" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "block2", @@ -6108,7 +6108,7 @@ dependencies = [ [[package]] name = "perry-ui-macos" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "block2", @@ -6123,7 +6123,7 @@ dependencies = [ [[package]] name = "perry-ui-model" -version = "0.5.1179" +version = "0.5.1180" [[package]] name = "perry-ui-test" @@ -6131,11 +6131,11 @@ version = "0.1.0" [[package]] name = "perry-ui-testkit" -version = "0.5.1179" +version = "0.5.1180" [[package]] name = "perry-ui-tvos" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "block2", @@ -6151,7 +6151,7 @@ dependencies = [ [[package]] name = "perry-ui-visionos" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "block2", @@ -6167,7 +6167,7 @@ dependencies = [ [[package]] name = "perry-ui-watchos" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "block2", "libc", @@ -6180,7 +6180,7 @@ dependencies = [ [[package]] name = "perry-ui-windows" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "libc", @@ -6197,14 +6197,14 @@ dependencies = [ [[package]] name = "perry-ui-windows-winui" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "perry-ui-windows", ] [[package]] name = "perry-updater" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "base64", "ed25519-dalek", @@ -6218,7 +6218,7 @@ dependencies = [ [[package]] name = "perry-wasm-host" -version = "0.5.1179" +version = "0.5.1180" dependencies = [ "wasmi", ] diff --git a/Cargo.toml b/Cargo.toml index 3a8962848..9dc01af97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -215,7 +215,7 @@ strip = false codegen-units = 16 [workspace.package] -version = "0.5.1179" +version = "0.5.1180" edition = "2021" license = "MIT" repository = "https://github.com/PerryTS/perry"