name: CI
on:
push:
branches:
- main
- develop
- 'feature/**'
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
pull_request:
branches:
- main
- develop
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
RUSTFLAGS: "-C debuginfo=0"
jobs:
check:
name: Check & Lint
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-check-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-check-
${{ runner.os }}-cargo-
- name: Check formatting
run: cargo fmt --all -- --check
- name: Run clippy
run: cargo clippy --all-features --all-targets -- -D warnings
- name: Check documentation
run: cargo doc --all-features --no-deps
env:
RUSTDOCFLAGS: "-D warnings"
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
needs: check
strategy:
matrix:
feature-set:
- minimal
- standard
- full
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-unit-${{ matrix.feature-set }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-unit-${{ matrix.feature-set }}-
${{ runner.os }}-cargo-unit-
${{ runner.os }}-cargo-
- name: Run unit tests (${{ matrix.feature-set }})
run: cargo test --lib --features ${{ matrix.feature-set }} --verbose
- name: Run common tests
run: cargo test --test common_tests --features ${{ matrix.feature-set }} --verbose || true
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: check
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: limiteron
POSTGRES_PASSWORD: limiteron
POSTGRES_DB: limiteron_test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgres://limiteron:limiteron@localhost:5432/limiteron_test
REDIS_URL: redis://localhost:6379
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-integration-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-integration-
${{ runner.os }}-cargo-
- name: Wait for services
run: |
sleep 5
pg_isready -h localhost -p 5432 -U limiteron -d limiteron_test
- name: Run integration tests
run: cargo test --test integration_tests --features full -- --ignored --test-threads=1 || true
continue-on-error: true
- name: Run unified tests
run: cargo test --test unified_tests --features full --verbose || true
continue-on-error: true
coverage:
name: Code Coverage
runs-on: ubuntu-latest
needs: [unit-tests]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install tarpaulin
uses: actions-rs/install@v0.1
with:
crate: cargo-tarpaulin
version: latest
continue-on-error: true
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-coverage-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-coverage-
${{ runner.os }}-cargo-
- name: Generate coverage report
run: |
cargo tarpaulin --all-features --workspace --timeout 300 --out Xml --out Html --output-dir coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/cobertura.xml
flags: unittests
name: limiteron-coverage
fail_ci_if_error: true
verbose: true
- name: Upload coverage artifacts
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
retention-days: 30
security:
name: Security Audit
runs-on: ubuntu-latest
needs: check
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-deny
uses: actions-rs/install@v0.1
with:
crate: cargo-deny
version: latest
- name: Run security audit
run: cargo deny check advisories bans licenses sources
build:
name: Build Verification
runs-on: ubuntu-latest
needs: check
strategy:
matrix:
feature-set:
- minimal
- standard
- full
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-build-${{ matrix.feature-set }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-build-${{ matrix.feature-set }}-
${{ runner.os }}-cargo-build-
${{ runner.os }}-cargo-
- name: Build (${{ matrix.feature-set }})
run: cargo build --features ${{ matrix.feature-set }} --release --verbose
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.feature-set }}
path: target/release/liblimiteron.rlib
retention-days: 7
examples:
name: Examples Build
runs-on: ubuntu-latest
needs: check
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-examples-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-examples-
${{ runner.os }}-cargo-
- name: Build all examples
run: cargo build --examples --features full --verbose
ci-success:
name: CI Success
runs-on: ubuntu-latest
needs: [check, unit-tests, coverage, security, build, examples]
if: always()
steps:
- name: Check CI status
run: |
if [[ "${{ needs.check.result }}" != "success" || \
"${{ needs.unit-tests.result }}" != "success" || \
"${{ needs.build.result }}" != "success" ]]; then
echo "CI failed!"
exit 1
fi
echo "CI passed!"