Skip to content
Draft
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
42 changes: 34 additions & 8 deletions .github/workflows/js.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
name: JS CI

# NOTE: The build/test commands below were verified by running them locally
# against this branch. They are NOT exercised on GitHub Actions until this
# workflow runs there, so the exact runner setup may still need tweaks.
#
# Build: a *real* wasm-pack (installed via jetli/wasm-pack-action) plus the
# wasm32-unknown-unknown target build the package into crates/ci-js/pkg, which
# the vitest suite imports as ../pkg/ci_js.js. `wasm-opt` is disabled via the
# crate's package metadata (crates/ci-js/Cargo.toml) because the locally
# installed wasm-opt is too old to parse the modern wasm the core emits; it only
# shrinks the binary, so disabling it does not affect correctness. CI may
# re-enable it once a newer wasm-opt is guaranteed on the runner.
#
# Tests live in crates/ci-js/tests (their own package.json + lockfile); the
# golden parity suite (golden.test.js) covers all 73 fixture cases (74 vitest
# test cases: 73 parametrized + 1 coverage assertion).

on:
push:
branches: [master, development]
paths:
- "crates/ci-js/**"
- "crates/ci-core/**"
- "tests/fixtures/**"
- "Cargo.toml"
- "Cargo.lock"
- ".github/workflows/js.yml"
pull_request:
paths:
- "crates/ci-js/**"
- "crates/ci-core/**"
- "tests/fixtures/**"
- "Cargo.toml"
- "Cargo.lock"
- ".github/workflows/js.yml"
Expand Down Expand Up @@ -66,24 +84,32 @@ jobs:
with:
node-version: lts/*
cache: npm
cache-dependency-path: crates/ci-js/package-lock.json
cache-dependency-path: crates/ci-js/tests/package-lock.json

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown

- uses: Swatinem/rust-cache@v2

# A real wasm-pack release (not the placeholder installer script).
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
uses: jetli/wasm-pack-action@v0.4.0
with:
version: latest

# Verified locally: builds into crates/ci-js/pkg (wasm-opt disabled via the
# crate's package metadata). The vitest suite imports ../pkg/ci_js.js.
- name: Build WASM package
working-directory: crates/ci-js
run: wasm-pack build --target nodejs --out-dir pkg
run: wasm-pack build crates/ci-js --target nodejs

- name: Install dependencies
working-directory: crates/ci-js
# Verified locally: `npm ci && npm test` in crates/ci-js/tests runs vitest;
# the golden suite covers all 73 fixture cases.
- name: Install test dependencies
working-directory: crates/ci-js/tests
run: npm ci

- name: Run tests
working-directory: crates/ci-js
run: npx vitest run --passWithNoTests
working-directory: crates/ci-js/tests
run: npm test
52 changes: 26 additions & 26 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
name: Python CI

# NOTE: The build/test commands below were verified by running them locally
# against this branch. They are NOT exercised on GitHub Actions until this
# workflow runs there, so the exact runner setup may still need tweaks.
#
# The bindings are built with maturin. On a Python newer than the installed
# PyO3 supports, set PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 (the crate already
# enables the `abi3-py310` feature, so a single abi3 wheel covers 3.10+). On CI
# we pin a supported Python (3.11-3.13) where that env var is not needed.
#
# The redesign removed the generated stubs / stub_gen binary, so there is no
# longer a "stubs up-to-date" job; the checked-in .pyi is maintained by hand.

on:
push:
branches: [master, development]
paths:
- 'crates/ci-python/**'
- 'crates/ci-core/**'
- 'tests/fixtures/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/python.yml'
pull_request:
paths:
- 'crates/ci-python/**'
- 'crates/ci-core/**'
- 'tests/fixtures/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/python.yml'
Expand All @@ -34,11 +48,12 @@ jobs:

- uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.12"

- name: Install ruff
run: pip install ruff

# Verified locally: `ruff format --check .` / `ruff check .` in crates/ci-python.
- name: Check formatting
working-directory: crates/ci-python
run: ruff format --check .
Expand All @@ -47,40 +62,22 @@ jobs:
working-directory: crates/ci-python
run: ruff check .

python-stubs:
name: Python Stubs Up-to-date
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Regenerate stubs
run: cargo run --release --bin stub_gen

- name: Check for diff
run: git diff --exit-code -- crates/ci-python/

python-test:
name: Python Tests
needs: [python-lint]
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
# Use a Python supported by the installed PyO3; no forward-compat env
# var needed here. The abi3-py310 wheel also works on 3.10+ at runtime.
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v5

- uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: ${{ matrix.python-version }}

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
Expand All @@ -90,6 +87,10 @@ jobs:
- name: Install Python dependencies
run: pip install maturin pytest numpy mypy

# Verified locally: maturin builds the extension; the golden parity test
# (crates/ci-python/test/test_golden.py) reproduces all 73 fixture cases.
# On a too-new interpreter, prefix with
# PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 (not required for 3.11-3.13).
- name: Build and install extension
working-directory: crates/ci-python
run: pip install -e . --no-build-isolation
Expand All @@ -98,7 +99,6 @@ jobs:
working-directory: crates/ci-python
run: mypy test/

# Verified locally: `pytest crates/ci-python/test/` -> golden = 73/73.
- name: Run tests
working-directory: crates/ci-python
shell: bash
run: pytest || [ "$?" -eq 5 ]
run: pytest crates/ci-python/test/
34 changes: 29 additions & 5 deletions .github/workflows/r.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
name: R CI

# NOTE: The build/test commands below were verified by running them locally
# against this branch. They are NOT exercised on GitHub Actions until this
# workflow runs there, so the exact runner setup may still need tweaks.
#
# Toolchain: R + rextendr (which compiles the embedded Rust crate), devtools,
# testthat, and jsonlite (the golden suite reads tests/fixtures/golden.json via
# jsonlite::fromJSON). rextendr::document() regenerates the extendr wrappers,
# then devtools::test() runs the package suite (469 tests, including the 73-case
# golden parity gate).
#
# We use r-lib/actions/setup-r (a standard CRAN R), which does NOT require the
# LD_LIBRARY_PATH workaround. (A *conda* R does: there you must export
# LD_LIBRARY_PATH=$(Rscript -e 'cat(R.home("lib"))') so the embedded Rust can
# link libR — not needed with the standard action below.)
#
# Commands are run from the repo root with the package path passed explicitly
# (rextendr::document("crates/ci-r") / devtools::test("crates/ci-r")) so the
# golden suite reliably resolves the repo-root fixture.

on:
push:
branches: [master, development]
paths:
- 'crates/ci-r/**'
- 'crates/ci-core/**'
- 'tests/fixtures/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/r.yml'
pull_request:
paths:
- 'crates/ci-r/**'
- 'crates/ci-core/**'
- 'tests/fixtures/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/r.yml'
Expand Down Expand Up @@ -74,18 +95,21 @@ jobs:

- uses: Swatinem/rust-cache@v2

# jsonlite is required by the golden suite but is not a package dependency,
# so install it alongside devtools/rextendr/testthat.
- name: Install R package dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
working-directory: crates/ci-r
extra-packages: any::devtools, any::rextendr
extra-packages: any::devtools, any::rextendr, any::testthat, any::jsonlite

# Verified locally: regenerate the extendr wrappers (compiles the Rust).
- name: Generate Makevars and R wrappers
working-directory: crates/ci-r
run: rextendr::document()
run: rextendr::document("crates/ci-r")
shell: Rscript {0}

# Verified locally: `devtools::test("crates/ci-r")` -> 469 tests incl. the
# 73-case golden parity gate (tests/fixtures/golden.json).
- name: Run R tests
working-directory: crates/ci-r
run: devtools::test(reporter = "summary")
run: devtools::test("crates/ci-r", reporter = "summary")
shell: Rscript {0}
41 changes: 24 additions & 17 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
name: Rust CI

# NOTE: The build/test/lint commands below were verified by running them locally
# against this branch's toolchain. They are NOT exercised on GitHub Actions until
# this workflow runs there, so the exact runner setup (toolchain versions, OS
# package availability) may still need tweaks.
#
# The workspace is no longer built/tested as a single step: the binding crates
# (ci_python / cir / ci_js) each need their own non-cargo toolchain (maturin,
# rextendr/R, wasm-pack) and are covered by python.yml / r.yml / js.yml. This
# workflow builds and gates only the pure-Rust core crate (ci_core), whose tests
# include the 73-case shared golden parity fixture.

on:
push:
branches: [master, development]
Expand All @@ -8,6 +19,7 @@ on:
- 'crates/ci-python/**'
- 'crates/ci-r/**'
- 'crates/ci-js/**'
- 'tests/fixtures/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/rust.yml'
Expand All @@ -17,6 +29,7 @@ on:
- 'crates/ci-python/**'
- 'crates/ci-r/**'
- 'crates/ci-js/**'
- 'tests/fixtures/**'
- 'Cargo.toml'
- 'Cargo.lock'
- '.github/workflows/rust.yml'
Expand All @@ -43,39 +56,31 @@ jobs:

- uses: Swatinem/rust-cache@v2

# Verified locally: `cargo fmt --all -- --check`
- name: Check formatting
run: cargo fmt --all -- --check

clippy:
name: Rust Clippy Lints
name: Rust Clippy Lints (ci_core)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install system dependencies
run: sudo apt-get install -y libopenblas-dev

- name: Install R
uses: r-lib/actions/setup-r@v2
with:
r-version: release

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy

- uses: Swatinem/rust-cache@v2

# Verified locally: `cargo clippy -p ci_core --all-targets -- -D warnings`.
# Scoped to ci_core so this job needs no Python/R/wasm toolchain; the
# binding crates are linted by their own workflows.
- name: Run Clippy
run: cargo clippy --workspace --all-targets -- -D warnings
run: cargo clippy -p ci_core --all-targets -- -D warnings

rust_test:
name: Rust Tests
name: Rust Tests (ci_core)
needs: [rust_fmt, clippy]
runs-on: ${{ matrix.os }}
strategy:
Expand All @@ -92,8 +97,10 @@ jobs:

- uses: Swatinem/rust-cache@v2

# Verified locally: `cargo test -p ci_core` (includes the 73-case golden
# parity test in crates/ci-core/tests/golden.rs).
- name: Build
run: cargo build --workspace --exclude ci_python --exclude cir --exclude ci_js --verbose
run: cargo build -p ci_core --verbose

- name: Run tests
run: cargo test --workspace --exclude ci_python --exclude cir --exclude ci_js --verbose
run: cargo test -p ci_core --verbose
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,8 @@ todo.txt
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode

*.code-workspace

# R: generated at install time by tools/config.R via configure; never track
# (a stale tracked copy can silently force a debug build).
crates/ci-r/src/Makevars
crates/ci-r/src/Makevars.win
Loading
Loading