on:
pull_request:
workflow_dispatch:
permissions:
id-token: write
contents: read
jobs:
prepare-resources:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11" architecture: x64
- name: Setup uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Install dependencies for resource creation
run: |
uv pip install --system numpy pandas seaborn scikit-learn toml
cp README.md package-python/README_PYTHON.md
cp LICENSE package-python/LICENSE
cp LICENSE package-r/LICENSE
mkdir -p resources
cd package-python
uv pip install --system -e .[dev]
cd ..
- name: Cache resources
id: cache-resources
uses: actions/cache@v4
with:
path: resources
key: resources-${{ hashFiles('scripts/make_resources.py') }}
- name: Build test data (create resources)
if: steps.cache-resources.outputs.cache-hit != 'true'
run: python scripts/make_resources.py
windows-build-test:
if: github.event_name != 'push'
needs: prepare-resources strategy:
matrix:
pyversion: ["3.10", "3.11", "3.12", "3.13", "3.14"]
runs-on: "windows-latest"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Restore resources cache
id: restore-resources
uses: actions/cache@v4
with:
path: resources
key: resources-${{ hashFiles('scripts/make_resources.py') }}
- name: Install latest stable Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.pyversion }}
architecture: x64
- name: Install deps
run: uv pip install --system numpy pandas seaborn scikit-learn toml
- run: |
cp README.md package-python/README_PYTHON.md
cp LICENSE package-python/LICENSE
cp LICENSE package-r/LICENSE
- name: Build test data (Install perpetual with its dev dependencies)
run: |
cd package-python
uv pip install --system -e .[dev]
cd ..
- name: Fallback build resources
if: steps.restore-resources.outputs.cache-hit != 'true'
run: python scripts/make_resources.py
- name: Build wheels with maturin
uses: PyO3/maturin-action@v1
with:
target: x86_64
command: build
args: --release --strip --interpreter python --manifest-path package-python/Cargo.toml --out dist --sdist
- name: Install wheel
run: uv pip install --system perpetual --no-index --find-links dist --no-deps --force-reinstall
- name: Run Package Tests
run: |
uv pip install --system pytest pytest-cov ruff setuptools typing-extensions --upgrade
cd package-python
ruff check .
ruff format --check .
pytest --cov=perpetual --cov-report=xml tests
cd ..
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
use_oidc: true
slug: ${{ github.repository }}
directory: ./package-python
flags: windows,python
fail_ci_if_error: true
verbose: true
- name: Save Artifacts
uses: actions/upload-artifact@v4
with:
name: dist-windows-${{ matrix.pyversion }}
path: dist
macos-build-test:
if: github.event_name != 'push'
needs: prepare-resources
strategy:
matrix:
pyversion: ["3.11", "3.12", "3.13", "3.14"]
os: [macos-latest, macos-latest-large]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Install OpenMP
run: brew install libomp
- name: Restore resources cache
id: restore-resources
uses: actions/cache@v4
with:
path: resources
key: resources-${{ hashFiles('scripts/make_resources.py') }}
- name: Install latest stable Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.pyversion }}
- name: Install deps
run: uv pip install --system numpy pandas seaborn scikit-learn toml
- run: |
cp README.md package-python/README_PYTHON.md
cp LICENSE package-python/LICENSE
cp LICENSE package-r/LICENSE
- name: Build test data (Install perpetual with its dev dependencies)
run: |
cd package-python
uv pip install --system -e .[dev]
cd ..
- name: Fallback build resources
if: steps.restore-resources.outputs.cache-hit != 'true'
run: python scripts/make_resources.py
- name: Build wheels with maturin
uses: PyO3/maturin-action@v1
with:
command: build
args: --release --strip --interpreter python --manifest-path package-python/Cargo.toml --out dist --sdist
- name: Install wheel
run: uv pip install --system perpetual --no-index --find-links dist --no-deps --force-reinstall
- name: Run Package Tests
run: |
uv pip install --system pytest pytest-cov ruff setuptools typing-extensions --upgrade
cd package-python
ruff check .
ruff format --check .
pytest --cov=perpetual --cov-report=xml tests
cd ..
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
use_oidc: true
slug: ${{ github.repository }}
directory: ./package-python
flags: macos,python
fail_ci_if_error: true
verbose: true
- name: Save Artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.os }}-${{ matrix.pyversion }}
path: dist
linux-build-test:
if: github.event_name != 'push'
needs: prepare-resources
runs-on: ubuntu-latest
strategy:
matrix:
pyversion: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Restore resources cache
id: restore-resources
uses: actions/cache@v4
with:
path: resources
key: resources-${{ hashFiles('scripts/make_resources.py') }}
- name: Install latest stable Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.pyversion }}
architecture: x64
- name: Install deps
run: uv pip install --system numpy pandas seaborn scikit-learn toml
- run: |
cp README.md package-python/README_PYTHON.md
cp LICENSE package-python/LICENSE
cp LICENSE package-r/LICENSE
- name: Build test data (Install perpetual with its dev dependencies)
run: |
cd package-python
uv pip install --system -e .[dev]
cd ..
- name: Fallback build resources
if: steps.restore-resources.outputs.cache-hit != 'true'
run: python scripts/make_resources.py
- name: Build wheels with maturin
uses: PyO3/maturin-action@v1
with:
target: x86_64
manylinux: auto
command: build
args: --release --strip --interpreter python${{ matrix.pyversion }} --manifest-path package-python/Cargo.toml --out dist --sdist
- name: Install wheel
run: uv pip install --system perpetual --no-index --find-links dist --no-deps --force-reinstall
- name: Run Package Tests
run: |
uv pip install --system pytest pytest-cov ruff setuptools typing-extensions --upgrade
cd package-python
ruff check .
ruff format --check .
pytest --cov=perpetual --cov-report=xml tests
cd ..
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
use_oidc: true
slug: ${{ github.repository }}
directory: ./package-python
flags: linux-x64,python
fail_ci_if_error: true
verbose: true
- name: Save Artifacts
uses: actions/upload-artifact@v4
with:
name: dist-linux-${{ matrix.pyversion }}
path: dist
linux-arm-build-test:
if: github.event_name != 'push'
needs: prepare-resources
runs-on: ubuntu-24.04-arm
strategy:
matrix:
pyversion: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Restore resources cache
id: restore-resources
uses: actions/cache@v4
with:
path: resources
key: resources-${{ hashFiles('scripts/make_resources.py') }}
- name: Install latest stable Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.pyversion }}
architecture: arm64
- name: Install deps
run: uv pip install --system numpy pandas seaborn scikit-learn toml
- run: |
cp README.md package-python/README_PYTHON.md
cp LICENSE package-python/LICENSE
cp LICENSE package-r/LICENSE
- name: Build test data (Install perpetual with its dev dependencies)
run: |
cd package-python
uv pip install --system -e .[dev]
cd ..
- name: Fallback build resources
if: steps.restore-resources.outputs.cache-hit != 'true'
run: python scripts/make_resources.py
- name: Build wheels with maturin
uses: PyO3/maturin-action@v1
with:
manylinux: auto
command: build
args: --release --strip --interpreter python${{ matrix.pyversion }} --manifest-path package-python/Cargo.toml --out dist --sdist
- name: Install wheel
run: uv pip install --system perpetual --no-index --find-links dist --no-deps --force-reinstall
- name: Run Package Tests
run: |
uv pip install --system pytest pytest-cov ruff setuptools typing-extensions --upgrade
cd package-python
ruff check .
ruff format --check .
pytest --cov=perpetual --cov-report=xml tests
cd ..
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
use_oidc: true
slug: ${{ github.repository }}
directory: ./package-python
flags: linux-arm,python
fail_ci_if_error: true
verbose: true
- name: Save Artifacts
uses: actions/upload-artifact@v4
with:
name: dist-linux-arm-${{ matrix.pyversion }}
path: dist
cargo-build-test:
if: github.event_name != 'push'
needs: prepare-resources
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Restore resources cache
id: restore-resources
uses: actions/cache@v4
with:
path: resources
key: resources-${{ hashFiles('scripts/make_resources.py') }}
- name: Install latest stable Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- uses: actions/setup-python@v5
with:
python-version: "3.11"
architecture: x64
- name: Install deps
run: uv pip install --system numpy pandas seaborn scikit-learn toml
- run: |
cp README.md package-python/README_PYTHON.md
cp LICENSE package-python/LICENSE
cp LICENSE package-r/LICENSE
- name: Build test data (Install perpetual with its dev dependencies)
run: |
cd package-python
uv pip install --system -e .[dev]
cd ..
- name: Fallback build resources
if: steps.restore-resources.outputs.cache-hit != 'true'
run: python scripts/make_resources.py
- name: Run tests
run: cargo test --verbose
- name: Install cargo-tarpaulin
uses: taiki-e/install-action@cargo-tarpaulin
- name: Run coverage
run: cargo tarpaulin --verbose --out Xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
use_oidc: true
slug: ${{ github.repository }}
files: ./cobertura.xml
flags: rust
fail_ci_if_error: true
verbose: true
R-CMD-check:
needs: prepare-resources
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
strategy:
fail-fast: false
matrix:
config:
- {os: ubuntu-latest, r: 'release'}
- {os: windows-latest, r: 'release'}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes
PERPETUAL_REQ_RESOURCES: true
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Restore resources cache
id: restore-resources
uses: actions/cache@v4
with:
path: resources
key: resources-${{ hashFiles('scripts/make_resources.py') }}
- name: Restore fallback deps (Python) for resource generation
if: steps.restore-resources.outputs.cache-hit != 'true'
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies for resource creation (Fallback)
if: steps.restore-resources.outputs.cache-hit != 'true'
run: |
pip install numpy pandas seaborn scikit-learn toml
cd package-python
pip install -e .
cd ..
- name: Fallback build resources
if: steps.restore-resources.outputs.cache-hit != 'true'
run: python scripts/make_resources.py
- name: Copy Resources for Tests
run: |
mkdir -p package-r/tests/testthat/resources
cp -r resources/* package-r/tests/testthat/resources/
shell: bash
- name: Setup Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
targets: ${{ runner.os == 'Windows' && 'x86_64-pc-windows-gnu' || '' }}
- uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ matrix.config.r }}
use-public-rspm: true
- name: Vendor core Rust logic
run: python scripts/vendor_r.py
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::rcmdcheck, any::devtools, any::testthat, any::roxygen2, any::jsonlite, any::covr
needs: check
working-directory: package-r
- name: Generate Documentation
run: |
Rscript -e "roxygen2::roxygenise('package-r')"
shell: bash
- name: Debug - List files before build
run: |
ls -R package-r/src/rust/core | head -n 20
shell: bash
- name: Manual Build
run: |
R CMD build package-r --no-manual --no-build-vignettes
shell: bash
- name: Manual Install Test
run: |
tarball=$(ls perpetual_*.tar.gz | head -n 1)
R CMD INSTALL "$tarball" --no-test-load
shell: bash
- name: Dump all check files on failure
if: failure()
shell: bash
run: |
echo "Listing all files in package-r/check:"
ls -R package-r/check || true
echo "Dumping 00install.out if it exists:"
find . -name "00install.out" -print -exec cat {} \; || true
echo "Dumping 00check.log if it exists:"
find . -name "00check.log" -print -exec cat {} \; || true
echo "Verifying vendored directory:"
ls -R package-r/src/rust/core || true
- name: Fix file permissions for R CMD check
if: runner.os != 'Windows'
run: |
# R CMD check warns about executable files in source packages.
# Strip execute permissions from all source files.
find package-r/src -type f -exec chmod -x {} +
shell: bash
- name: Check
uses: r-lib/actions/check-r-package@v2
with:
working-directory: package-r
error-on: ${{ runner.os == 'Windows' && '"error"' || '"warning"' }}
- name: Check Coverage
if: success() && matrix.config.os == 'ubuntu-latest'
run: |
Rscript -e "cov <- covr::package_coverage('package-r'); covr::to_cobertura(cov, filename = 'package-r/cobertura.xml')"
shell: bash
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
use_oidc: true
slug: ${{ github.repository }}
files: package-r/cobertura.xml
flags: r
fail_ci_if_error: true
verbose: true