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
59 changes: 56 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# ──────────────────────────────────────────────────────────────
# f2a CI — Lint, build, test on every push / PR
# Based on CocoRoF/googer proven workflow pattern.
#
# Optimised for speed:
# - Rust target + registry cached (Swatinem/rust-cache)
# - pip cached
# - lint & test run in parallel
# - matrix trimmed: full OS × Python only on main; PR = Linux-only
# ──────────────────────────────────────────────────────────────
name: CI

Expand All @@ -10,7 +16,29 @@ on:
pull_request:
branches: [main]

env:
CARGO_INCREMENTAL: "1"
CARGO_NET_RETRY: "10"
RUSTUP_MAX_RETRIES: "10"

jobs:
# ── Version consistency check (fast, no build) ────────────
check-versions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Verify pyproject.toml == Cargo.toml versions
run: |
PY_VER=$(grep -oP '^version\s*=\s*"\K[^"]+' pyproject.toml)
RS_VER=$(grep -oP '^version\s*=\s*"\K[^"]+' Cargo.toml)
echo "pyproject.toml = $PY_VER"
echo "Cargo.toml = $RS_VER"
if [ "$PY_VER" != "$RS_VER" ]; then
echo "::error::Version mismatch! pyproject.toml=$PY_VER vs Cargo.toml=$RS_VER — update both files."
exit 1
fi

# ── Lint (Rust + Python) ──────────────────────────────────
lint:
runs-on: ubuntu-latest
Expand All @@ -22,6 +50,11 @@ jobs:
with:
components: clippy, rustfmt

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true

- name: cargo fmt --check
run: cargo fmt --all -- --check

Expand All @@ -30,24 +63,44 @@ jobs:

# ── Test (cross-platform × multi-Python) ──────────────────
test:
needs: lint
# Run in parallel with lint (no 'needs')
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
python-version: ["3.10", "3.11", "3.12", "3.13"]
os: [ubuntu-latest]
python-version: ["3.10", "3.12"]
include:
# Spot-check other platforms with one Python version
- os: macos-14
python-version: "3.12"
- os: windows-latest
python-version: "3.12"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

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

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.os }}-py${{ matrix.python-version }}
cache-on-failure: true

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Pip cache
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ matrix.os }}-py${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
restore-keys: |
pip-${{ matrix.os }}-py${{ matrix.python-version }}-

- name: Install package and test deps
run: |
python -m pip install --upgrade pip
Expand Down
16 changes: 15 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
python-version: ["3.10", "3.13"]
steps:
- uses: actions/checkout@v4

Expand All @@ -79,6 +79,20 @@ jobs:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
key: publish-py${{ matrix.python-version }}
cache-on-failure: true

- name: Pip cache
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-publish-py${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
restore-keys: |
pip-publish-py${{ matrix.python-version }}-

- name: Install package and test deps
run: |
python -m pip install --upgrade pip
Expand Down
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "f2a"
version = "1.0.2"
version = "1.0.3"
edition = "2021"
description = "f2a computation core -- Rust engine with PyO3 bindings"
license = "Apache-2.0"
Expand Down Expand Up @@ -58,6 +58,11 @@ indexmap = { version = "2", features = ["serde"] }

[profile.release]
opt-level = 3

# Faster dev/test builds (used by `pip install .` which defaults to debug)
[profile.dev]
opt-level = 1 # enough optimisation to keep tests realistic
debug = false # skip DWARF → faster link
lto = "fat"
codegen-units = 1
strip = true
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "maturin"

[project]
name = "f2a"
version = "1.0.2"
version = "1.0.3"
description = "File to Analysis -- Automatically perform statistical analysis from any data source (Rust-powered)"
license = { text = "Apache-2.0" }
readme = "README.md"
Expand Down
8 changes: 7 additions & 1 deletion python/f2a/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
__version__ = "1.0.0"
from importlib.metadata import version, PackageNotFoundError

try:
__version__: str = version("f2a")
except PackageNotFoundError:
# Fallback for editable / dev installs where metadata isn't available yet
__version__ = "0.0.0-dev"
11 changes: 9 additions & 2 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,20 @@ def test_import():
def test_version():
import f2a

assert f2a.__version__ == "1.0.0"
# Version must be a valid semver-like string, not the dev fallback
assert f2a.__version__ != "0.0.0-dev"
parts = f2a.__version__.split(".")
assert len(parts) >= 2, f"Unexpected version format: {f2a.__version__}"


def test_rust_core_version():
from f2a._core import version
import f2a

assert version() == "1.0.0"
# Rust core version (from Cargo.toml) must match Python package version (from pyproject.toml)
assert version() == f2a.__version__, (
f"Version mismatch: Rust core={version()}, Python package={f2a.__version__}"
)


def test_rust_core_configs():
Expand Down
Loading