From 8c0925a42671813216f6beaabf5c37baa926b889 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 15 Aug 2026 20:13:17 -0700 Subject: [PATCH 1/5] fix(ci): build the workspace once per e2e job --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index c968f901..58e12c53 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,7 @@ SMOKE_BIN := $(TARGET_DIR)/fff_c_smoke SMOKE_SRC := crates/fff-c/tests/smoke.c SMOKE_INCLUDE := crates/fff-c/include -test-c-smoke: build +test-c-smoke: build-e2e $(CC) $(CFLAGS) -I $(SMOKE_INCLUDE) -L $(TARGET_DIR) \ -Wl,-rpath,@loader_path/../target/release \ -Wl,-rpath,$$(pwd)/$(TARGET_DIR) \ @@ -136,7 +136,7 @@ test-c-api: test-c-smoke # neovim instance swallows internal crashes and doesn't rise the the error exiting silently # so check the stdout in case the sigsegv coming out of fff was printed (actual regression). # Output is streamed live via `tee`; pipefail (set above) propagates nvim's exit. -test-lua: test-setup build +test-lua: test-setup build-e2e @logfile=$$(mktemp); \ trap 'rm -f "$$logfile"' EXIT; \ nvim --headless -u tests/minimal_init.lua \ @@ -148,7 +148,7 @@ test-lua: test-setup build exit 1; \ fi -test-lua-snap: test-setup build +test-lua-snap: test-setup build-e2e @logfile=$$(mktemp); \ trap 'rm -f "$$logfile"' EXIT; \ nvim --headless -u tests/minimal_init.lua \ @@ -164,13 +164,13 @@ test-version: test-setup nvim --headless -u tests/minimal_init.lua \ -c "PlenaryBustedFile tests/version_spec.lua" 2>&1 -prepare-bun: build sync-js-api +prepare-bun: build-e2e sync-js-api mkdir -p packages/fff-bun/bin cp target/release/libfff_c.dylib packages/fff-bun/bin/ 2>/dev/null || true; \ cp target/release/libfff_c.so packages/fff-bun/bin/ 2>/dev/null || true; \ cp target/release/fff_c.dll packages/fff-bun/bin/ 2>/dev/null || true -prepare-node: build sync-js-api +prepare-node: build-e2e sync-js-api mkdir -p packages/fff-node/bin cp target/release/libfff_c.dylib packages/fff-node/bin/ 2>/dev/null || true; \ cp target/release/libfff_c.so packages/fff-node/bin/ 2>/dev/null || true; \ From 1029710010eaa7ec6a7bc436b884031ba8e3b307 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 15 Aug 2026 20:13:17 -0700 Subject: [PATCH 2/5] perf(ci): cache rust compilations with sccache --- .github/workflows/external-tests.yml | 14 +++++++++++++ .github/workflows/python.yml | 7 +++++++ .github/workflows/rust.yml | 31 +++++++++++++++++++++++++++- crates/fff-core/Cargo.toml | 2 +- 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/.github/workflows/external-tests.yml b/.github/workflows/external-tests.yml index 15e6d3e7..46544a03 100644 --- a/.github/workflows/external-tests.yml +++ b/.github/workflows/external-tests.yml @@ -29,6 +29,10 @@ jobs: runs-on: ${{ matrix.os }} # e2e tests could be flaky on CI so we do not block release creation if they failed continue-on-error: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }} + # alpine-musl installs rust via apk and has no sccache, so keep this scoped. + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: sccache strategy: fail-fast: false matrix: @@ -53,10 +57,20 @@ jobs: cache-key: "v2-lua-e2e" rustflags: "" + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Build Rust binary shell: bash run: make build-e2e + - name: sccache stats + if: always() + shell: bash + run: sccache --show-stats + - name: Verify Windows DLL has no unexpected dependencies if: matrix.os == 'windows-latest' shell: pwsh diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index ccc20632..2833352e 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -17,6 +17,8 @@ env: MACOSX_DEPLOYMENT_TARGET: "13.0" CARGO_PROFILE_RELEASE_LTO: thin CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 16 + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: sccache jobs: test: @@ -39,6 +41,11 @@ jobs: cache-on-failure: true cache-key: "v1-rust-python" + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Setup uv uses: astral-sh/setup-uv@v5 with: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 159b05c8..9aea096a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,6 +17,8 @@ env: # Ensure consistent macOS deployment target across all compiled objects # (Rust, cc-compiled C code, and Zig-compiled zlob) to avoid linker warnings MACOSX_DEPLOYMENT_TARGET: "13" + # RUSTC_WRAPPER is set per job, since cargo fmt runs without sccache. + SCCACHE_GHA_ENABLED: "true" jobs: test: @@ -46,7 +48,14 @@ jobs: cache-key: "v1-rust" components: rustfmt, clippy + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Run tests + env: + RUSTC_WRAPPER: sccache # fff-python requires full python o3 machinery which is very slow run: cargo test --no-default-features --features zlob --workspace --exclude fff-nvim --exclude fff-python @@ -66,6 +75,7 @@ jobs: FFF_STRESS_CASES: "5" FFF_STRESS_MIN_OPS: "30" FFF_STRESS_MAX_OPS: "60" + RUSTC_WRAPPER: sccache steps: - uses: actions/checkout@v5 @@ -82,6 +92,11 @@ jobs: cache-key: "v1-rust-stress-${{ matrix.os }}" components: rustfmt, clippy + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Stress test seeded shell: bash run: make test-stress-seeded @@ -125,7 +140,14 @@ jobs: cache-on-failure: true cache-key: "v1-rust-i686" + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Build fff-search for i686 + env: + RUSTC_WRAPPER: sccache run: cargo build -p fff-search --target i686-unknown-linux-gnu fmt: @@ -158,6 +180,13 @@ jobs: with: toolchain: stable components: clippy - + + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Run clippy + env: + RUSTC_WRAPPER: sccache run: cargo clippy --no-default-features --features zlob -- -D warnings diff --git a/crates/fff-core/Cargo.toml b/crates/fff-core/Cargo.toml index 5aafc8aa..afaf96dd 100644 --- a/crates/fff-core/Cargo.toml +++ b/crates/fff-core/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [lib] path = "src/lib.rs" -crate-type = ["rlib", "staticlib", "cdylib"] +crate-type = ["rlib"] [[bench]] name = "parse_bench" From aef657e50925e66d6483a99df4f42b63a7952608 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 15 Aug 2026 20:46:22 -0700 Subject: [PATCH 3/5] fix(ci): stop sccache idling out mid-compile and cancel superseded runs --- .github/workflows/external-tests.yml | 7 +++++++ .github/workflows/lua.yml | 4 ++++ .github/workflows/nix.yml | 4 ++++ .github/workflows/python.yml | 7 +++++++ .github/workflows/release.yaml | 4 ++++ .github/workflows/rust.yml | 7 +++++++ .github/workflows/spelling.yaml | 4 ++++ .github/workflows/stylua.yaml | 4 ++++ 8 files changed, 41 insertions(+) diff --git a/.github/workflows/external-tests.yml b/.github/workflows/external-tests.yml index 46544a03..bec4df35 100644 --- a/.github/workflows/external-tests.yml +++ b/.github/workflows/external-tests.yml @@ -23,6 +23,10 @@ env: CARGO_PROFILE_RELEASE_LTO: thin CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 16 +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} + jobs: lua-tests: name: e2e (${{ matrix.os }}) @@ -33,6 +37,9 @@ jobs: env: SCCACHE_GHA_ENABLED: "true" RUSTC_WRAPPER: sccache + # fff-search alone exceeds the 600s default on windows, and the server + # sees no new requests while it compiles, so it would idle out mid-unit. + SCCACHE_IDLE_TIMEOUT: "0" strategy: fail-fast: false matrix: diff --git a/.github/workflows/lua.yml b/.github/workflows/lua.yml index 5455d13d..3e7b2a7d 100644 --- a/.github/workflows/lua.yml +++ b/.github/workflows/lua.yml @@ -12,6 +12,10 @@ on: - '**.md' - 'doc/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} + jobs: lua-ls: name: lua-language-server type check diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 155eeca7..eb4604ad 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -12,6 +12,10 @@ on: - '**.md' - 'doc/**' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} + jobs: check: runs-on: ubuntu-22.04 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 2833352e..e4d570b5 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -19,6 +19,13 @@ env: CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 16 SCCACHE_GHA_ENABLED: "true" RUSTC_WRAPPER: sccache + # fff-search alone exceeds the 600s default on windows, and the server sees + # no new requests while it compiles, so it would idle out mid-unit. + SCCACHE_IDLE_TIMEOUT: "0" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} jobs: test: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5df39aaf..ce689641 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -17,6 +17,10 @@ on: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} + jobs: build-nvim: name: Build Neovim ${{ matrix.target }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9aea096a..50df0743 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -19,6 +19,13 @@ env: MACOSX_DEPLOYMENT_TARGET: "13" # RUSTC_WRAPPER is set per job, since cargo fmt runs without sccache. SCCACHE_GHA_ENABLED: "true" + # fff-search alone exceeds the 600s default on windows, and the server sees + # no new requests while it compiles, so it would idle out mid-unit. + SCCACHE_IDLE_TIMEOUT: "0" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} jobs: test: diff --git a/.github/workflows/spelling.yaml b/.github/workflows/spelling.yaml index b3b8d41c..3f08d34b 100644 --- a/.github/workflows/spelling.yaml +++ b/.github/workflows/spelling.yaml @@ -12,6 +12,10 @@ on: env: CLICOLOR: 1 +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} + jobs: spelling: name: Spell Check with Typos diff --git a/.github/workflows/stylua.yaml b/.github/workflows/stylua.yaml index fa7edb11..d914d068 100644 --- a/.github/workflows/stylua.yaml +++ b/.github/workflows/stylua.yaml @@ -20,6 +20,10 @@ on: env: CLICOLOR: 1 +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/tags/') }} + jobs: stylua: name: Check lua files using Stylua From 9e3dde03486ad00df5cc7b1735b058509f927a29 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 15 Aug 2026 21:46:49 -0700 Subject: [PATCH 4/5] fix(tests): poll for the new root index instead of a fixed sleep --- tests/programmatic_search_spec.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/programmatic_search_spec.lua b/tests/programmatic_search_spec.lua index 4d1b5ca6..c8b72c47 100644 --- a/tests/programmatic_search_spec.lua +++ b/tests/programmatic_search_spec.lua @@ -218,7 +218,13 @@ describe('programmatic search APIs', function() local before = fff.content_search(marker) assert.are.equal(0, #before.items, 'marker leaked into primary fff tree') - local result = fff.content_search(marker, { cwd = sandbox_root }) + -- Poll instead of asserting on the first grep: the index of the new root + -- can lag a mkdir by a few ms on CI, which flaked on linux too. + local result + vim.wait(2000, function() + result = fff.content_search(marker, { cwd = sandbox_root }) + return #result.items > 0 + end, 50) assert.is_true(#result.items > 0, 'cwd switch did not surface match from the new root') end) end) From 37a9aa5cbd32aed44efb116767bd4e87bad1d0f4 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 15 Aug 2026 21:51:08 -0700 Subject: [PATCH 5/5] perf(ci): cache release target builds with sccache --- .github/workflows/release.yaml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ce689641..1df85caf 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -25,6 +25,10 @@ jobs: build-nvim: name: Build Neovim ${{ matrix.target }} runs-on: ${{ matrix.os }} + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: sccache + SCCACHE_IDLE_TIMEOUT: "0" permissions: contents: read id-token: write @@ -95,6 +99,11 @@ jobs: with: key: nvim-${{ matrix.target }} + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Install Zig uses: mlugg/setup-zig@v2 with: @@ -150,6 +159,10 @@ jobs: build-c: name: Build C FFI ${{ matrix.target }} runs-on: ${{ matrix.os }} + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: sccache + SCCACHE_IDLE_TIMEOUT: "0" permissions: contents: read strategy: @@ -232,6 +245,11 @@ jobs: with: key: c-${{ matrix.target }} + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Install Zig uses: mlugg/setup-zig@v2 with: @@ -298,6 +316,10 @@ jobs: build-mcp: name: Build MCP ${{ matrix.target }} runs-on: ${{ matrix.os }} + env: + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: sccache + SCCACHE_IDLE_TIMEOUT: "0" permissions: contents: read strategy: @@ -348,6 +370,11 @@ jobs: with: key: mcp-${{ matrix.target }} + - name: Setup sccache + uses: mozilla-actions/sccache-action@v0.0.11 + with: + version: v0.17.0 + - name: Install Zig uses: mlugg/setup-zig@v2 with: