From bfe33e19ce478ac5a1a7280cd9db0f555cf5fca2 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 11:22:51 +0200 Subject: [PATCH 01/12] install cargo tools Signed-off-by: Christoph Schulze --- .github/actions/setup-rust/action.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index 4f42d38167a..867efd18e1e 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -80,6 +80,11 @@ runs: shell: bash run: sccache --start-server + - name: Install cargo tools (cargo-hack, cargo-nextest, cargo-minimal-versions) + uses: taiki-e/install-action@9e1e5806d4a4822de933115878265be9aaa786d9 # v2 + with: + tool: cargo-hack,cargo-nextest,cargo-minimal-versions + - name: Install Protoc (for lance-encoding build step) if: runner.os != 'Windows' uses: ./.github/actions/setup-protoc From 88e4622427a16fffd1946f88246d9aa028cdd072 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 12:41:11 +0200 Subject: [PATCH 02/12] taplo Signed-off-by: Christoph Schulze --- Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3293c5b1a54..ca3694b4c38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,7 +137,9 @@ cudarc = { version = "0.19.0", features = [ ] } custom-labels = "0.4.4" dashmap = "6.1.0" -datafusion = { git = "https://github.com/massive-com/arrow-datafusion", rev = "6363fbeb2a593e78fb6d73ad07ddba13c0406949", default-features = false, features = ["sql"] } +datafusion = { git = "https://github.com/massive-com/arrow-datafusion", rev = "6363fbeb2a593e78fb6d73ad07ddba13c0406949", default-features = false, features = [ + "sql", +] } datafusion-catalog = { git = "https://github.com/massive-com/arrow-datafusion", rev = "6363fbeb2a593e78fb6d73ad07ddba13c0406949" } datafusion-common = { git = "https://github.com/massive-com/arrow-datafusion", rev = "6363fbeb2a593e78fb6d73ad07ddba13c0406949" } datafusion-common-runtime = { git = "https://github.com/massive-com/arrow-datafusion", rev = "6363fbeb2a593e78fb6d73ad07ddba13c0406949" } From e12ff5bb86c9740fa0c01b72f8d85f105b7c1072 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 12:48:57 +0200 Subject: [PATCH 03/12] Fix fork CI: install uv and remove expect_used lint violation - Install uv on the fork fallback path so python-lint/test jobs that call uvx/uv run work outside the prebuilt images. - Replace is_some()+expect() in Reversed::validate with a let-else that bails, satisfying the workspace-wide clippy::expect_used = deny lint. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- .github/actions/setup-prebuild/action.yml | 9 ++++++++- vortex-array/src/arrays/reversed/vtable.rs | 10 +++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/actions/setup-prebuild/action.yml b/.github/actions/setup-prebuild/action.yml index 9cfc837b680..b5213795e7e 100644 --- a/.github/actions/setup-prebuild/action.yml +++ b/.github/actions/setup-prebuild/action.yml @@ -39,7 +39,7 @@ runs: # Fallback path: full setup for forks - name: Full Rust setup - if: github.repository != 'vortex-data/vortex' + if: github.repository == 'massive-com/vortex' uses: ./.github/actions/setup-rust with: repo-token: ${{ inputs.repo-token }} @@ -47,3 +47,10 @@ runs: components: ${{ inputs.components }} targets: ${{ inputs.targets }} enable-sccache: ${{ inputs.enable-sccache }} + + # uv is preinstalled on the prebuilt images; install it for forks. + - name: Install uv + if: github.repository == 'massive-com/vortex' + uses: spiraldb/actions/.github/actions/setup-uv@a746510eafaa926484c354541cfc49b2ec06cc63 # 0.18.6 + with: + sync: false diff --git a/vortex-array/src/arrays/reversed/vtable.rs b/vortex-array/src/arrays/reversed/vtable.rs index f2627e45fba..f6e98af3444 100644 --- a/vortex-array/src/arrays/reversed/vtable.rs +++ b/vortex-array/src/arrays/reversed/vtable.rs @@ -55,13 +55,9 @@ impl VTable for Reversed { len: usize, slots: &[Option], ) -> VortexResult<()> { - vortex_ensure!( - slots[CHILD_SLOT].is_some(), - "ReversedArray child slot must be present" - ); - let child = slots[CHILD_SLOT] - .as_ref() - .expect("validated child slot presence"); + let Some(child) = slots[CHILD_SLOT].as_ref() else { + vortex_bail!("ReversedArray child slot must be present"); + }; vortex_ensure!( child.dtype() == dtype, "ReversedArray dtype {} does not match child dtype {}", From 52d0529ae2395bf290f7d55f73e0cac7fdc8ea3a Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 14:07:09 +0200 Subject: [PATCH 04/12] Fix fork CI: install flatc and fix clone_on_ref_ptr lints - Install flatc via setup-flatc in the generated-files job on the fork, matching how uv/cargo-hack are handled; upstream bakes it into the AMI. - Replace .clone() on Arc with Arc::clone(&..) in vortex-layout segment cache and scan task test to satisfy clippy::clone_on_ref_ptr. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- .github/workflows/ci.yml | 3 +++ vortex-layout/src/scan/tasks.rs | 2 +- vortex-layout/src/segments/cache.rs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54a3960ae28..c1bbca0310f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -533,6 +533,9 @@ jobs: sccache: s3 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - uses: ./.github/actions/setup-prebuild + # flatc is preinstalled on the prebuilt images; install it for forks. + - uses: ./.github/actions/setup-flatc + if: github.repository == 'massive-com/vortex' - name: Install nightly for cbindgen macro expansion run: rustup toolchain install $NIGHTLY_TOOLCHAIN - name: "regenerate all .fbs/.proto Rust code" diff --git a/vortex-layout/src/scan/tasks.rs b/vortex-layout/src/scan/tasks.rs index fe6e02b6dfa..05c868067e1 100644 --- a/vortex-layout/src/scan/tasks.rs +++ b/vortex-layout/src/scan/tasks.rs @@ -255,7 +255,7 @@ mod tests { let remaining = Arc::new(AtomicU64::new(LIMIT)); let handles: Vec<_> = (0..THREADS) .map(|_| { - let remaining = remaining.clone(); + let remaining = Arc::clone(&remaining); thread::spawn(move || { let mut total: usize = 0; while total < PER_THREAD_REQUEST { diff --git a/vortex-layout/src/segments/cache.rs b/vortex-layout/src/segments/cache.rs index a26701959a7..64808180047 100644 --- a/vortex-layout/src/segments/cache.rs +++ b/vortex-layout/src/segments/cache.rs @@ -209,7 +209,7 @@ impl SegmentCacheSourceAdapter { impl SegmentSource for SegmentCacheSourceAdapter { fn request(&self, id: SegmentId) -> SegmentFuture { - let cache = self.cache.clone(); + let cache = Arc::clone(&self.cache); let delegate = self.source.request(id); async move { From 072606af8367c96fd7dae717ddb126c9dfb9ed48 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 16:55:14 +0200 Subject: [PATCH 05/12] Fix fork CI: rustdoc lints and skip benchmark tuning on forks - Fix rustdoc::private_intra_doc_links in reversed/mod.rs (drop link to private execute module) and rustdoc::redundant_explicit_links in erased.rs (use the shortcut intra-doc link form). - Gate the benchmark tuning + benchmark run steps in Python (test) to upstream; scripts/setup-benchmark.sh (aa-teardown etc.) requires the self-hosted prebuilt runner and aborts on GitHub-hosted ubuntu-latest. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- .github/workflows/ci.yml | 3 +++ vortex-array/src/array/erased.rs | 2 +- vortex-array/src/arrays/reversed/mod.rs | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1bbca0310f..6145a9e1c1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,10 +114,13 @@ jobs: uv run --all-packages pytest --benchmark-disable -n auto test/ working-directory: vortex-python/ + # Benchmark tuning requires the self-hosted prebuilt runner; skip on forks. - name: Setup benchmark environment + if: github.repository == 'vortex-data/vortex' run: sudo bash scripts/setup-benchmark.sh - name: Pytest Benchmarks - Vortex + if: github.repository == 'vortex-data/vortex' run: | bash ../scripts/bench-taskset.sh uv run --all-packages pytest --benchmark-only benchmark/ working-directory: vortex-python/ diff --git a/vortex-array/src/array/erased.rs b/vortex-array/src/array/erased.rs index 95b3354310d..ffcab4ea884 100644 --- a/vortex-array/src/array/erased.rs +++ b/vortex-array/src/array/erased.rs @@ -265,7 +265,7 @@ impl ArrayRef { .optimize() } - /// Wraps the array in a [`ReversedArray`](crate::arrays::ReversedArray) such that it is + /// Wraps the array in a [`ReversedArray`] such that it is /// logically yielded in reverse element order. The optimizer is run immediately, which may /// eliminate the wrapper (for example, for `Reversed(Reversed(x))` or `Reversed(Dict(...))`). pub fn reverse(&self) -> VortexResult { diff --git a/vortex-array/src/arrays/reversed/mod.rs b/vortex-array/src/arrays/reversed/mod.rs index b85c06705c7..36c565bc322 100644 --- a/vortex-array/src/arrays/reversed/mod.rs +++ b/vortex-array/src/arrays/reversed/mod.rs @@ -15,7 +15,7 @@ //! dictionary-encoded, so the per-chunk reversal cost is O(n_codes) rather than O(n_rows). //! //! For encodings that have no reduce rule the `ReversedArray` wrapper survives to -//! decode time, where [`execute.rs`](self::execute) reverses the canonical form +//! decode time, where `execute.rs` reverses the canonical form //! directly: //! //! * `Primitive`: iterates the typed buffer backwards — O(n), fully sequential. From ac826a75322b585656550042a6d723b18c3793a3 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 17:04:44 +0200 Subject: [PATCH 06/12] Fix fork CI: apply nightly rustfmt to patched/mod.rs cargo +nightly fmt (NIGHTLY_TOOLCHAIN) normalizes a blank line inside the doc-comment diagram in patched/mod.rs; commit the formatting so 'Rust (lint) - Format' (cargo fmt --all --check) passes. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- vortex-array/src/arrays/patched/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vortex-array/src/arrays/patched/mod.rs b/vortex-array/src/arrays/patched/mod.rs index 0d4a4dbdb5a..a88628e5587 100644 --- a/vortex-array/src/arrays/patched/mod.rs +++ b/vortex-array/src/arrays/patched/mod.rs @@ -43,7 +43,7 @@ //! `indices` and `values` are aligned and accessed together. //! //! ```text -//! +//! //! chunk 0 chunk 0 chunk 0 chunk 0 chunk 0 chunk 0 //! lane 0 lane 1 lane 2 lane 3 lane 4 lane 5 //! ┌────────────┬────────────┬────────────┬────────────┬────────────┬────────────┐ From fd58d8b93b67a6ad01f8c79fd91b5ef1e3feac81 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 17:15:37 +0200 Subject: [PATCH 07/12] Fix fork CI: install doxygen for Python docs on forks docs/conf.py requires doxygen on PATH to build the C++ API docs via breathe; it is preinstalled on the prebuilt images but missing on GitHub-hosted runners, so 'make doctest'/'make html' aborted. Install it via ssciwr/doxygen-install on the fork before the docs steps. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6145a9e1c1b..e0f15b23b95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,6 +108,10 @@ jobs: sccache: s3 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - uses: ./.github/actions/setup-prebuild + # doxygen is preinstalled on the prebuilt images; install it for forks. + - name: Install Doxygen + if: github.repository == 'massive-com/vortex' + uses: ssciwr/doxygen-install@329d88f5a303066a5bd006db7516b1925b86350e # v2 - name: Pytest - Vortex run: | From a98ec3aee6cc99e52120421739912b873aeb2387 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 13 Jul 2026 18:33:17 +0200 Subject: [PATCH 08/12] Resolve RUSTSEC advisories flagged by cargo-deny - Bump crossbeam-epoch 0.9.18 -> 0.9.20 (RUSTSEC-2026-0204, patched >= 0.9.20), matching upstream develop. - Bump cxx 1.0.194 -> 1.0.195 (RUSTSEC-2026-0202, patched >= 1.0.195). - Ignore RUSTSEC-2026-0194/0195 (quick-xml) in deny.toml; no patched release exists and it is a transitive dependency, matching upstream. cargo deny check advisories now passes. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- Cargo.lock | 46 +++++++++++++++++++++++----------------------- deny.toml | 5 ++++- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a84c673f61..1dbfe5d9eb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1443,7 +1443,7 @@ checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", - "unicode-width 0.2.2", + "unicode-width 0.1.14", ] [[package]] @@ -1545,7 +1545,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1860,9 +1860,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] @@ -1999,9 +1999,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d8437319e3a2f43d93b341c137927ca70c0f5dabeea7a005a73665e247c7e" +checksum = "201f2332bd98022973bbf50c87f2d2f8151200f43e640da370901b20f1bea9d3" dependencies = [ "cc", "cxx-build", @@ -2014,9 +2014,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f4697d190a142477b16aef7da8a99bfdc41e7e8b1687583c0d23a79c7afc1e" +checksum = "02da7762e3807681f61c4561f34e1ff791417334294b225dbe22236459c9deef" dependencies = [ "cc", "codespan-reporting", @@ -2029,9 +2029,9 @@ dependencies = [ [[package]] name = "cxxbridge-cmd" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0956799fa8678d4c50eed028f2de1c0552ae183c76e976cf7ca8c4e36a7c328" +checksum = "21c216b8cd7c26c2798bbecdb13de2f8dc65239b9ed892756deacff10fc0fa64" dependencies = [ "clap", "codespan-reporting", @@ -2043,15 +2043,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23384a836ab4f0ad98ace7e3955ad2de39de42378ab487dc28d3990392cb283a" +checksum = "61c618f09812e388d1d065fd43fdc4340fade506ab2e0903397bf238650fce45" [[package]] name = "cxxbridge-macro" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6acc6b5822b9526adfb4fc377b67128fdd60aac757cc4a741a6278603f763cf" +checksum = "415b113deba00cc605302b9b0b4974ab3d57c41135d81737cd47b89dbaa17c38" dependencies = [ "indexmap 2.14.0", "proc-macro2", @@ -3577,7 +3577,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3763,7 +3763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -4944,7 +4944,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6317,7 +6317,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -8094,7 +8094,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -8152,7 +8152,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -9018,7 +9018,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -9037,7 +9037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -11068,7 +11068,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] diff --git a/deny.toml b/deny.toml index b9f9c79a796..3a38fd19fec 100644 --- a/deny.toml +++ b/deny.toml @@ -16,7 +16,10 @@ ignore = [ # Paste is no longer maintained because its essentially "finished". "RUSTSEC-2024-0436", # proc-macro-error-2 is unmaintained, only used by the `test_with` test dependency - "RUSTSEC-2026-0173" + "RUSTSEC-2026-0173", + # quick-xml is a transitive dependency that we cannot upgrade ourselves + "RUSTSEC-2026-0195", + "RUSTSEC-2026-0194" ] [licenses] From 916f9cc62ff7f76bfbfe2ecbd69d4e8d5a828804 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Tue, 14 Jul 2026 10:40:41 +0200 Subject: [PATCH 09/12] Tune fork CI: raise build timeouts, disable upstream-only workflows Forks run on GitHub-hosted runners without sccache, so uncached builds straddle the 30m timeout: - build-rust: 30 -> 60m on forks (all-features/default builds). - rust-instrumented coverage + sanitizer: 30 -> 90m on forks. Disable workflows that require upstream secrets/infrastructure and can never pass on a fork: - Codspeed bench shards (need CODSPEED_TOKEN). - Publish Dry Runs (git deps are unpublishable; some jobs target the upstream self-hosted runners and hang waiting for a runner). Upstream timeouts and behavior are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- .github/workflows/ci.yml | 3 ++- .github/workflows/codspeed.yml | 2 ++ .github/workflows/publish-dry-runs.yml | 6 ++++++ .github/workflows/rust-instrumented.yml | 6 ++++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0f15b23b95..523ccd14905 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -200,7 +200,8 @@ jobs: build-rust: name: "Rust build (${{matrix.config.name}})" - timeout-minutes: 30 + # Forks build without sccache, so give the uncached build more headroom. + timeout-minutes: ${{ github.repository == 'vortex-data/vortex' && 30 || 60 }} runs-on: >- ${{ github.repository == 'vortex-data/vortex' && format('runs-on={0}/runner={1}/image=ubuntu24-full-x64-pre-v2/tag={2}', github.run_id, matrix.config.runner, matrix.config.name) diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index 2cdcbaa9dbf..89797a21136 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -24,6 +24,8 @@ env: jobs: bench-codspeed: + # CodSpeed requires an upstream account/token; skip on forks. + if: github.repository == 'vortex-data/vortex' strategy: matrix: include: diff --git a/.github/workflows/publish-dry-runs.yml b/.github/workflows/publish-dry-runs.yml index 49f539a19e4..ce00716cf17 100644 --- a/.github/workflows/publish-dry-runs.yml +++ b/.github/workflows/publish-dry-runs.yml @@ -24,6 +24,9 @@ env: jobs: python-wheel-build: name: "Python (wheel build)" + # Publish validation is upstream-only (git deps are unpublishable, and some + # jobs require the upstream self-hosted runners); skip on forks. + if: github.repository == 'vortex-data/vortex' runs-on: ubuntu-latest timeout-minutes: 30 steps: @@ -64,6 +67,7 @@ jobs: working-directory: vortex-python/ check-java-publish-build: + if: github.repository == 'vortex-data/vortex' timeout-minutes: 30 strategy: fail-fast: false @@ -96,12 +100,14 @@ jobs: compat-check: name: "Compat check" + if: github.repository == 'vortex-data/vortex' uses: ./.github/workflows/compat-validation.yml with: mode: last rust-publish-dry-run: name: "Rust publish dry-run" + if: github.repository == 'vortex-data/vortex' timeout-minutes: 30 runs-on: >- ${{ github.repository == 'vortex-data/vortex' diff --git a/.github/workflows/rust-instrumented.yml b/.github/workflows/rust-instrumented.yml index bf45fc7be13..00a0f1369f9 100644 --- a/.github/workflows/rust-instrumented.yml +++ b/.github/workflows/rust-instrumented.yml @@ -44,7 +44,8 @@ jobs: rust-coverage: name: "Rust tests (coverage) (${{ matrix.suite }})" needs: duckdb-ready - timeout-minutes: 30 + # Forks build instrumented without sccache; give the uncached run more headroom. + timeout-minutes: ${{ github.repository == 'vortex-data/vortex' && 30 || 90 }} permissions: id-token: write strategy: @@ -130,7 +131,8 @@ jobs: ${{ github.repository == 'vortex-data/vortex' && format('runs-on={0}/pool=amd64-medium-pre-v2/tag=rust-test-sanitizer', github.run_id) || 'ubuntu-latest' }} - timeout-minutes: 30 + # Forks build instrumented without sccache; give the uncached run more headroom. + timeout-minutes: ${{ github.repository == 'vortex-data/vortex' && 30 || 90 }} env: ASAN_OPTIONS: "symbolize=1:check_initialization_order=1:detect_leaks=1:leak_check_at_exit=1" LSAN_OPTIONS: "report_objects=1" From 8077277903eb7048b5a5b8bce6bb8057a162d218 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Tue, 14 Jul 2026 12:37:00 +0200 Subject: [PATCH 10/12] Fix fork tsan/asan: provide llvm-symbolizer so suppressions match The sanitizer jobs hardcode *_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer, which the prebuilt image ships but GitHub-hosted runners do not. Without it TSan cannot symbolize frames, so vortex-ffi/tsan_suppressions.txt (benign crossbeam-epoch/deque and oneshot fence races surfaced via moka's cache) never matches and the job fails on false positives. Symlink an available llvm-symbolizer to the expected path on forks. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- .github/workflows/rust-instrumented.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/rust-instrumented.yml b/.github/workflows/rust-instrumented.yml index 00a0f1369f9..82d9f31ae86 100644 --- a/.github/workflows/rust-instrumented.yml +++ b/.github/workflows/rust-instrumented.yml @@ -156,6 +156,27 @@ jobs: run: | rustup toolchain install $NIGHTLY_TOOLCHAIN rustup component add --toolchain $NIGHTLY_TOOLCHAIN rust-src rustfmt clippy llvm-tools-preview + # The prebuilt image ships /usr/bin/llvm-symbolizer; GitHub-hosted runners + # do not. Without it TSan/ASan cannot symbolize frames, so the + # tsan_suppressions.txt entries (benign crossbeam/oneshot fence races) + # never match and fail the job. Symlink an available llvm-symbolizer. + - name: Ensure llvm-symbolizer (forks) + if: github.repository == 'massive-com/vortex' + shell: bash + run: | + if [ ! -x /usr/bin/llvm-symbolizer ]; then + sym="$(command -v llvm-symbolizer \ + || ls -1 /usr/bin/llvm-symbolizer-* 2>/dev/null | sort -V | tail -1 \ + || ls -1 /usr/lib/llvm-*/bin/llvm-symbolizer 2>/dev/null | sort -V | tail -1)" + if [ -z "$sym" ]; then + sudo apt-get update + sudo apt-get install -y llvm + sym="$(ls -1 /usr/bin/llvm-symbolizer-* 2>/dev/null | sort -V | tail -1 \ + || ls -1 /usr/lib/llvm-*/bin/llvm-symbolizer 2>/dev/null | sort -V | tail -1)" + fi + sudo ln -sf "$sym" /usr/bin/llvm-symbolizer + fi + /usr/bin/llvm-symbolizer --version - name: Build tests with sanitizer run: | RUSTFLAGS="${RUSTFLAGS} ${{ matrix.sanitizer_flags }}" \ From 20986996e451f3f36236c0b117c5b303ad6ec948 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Tue, 14 Jul 2026 13:45:08 +0200 Subject: [PATCH 11/12] Disable coverage job on forks (OOMs GitHub-hosted runners) Rust tests (coverage) instruments and runs the whole workspace test suite, exhausting memory on the ubuntu-latest runners forks use ('hosted runner lost communication with the server'); upstream runs it on larger self-hosted runners and uploads via Codecov OIDC that forks lack. Gate the job to upstream. tsan/asan/miri remain enabled on forks. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- .github/workflows/rust-instrumented.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust-instrumented.yml b/.github/workflows/rust-instrumented.yml index 82d9f31ae86..2e43266784f 100644 --- a/.github/workflows/rust-instrumented.yml +++ b/.github/workflows/rust-instrumented.yml @@ -43,9 +43,12 @@ jobs: rust-coverage: name: "Rust tests (coverage) (${{ matrix.suite }})" + # Coverage instruments and runs the whole test suite, which OOMs the + # GitHub-hosted runners forks use (upstream runs it on larger self-hosted + # runners); it also uploads to Codecov via OIDC that forks lack. Skip on forks. + if: github.repository == 'vortex-data/vortex' needs: duckdb-ready - # Forks build instrumented without sccache; give the uncached run more headroom. - timeout-minutes: ${{ github.repository == 'vortex-data/vortex' && 30 || 90 }} + timeout-minutes: 30 permissions: id-token: write strategy: From 7cc9da6cbf386825b25107a50adc9d7345684dc6 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Tue, 14 Jul 2026 16:28:06 +0200 Subject: [PATCH 12/12] Fix leak in vortex-ffi test_sink_invalid_path (asan/leak sanitizer) With an invalid path the async writer can fail such that both vx_array_sink_push and vx_array_sink_close write an error into the same out-param; close overwrote the push error pointer and the test only freed the final error, leaking the push error (intermittently caught by LSan depending on writer-task timing). Free the push error before reusing the variable for close. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Christoph Schulze --- vortex-ffi/src/sink.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vortex-ffi/src/sink.rs b/vortex-ffi/src/sink.rs index 639d22196e3..20b9fb0167f 100644 --- a/vortex-ffi/src/sink.rs +++ b/vortex-ffi/src/sink.rs @@ -242,6 +242,12 @@ mod tests { let vx_array_ptr = vx_array::new(Arc::new(array.into_array())); vx_array_sink_push(sink, vx_array_ptr, &raw mut error); vx_array_free(vx_array_ptr); + // Free any push error before reusing `error` for close, otherwise + // close overwrites the pointer and the push error leaks. + if !error.is_null() { + vx_error_free(error); + error = std::ptr::null_mut(); + } // Close should fail due to invalid path vx_array_sink_close(sink, &raw mut error);