Files
mcp-docx/.github/workflows/ci.yml
T
Andy d4ebdbf6a9 CLI: inline font download + checksum verification
- Add `fonts download` and `fonts verify` subcommands
- Implement Rust-based downloader (ureq + tar + flate2) with pinned sources
- Verify SHA-256 for Liberation and Noto Sans TTFs for reproducibility
- Keep binary behind `build-bin` feature; library build unaffected
2025-08-11 15:04:47 +08:00

438 lines
12 KiB
YAML

name: Continuous Integration
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
schedule:
# Run tests daily at 2 AM UTC
- cron: '0 2 * * *'
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
test:
name: Test Suite
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
rust: [stable, beta, nightly]
exclude:
# Reduce matrix size by excluding some combinations
- os: windows-latest
rust: beta
- os: windows-latest
rust: nightly
- os: macos-latest
rust: beta
include:
# Add minimum supported Rust version
- os: ubuntu-latest
rust: 1.70.0
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
components: rustfmt, clippy
- name: Cache Cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ matrix.rust }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-${{ matrix.rust }}-
${{ runner.os }}-cargo-
- name: Install system dependencies (Ubuntu)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
- name: Install system dependencies (macOS)
if: matrix.os == 'macos-latest'
run: |
brew update
brew install pkg-config freetype jpeg libpng
- name: Check code formatting
if: matrix.rust == 'stable'
run: cargo fmt --all -- --check
- name: Run Clippy lints (library only)
if: matrix.rust == 'stable'
run: cargo clippy --lib -- -D warnings
- name: Build project (no extra features)
run: cargo build --verbose
- name: Run unit tests
run: cargo test --verbose --lib
- name: Run integration tests (opt-in)
if: contains(github.event.head_commit.message, '[integration]')
run: cargo test --verbose --test args_tests
- name: Run doc tests (opt-in)
if: contains(github.event.head_commit.message, '[full-ci]')
run: cargo test --verbose --doc
- name: Test with minimal features (opt-in)
if: contains(github.event.head_commit.message, '[full-ci]')
run: cargo test --verbose --no-default-features --lib
- name: Test with all features (opt-in)
if: contains(github.event.head_commit.message, '[full-ci]')
run: cargo test --verbose --all-features --lib
security:
name: Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout code
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: ubuntu-cargo-audit-${{ hashFiles('**/Cargo.lock') }}
- 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: Check licenses and dependencies
run: cargo deny check
coverage:
name: Code Coverage
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Generate coverage report (library only)
run: |
cargo llvm-cov --lib --workspace --lcov --output-path lcov.info
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: lcov.info
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
benchmarks:
name: Performance Benchmarks
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
- name: Cache Cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ubuntu-cargo-bench-${{ hashFiles('**/Cargo.lock') }}
- name: Run benchmarks
run: cargo bench --all-features
- name: Store benchmark results
uses: benchmark-action/github-action-benchmark@v1
with:
tool: 'cargo'
output-file-path: target/criterion/reports/index.html
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
comment-on-alert: true
alert-threshold: '200%'
fail-on-alert: true
memory-safety:
name: Memory Safety Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@nightly
with:
components: rust-src
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
- name: Install Miri
run: rustup component add miri
- name: Run Miri tests
run: |
cargo miri setup
# Run a subset of tests with Miri (full test suite might be too slow)
cargo miri test --lib -- --test-threads=1
env:
MIRIFLAGS: -Zmiri-strict-provenance
docker:
if: contains(github.event.head_commit.message, '[docker]')
name: Docker Build Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
run: |
cat > Dockerfile << 'EOF'
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
RUN cargo build --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y \
libssl3 \
libfontconfig1 \
libfreetype6 \
libjpeg62-turbo \
libpng16-16 \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/docx-mcp /usr/local/bin/
EXPOSE 8080
CMD ["docx-mcp"]
EOF
docker buildx build --tag docx-mcp:test .
- name: Test Docker container
run: |
# Start container in background
docker run -d --name docx-mcp-test -p 8080:8080 docx-mcp:test
sleep 10
# Basic health check (adapt based on your server's health endpoint)
docker logs docx-mcp-test
docker stop docx-mcp-test
docker rm docx-mcp-test
release-check:
name: Release Readiness
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
- name: Check that release builds (library only)
run: cargo build --release
- name: Verify package can be published
run: cargo package --dry-run
- name: Generate documentation
run: cargo doc --all-features --no-deps
- name: Check documentation links
run: cargo doc --all-features --no-deps --open || true
integration:
if: contains(github.event.head_commit.message, '[integration]')
name: Integration Tests
runs-on: ubuntu-latest
services:
# Add any services your integration tests might need
# For example, if you need a test database or cache
redis:
image: redis:7-alpine
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
- name: Run integration tests (focused)
run: |
export RUST_LOG=debug
cargo test --test args_tests -- --nocapture --test-threads=1
env:
RUST_LOG: debug
stress-test:
name: Stress Testing
runs-on: ubuntu-latest
if: github.event_name == 'schedule' || contains(github.event.head_commit.message, '[stress-test]')
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libssl-dev \
libfontconfig1-dev \
libfreetype6-dev \
libjpeg-dev \
libpng-dev
- name: Build in release mode
run: cargo build --release --all-features
- name: Run stress tests
run: |
export STRESS_TEST=1
export RUST_LOG=info
cargo test --release --test performance_tests -- --ignored --test-threads=1
cargo test --release --test e2e_workflow_tests -- --ignored --test-threads=1
notify:
name: Notify Results
runs-on: ubuntu-latest
needs: [test, security, coverage, benchmarks]
if: always() && (github.event_name == 'push' && github.ref == 'refs/heads/main')
steps:
- name: Notify on success
if: ${{ needs.test.result == 'success' && needs.security.result == 'success' && (needs.coverage.result == 'success' || needs.coverage.result == 'skipped') }}
run: |
echo "✅ All CI checks passed for main branch!"
# Add webhook notification here if needed
- name: Notify on failure
if: ${{ needs.test.result == 'failure' || needs.security.result == 'failure' || needs.coverage.result == 'failure' }}
run: |
echo "❌ CI checks failed for main branch!"
# Add failure notification here if needed
exit 1