name: Scribe CI/CD Pipeline
on:
push:
branches: [main, master, develop]
pull_request:
branches: [main, master]
schedule:
- cron: '0 2 * * *'
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
rust-core:
name: Rust Core - Build & Test
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
- name: Check Rust formatting
run: cargo fmt --all -- --check
- name: Run Clippy lints
run: cargo clippy --lib --bins --tests --all-features -- -D warnings
- name: Build all workspace crates
run: cargo build --workspace --all-features
- name: Run Rust unit tests
run: cargo test --workspace --all-features
- name: Run Rust integration tests
run: |
cargo test --workspace --all-features --test '*'
- name: Build scribe binaries
run: |
cargo build -p scribe-analyzer --bin scribe --release
cargo build -p scribe-webservice --bin scribe-web --release
- name: Test CLI functionality
run: |
./target/release/scribe --version
./target/release/scribe --help
./target/release/scribe-web --version
./target/release/scribe-web --help
- name: Upload Rust artifacts
uses: actions/upload-artifact@v4
with:
name: rust-artifacts
path: |
target/release/scribe
target/release/scribe-web
retention-days: 7
e2e-tests:
name: E2E Tests - Library & CLI
runs-on: ubuntu-latest
needs: rust-core
timeout-minutes: 45
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
workspaces: .
- name: Download Rust artifacts
uses: actions/download-artifact@v4
with:
name: rust-artifacts
path: target/release/
- name: Make binaries executable
run: |
chmod +x target/release/scribe
chmod +x target/release/scribe-web
- name: Setup e2e test environment
run: |
cd tests
make check-deps
make deps
- name: Run library unit tests
run: |
cd tests
make test-lib
- name: Build Scribe for e2e tests
run: |
cd tests
make build
- name: Run CLI parameter tests
run: |
cd tests
make test-cli
- name: Upload e2e test results
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-test-results
path: |
tests/artifacts/
tests/logs/
retention-days: 7
webui-e2e:
name: Web UI E2E Tests
runs-on: ubuntu-latest
needs: rust-core
timeout-minutes: 60
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
workspaces: .
- name: Download Rust artifacts
uses: actions/download-artifact@v4
with:
name: rust-artifacts
path: target/release/
- name: Make binaries executable
run: |
chmod +x target/release/scribe
chmod +x target/release/scribe-web
- name: Setup test environment
run: |
cd tests
make check-deps
make deps
- name: Install Playwright browsers
run: |
cd tests
bun run playwright:install
- name: Build Scribe for web UI tests
run: |
cd tests
make build
- name: Run Web UI tests
run: |
cd tests
make test-webui
env:
CI: true
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: |
tests/playwright-report/
tests/test-results/
retention-days: 7
integration:
name: Integration & Smoke Tests
runs-on: ubuntu-latest
needs: [rust-core, e2e-tests]
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install Bun
uses: oven-sh/setup-bun@v1
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
workspaces: .
- name: Download Rust artifacts
uses: actions/download-artifact@v4
with:
name: rust-artifacts
path: target/release/
- name: Make binaries executable
run: |
chmod +x target/release/scribe
chmod +x target/release/scribe-web
- name: Smoke test - Scribe on itself
run: |
# Test Scribe analyzing its own codebase
./target/release/scribe-web . --token-budget 10000 --no-browser --port 9999 &
SERVER_PID=$!
# Wait for server to start
sleep 10
# Check if server is responding
curl -f http://localhost:9999/ || echo "Server not responding"
# Clean shutdown
kill $SERVER_PID || true
wait $SERVER_PID 2>/dev/null || true
- name: Test different CLI configurations
run: |
# Test various CLI parameter combinations
./target/release/scribe-web . --token-budget 5000 --max-file-size 100000 --no-exclude-tests --no-browser --port 9998 &
SERVER_PID=$!
sleep 5
kill $SERVER_PID || true
wait $SERVER_PID 2>/dev/null || true
- name: Performance baseline test
run: |
# Quick performance test
time ./target/release/scribe-web . --token-budget 1000 --no-browser --port 9997 &
SERVER_PID=$!
sleep 3
kill $SERVER_PID || true
wait $SERVER_PID 2>/dev/null || true
security:
name: Security & Quality
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
workspaces: .
- name: Run cargo audit
run: |
cargo install cargo-audit
cargo audit
- name: Run cargo deny
run: |
cargo install cargo-deny
cargo deny check
- name: Check for common security issues
run: |
# Check for hardcoded secrets (basic check)
if grep -r "password\|secret\|key\|token" --include="*.rs" . | grep -v "// " | grep -v "test"; then
echo "Warning: Potential hardcoded secrets found"
fi
- name: Validate dependencies
run: |
cargo tree --duplicates
release-check:
name: Release Readiness
runs-on: ubuntu-latest
needs: [rust-core, e2e-tests, webui-e2e, integration, security]
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Check release build
run: |
cargo build --release --workspace
- name: Validate documentation
run: |
cargo doc --workspace --all-features --no-deps
- name: Check version consistency
run: |
# Ensure all workspace crates have the same version
EXPECTED_VERSION=$(grep '^version' Cargo.toml | head -1 | cut -d'"' -f2)
echo "Expected version: $EXPECTED_VERSION"
for crate in scribe-*; do
if [ -f "$crate/Cargo.toml" ]; then
CRATE_VERSION=$(grep '^version.workspace = true' "$crate/Cargo.toml" || grep '^version = ' "$crate/Cargo.toml" | cut -d'"' -f2)
if [ -n "$CRATE_VERSION" ] && [ "$CRATE_VERSION" != "true" ] && [ "$CRATE_VERSION" != "$EXPECTED_VERSION" ]; then
echo "Version mismatch in $crate: $CRATE_VERSION"
exit 1
fi
fi
done
- name: Generate release summary
run: |
echo "# Scribe Release Summary" > release-summary.md
echo "" >> release-summary.md
echo "**Version:** $(grep '^version' Cargo.toml | head -1 | cut -d'"' -f2)" >> release-summary.md
echo "**Commit:** ${{ github.sha }}" >> release-summary.md
echo "**Date:** $(date -Iseconds)" >> release-summary.md
echo "" >> release-summary.md
echo "## Test Results" >> release-summary.md
echo "- ✅ Rust core tests passed" >> release-summary.md
echo "- ✅ E2E tests passed" >> release-summary.md
echo "- ✅ Web UI tests passed" >> release-summary.md
echo "- ✅ Integration tests passed" >> release-summary.md
echo "- ✅ Security checks passed" >> release-summary.md
- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
name: release-summary
path: release-summary.md
retention-days: 30
status:
name: CI Status Summary
runs-on: ubuntu-latest
needs: [rust-core, e2e-tests, webui-e2e, integration, security]
if: always()
steps:
- name: Check overall status
run: |
echo "==================================="
echo "Scribe CI/CD Pipeline Summary"
echo "==================================="
echo "Rust Core: ${{ needs.rust-core.result }}"
echo "E2E Tests: ${{ needs.e2e-tests.result }}"
echo "Web UI Tests: ${{ needs.webui-e2e.result }}"
echo "Integration: ${{ needs.integration.result }}"
echo "Security: ${{ needs.security.result }}"
echo "==================================="
# Determine overall status
if [[ "${{ needs.rust-core.result }}" == "success" &&
"${{ needs.e2e-tests.result }}" == "success" &&
"${{ needs.integration.result }}" == "success" &&
"${{ needs.security.result }}" == "success" ]]; then
echo "🎉 Overall Status: SUCCESS"
echo "All critical tests passed!"
exit 0
else
echo "❌ Overall Status: FAILURE"
echo "Some tests failed - review the logs above"
exit 1
fi