name: Comprehensive CI/CD Pipeline
on:
push:
branches: [ main, develop, "release/*" ]
pull_request:
branches: [ main, develop ]
schedule:
- cron: '0 0 * * 0'
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
RUST_LOG: info
jobs:
quality:
name: Code Quality & Formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
run: cargo fmt --all -- --check
- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Check documentation
run: cargo doc --no-deps --all-features --document-private-items
security:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install cargo-audit
run: cargo install cargo-audit
- name: Run security audit
run: cargo audit
- name: Install cargo-deny
run: cargo install cargo-deny
- name: Run cargo-deny
run: cargo deny check
compile:
name: Compilation Tests
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
rust: [stable, beta, nightly]
exclude:
- os: windows-latest
rust: nightly
- os: macos-latest
rust: nightly
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.rust == 'nightly' }}
steps:
- uses: actions/checkout@v4
- name: Install Rust ${{ matrix.rust }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build debug
run: cargo build --all-features
- name: Build release
run: cargo build --release --all-features
- name: Test compilation of all binaries
run: |
cargo build --bin opencrates
cargo build --bin opencrates-server
cargo build --bin opencrates-cli
test:
name: Test Suite
runs-on: ubuntu-latest
services:
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
postgres:
image: postgres:16
ports:
- '5432:5432'
env:
POSTGRES_PASSWORD: pg
options: >-
--health-cmd "pg_isready"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libssl-dev pkg-config
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
- name: Run unit tests
run: cargo test --lib --all-features --verbose
env:
RUST_LOG: debug
- name: Run integration tests
run: cargo test --test '*' --all-features --verbose
env:
RUST_LOG: debug
REDIS_URL: redis://localhost:6379
DATABASE_URL: postgres://postgres:testpass@localhost:5432/testdb
- name: Run doc tests
run: cargo test --doc --all-features --verbose
coverage:
name: Code Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-coverage-${{ hashFiles('**/Cargo.lock') }}
- name: Generate code coverage
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
- name: Upload to codecov.io
uses: codecov/codecov-action@v3
with:
files: lcov.info
fail_ci_if_error: true
benchmark:
name: Performance Benchmarks
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-bench-${{ hashFiles('**/Cargo.lock') }}
- name: Run benchmarks
run: cargo bench --all-features
- name: Store benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
name: Rust Benchmark
tool: 'cargo'
output-file-path: target/criterion/report/index.html
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
docker:
name: Docker Build & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: opencrates:test
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Test Docker image
run: |
docker run --rm opencrates:test --version
docker run --rm opencrates:test --help
examples:
name: Example Projects
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-examples-${{ hashFiles('**/Cargo.lock') }}
- name: Build OpenCrates
run: cargo build --release
- name: Test example generation
run: |
mkdir -p test-examples
./target/release/opencrates generate --name test-crate --output test-examples/
cd test-examples/test-crate
cargo check
cargo test
memory:
name: Memory Safety Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@nightly
with:
components: miri
- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-miri-${{ hashFiles('**/Cargo.lock') }}
- name: Run Miri
run: cargo +nightly miri test --lib
env:
MIRIFLAGS: -Zmiri-disable-isolation
release:
name: Release Preparation
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/')
needs: [quality, security, compile, test, coverage, docker]
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-release
run: cargo install cargo-release
- name: Prepare release
run: |
cargo release --dry-run
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
- name: Create Release Artifacts
run: |
cargo build --release --all-features
mkdir -p artifacts
cp target/release/opencrates artifacts/
cp target/release/opencrates-server artifacts/
cp target/release/opencrates-cli artifacts/
tar -czf artifacts/opencrates-${{ github.ref_name }}.tar.gz -C artifacts .
- name: Upload Release Artifacts
uses: actions/upload-artifact@v4
with:
name: release-artifacts
path: artifacts/
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
needs: [quality, security, compile, test, coverage, docker]
environment: staging
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
run: |
echo "Deploying to staging environment..."
# Add actual deployment steps here
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
needs: [quality, security, compile, test, coverage, docker, benchmark]
environment: production
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: |
echo "Deploying to production environment..."
# Add actual deployment steps here
test-and-docs:
name: Test & Build Docs
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
ports: ['5432:5432']
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: pg
POSTGRES_DB: test
options: >-
--health-cmd "pg_isready -U postgres -d test"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
- name: Install tarpaulin for code coverage
uses: taiki-e/install-action@v2
with:
tool: cargo-tarpaulin
- name: Run Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Run Rust tests
run: |
export DATABASE_URL=postgres://postgres:pg@localhost:5432/test
cargo test --all-features --all-targets
env:
POSTGRES_PASSWORD: pg
- name: Run code coverage
run: cargo tarpaulin --workspace --timeout 120 --skip-clean --ignore-tests
- name: Install mdBook
run: cargo install mdbook mdbook-mermaid mdbook-widdershins --locked
- name: Install Node.js for doc generator
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install widdershins
run: npm install -g widdershins
- name: Generate docs content
run: ./scripts/gen_openapi_md.sh
- name: Build documentation
run: mdbook build docs
- name: Deploy to GitHub Pages
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/book
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'
commit_message: 'docs: Deploy handbook from commit ${{ github.sha }}'