e359392a00
Add a `visualization` feature flag that generates self-contained HTML reports with interactive Plotly.js charts for offline visualization of optimization results. Charts include optimization history, slice plots, parallel coordinates, parameter importance, trial timeline, and intermediate values (learning curves).
408 lines
12 KiB
YAML
408 lines
12 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main, master]
|
|
pull_request:
|
|
branches: [main, master]
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
|
|
jobs:
|
|
fmt:
|
|
name: Format
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
rustup component add rustfmt
|
|
- run: cargo fmt --all --check
|
|
|
|
clippy:
|
|
name: Clippy
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
rustup component add clippy
|
|
- uses: Swatinem/rust-cache@v2
|
|
- run: cargo clippy --all-targets --all-features -- -D warnings
|
|
|
|
test:
|
|
name: Test
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
features:
|
|
- ""
|
|
- "async"
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Run tests
|
|
run: |
|
|
if [ -z "${{ matrix.features }}" ]; then
|
|
cargo test --verbose
|
|
else
|
|
cargo test --verbose --features "${{ matrix.features }}"
|
|
fi
|
|
|
|
examples:
|
|
name: Examples
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Run sync example (ml_hyperparameter_tuning)
|
|
run: cargo run --example ml_hyperparameter_tuning
|
|
- name: Run sync example (benchmark_convergence)
|
|
run: cargo run --example benchmark_convergence
|
|
- name: Run derive example (parameter_api)
|
|
run: cargo run --example parameter_api --features derive
|
|
- name: Run async example (async_api_optimization)
|
|
run: cargo run --example async_api_optimization --features async
|
|
- name: Run visualization example (visualization_demo)
|
|
run: cargo run --example visualization_demo --features visualization
|
|
|
|
docs:
|
|
name: Docs
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- run: cargo doc --all-features --no-deps
|
|
env:
|
|
RUSTDOCFLAGS: -D warnings
|
|
|
|
feature-check:
|
|
name: Feature Combinations
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- name: Install cargo-hack
|
|
uses: taiki-e/install-action@cargo-hack
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Check feature powerset
|
|
run: cargo hack check --feature-powerset --no-dev-deps
|
|
|
|
coverage:
|
|
name: Coverage
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
rustup component add llvm-tools-preview
|
|
- name: Install cargo-llvm-cov
|
|
uses: taiki-e/install-action@cargo-llvm-cov
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Generate coverage report
|
|
run: cargo llvm-cov --all-features --lcov --output-path lcov.info
|
|
- name: Upload coverage to Codecov
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
files: lcov.info
|
|
fail_ci_if_error: true
|
|
|
|
msrv:
|
|
name: MSRV (1.88)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust 1.88
|
|
run: |
|
|
rustup override set 1.88
|
|
rustup update 1.88
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Check compilation
|
|
run: cargo check --all-features
|
|
|
|
deny:
|
|
name: Cargo Deny
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- uses: EmbarkStudios/cargo-deny-action@v2
|
|
|
|
machete:
|
|
name: Unused Dependencies
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Machete
|
|
uses: bnjbvr/cargo-machete@7959c845782fed02ee69303126d4a12d64f1db18
|
|
|
|
semver:
|
|
name: Semver Check
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Install cargo-semver-checks
|
|
uses: taiki-e/install-action@cargo-semver-checks
|
|
- name: Check semver
|
|
run: cargo semver-checks check-release
|
|
|
|
minimal-versions:
|
|
name: Minimal Versions
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust nightly
|
|
run: |
|
|
rustup toolchain install nightly
|
|
rustup override set nightly
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Generate minimal version lockfile
|
|
run: cargo +nightly -Z minimal-versions update
|
|
- name: Install Rust stable
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- name: Check with minimal versions
|
|
run: cargo check --all-features --locked
|
|
|
|
cross-platform:
|
|
name: ${{ matrix.os }}
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [windows-latest, macos-latest]
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Check compilation
|
|
run: cargo check --all-features
|
|
- name: Run tests
|
|
run: cargo test --all-features
|
|
|
|
cross-targets:
|
|
name: ${{ matrix.target }}
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
target:
|
|
- aarch64-unknown-linux-gnu
|
|
- i686-unknown-linux-gnu
|
|
- powerpc64le-unknown-linux-gnu
|
|
- s390x-unknown-linux-gnu
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
rustup target add ${{ matrix.target }}
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Check compilation
|
|
run: cargo check --all-features --target ${{ matrix.target }}
|
|
|
|
typos:
|
|
name: Typos
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: taiki-e/cache-cargo-install-action@v3
|
|
with:
|
|
tool: typos-cli
|
|
- name: Typos Check
|
|
run: typos src/
|
|
|
|
bench-check:
|
|
name: Benchmark Smoke Test
|
|
if: github.event_name == 'push'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Run benchmarks (smoke test)
|
|
run: cargo bench --all-features --bench samplers --bench optimization
|
|
|
|
bench-compare:
|
|
name: Benchmark Comparison
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
|
|
- name: Install critcmp
|
|
run: cargo install critcmp
|
|
|
|
# --- Run benchmarks on the BASE (target) branch ---
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
ref: ${{ github.event.pull_request.base.sha }}
|
|
clean: false
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
key: bench-base
|
|
|
|
- name: Bench baseline
|
|
run: cargo bench --all-features --bench samplers --bench optimization -- --save-baseline base
|
|
|
|
# --- Run benchmarks on the HEAD (PR) branch ---
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
clean: false
|
|
|
|
- uses: Swatinem/rust-cache@v2
|
|
with:
|
|
key: bench-head
|
|
|
|
- name: Bench PR head
|
|
run: cargo bench --all-features --bench samplers --bench optimization -- --save-baseline head
|
|
|
|
# --- Compare and post comment ---
|
|
- name: Compare benchmarks
|
|
id: compare
|
|
run: |
|
|
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
|
|
echo "result<<$EOF" >> "$GITHUB_OUTPUT"
|
|
critcmp base head --color never >> "$GITHUB_OUTPUT"
|
|
echo "$EOF" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Find existing comment
|
|
uses: peter-evans/find-comment@v4
|
|
id: find-comment
|
|
with:
|
|
issue-number: ${{ github.event.pull_request.number }}
|
|
comment-author: github-actions[bot]
|
|
body-includes: "## Benchmark Comparison"
|
|
|
|
- name: Post or update PR comment
|
|
uses: peter-evans/create-or-update-comment@v5
|
|
with:
|
|
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
|
issue-number: ${{ github.event.pull_request.number }}
|
|
edit-mode: replace
|
|
body: |
|
|
## Benchmark Comparison
|
|
|
|
**Base:** `${{ github.event.pull_request.base.sha }}` | **Head:** `${{ github.event.pull_request.head.sha }}`
|
|
|
|
<details>
|
|
<summary>Click to expand full results</summary>
|
|
|
|
```
|
|
${{ steps.compare.outputs.result }}
|
|
```
|
|
|
|
</details>
|
|
|
|
> Benchmarks run on `ubuntu-latest` via [Criterion](https://github.com/bheisler/criterion.rs) + [critcmp](https://github.com/BurntSushi/critcmp).
|
|
> Results may vary due to shared CI runners. Look for consistent >5% changes.
|
|
|
|
publish:
|
|
name: Publish to crates.io
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'push'
|
|
needs:
|
|
- fmt
|
|
- clippy
|
|
- test
|
|
- examples
|
|
- docs
|
|
- feature-check
|
|
- coverage
|
|
- msrv
|
|
- deny
|
|
- machete
|
|
- semver
|
|
- minimal-versions
|
|
- cross-platform
|
|
- cross-targets
|
|
- typos
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
- name: Install Rust
|
|
run: |
|
|
rustup override set stable
|
|
rustup update stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Check if version already published
|
|
id: check
|
|
run: |
|
|
CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
|
|
echo "version=$CARGO_VERSION" >> "$GITHUB_OUTPUT"
|
|
|
|
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://crates.io/api/v1/crates/optimizer/$CARGO_VERSION")
|
|
if [ "$HTTP_STATUS" = "200" ]; then
|
|
echo "Version $CARGO_VERSION already exists on crates.io, skipping publish"
|
|
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "Version $CARGO_VERSION not found on crates.io, will publish"
|
|
echo "skip=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Publish
|
|
if: steps.check.outputs.skip == 'false'
|
|
run: |
|
|
cargo publish --allow-dirty 2>&1 | tee publish_output.txt || {
|
|
if grep -q "already uploaded" publish_output.txt; then
|
|
echo "Version already published, skipping"
|
|
exit 0
|
|
fi
|
|
exit 1
|
|
}
|
|
env:
|
|
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|