Skip to content

CI

CI #711

Workflow file for this run

name: CI
# Simplified CI workflow with clear separation of concerns:
# - PR: Fast checks (fmt, clippy, basic tests) - must pass
# - Main: Full test suite across platforms
# - Schedule: Security & dependency audits
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
schedule:
# Daily security audit at 10:00 UTC (3:00 AM LA time)
- cron: '0 10 * * *'
workflow_dispatch:
inputs:
skip_tests:
description: 'Skip tests (for debugging)'
required: false
type: boolean
default: false
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# ============================================================================
# PR & Push Checks - Fast feedback (<5 minutes)
# ============================================================================
format:
name: Format Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
clippy:
name: Clippy Lints
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Build frontend
run: |
cd front-end
npm ci
npm run build
- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
test-quick:
name: Quick Tests (Ubuntu/stable)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || github.event_name == 'push'
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Build frontend
run: |
cd front-end
npm ci
npm run build
- name: Build
run: cargo build --verbose
- name: Run unit and CLI tests
if: ${{ !inputs.skip_tests }}
run: cargo test --lib --bins --verbose
- name: Run integration tests (parallel safe)
if: ${{ !inputs.skip_tests }}
run: |
cargo test --test integration_tests --verbose
cargo test --test interface_spec_test --verbose
- name: Clean up test database before doctor command
run: rm -rf ~/.intent-engine
- name: Test doctor command
run: cargo run --bin ie -- doctor
# ============================================================================
# Main Branch - Full Test Suite
# ============================================================================
test-full:
name: Full Tests (${{ matrix.os }} / ${{ matrix.rust }})
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# Linux
- os: ubuntu-latest
rust: stable
- os: ubuntu-latest
rust: beta
# macOS
- os: macos-latest
rust: stable
# Windows
- os: windows-latest
rust: stable
# Nightly (experimental)
- os: ubuntu-latest
rust: nightly
experimental: true
continue-on-error: ${{ matrix.experimental || false }}
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ matrix.rust }}-${{ matrix.os }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Build frontend
run: |
cd front-end
npm ci
npm run build
- name: Build
run: cargo build --verbose
- name: Run unit and CLI tests
if: ${{ !inputs.skip_tests }}
run: cargo test --lib --bins --verbose
- name: Run integration tests (parallel safe)
if: ${{ !inputs.skip_tests }}
run: |
cargo test --test integration_tests --verbose
cargo test --test interface_spec_test --verbose
- name: Build release
run: cargo build --release --verbose
- name: Upload artifacts on failure
if: failure()
uses: actions/upload-artifact@v5
with:
name: test-logs-${{ matrix.os }}-${{ matrix.rust }}
path: target/*/deps/*.log
retention-days: 7
# ============================================================================
# Documentation & Package
# ============================================================================
docs:
name: Documentation
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Check documentation
run: cargo doc --no-deps --all-features --document-private-items
env:
RUSTDOCFLAGS: -D warnings
- name: Test doc examples
run: cargo test --doc --all-features
package:
name: Package Check
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Build frontend
run: |
cd front-end
npm ci
npm run build
- name: Verify package
run: |
cargo package --allow-dirty
PKG_FILE=$(find target/package -name "intent-engine-*.crate" -type f | head -n 1)
echo "Found package: $PKG_FILE"
# Extract and test
tar -xzf "$PKG_FILE" -C target/package/
PKG_DIR=$(find target/package -maxdepth 1 -name "intent-engine-*" -type d | head -n 1)
cd "$PKG_DIR"
cargo build --release --verbose
# Run tests
cargo test --lib --bins --verbose
cargo test --test integration_tests --verbose
cargo test --test interface_spec_test --verbose
# ============================================================================
# Security & Dependencies (Daily Schedule)
# ============================================================================
security:
name: Security Audit
runs-on: ubuntu-latest
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- 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 advisories
run: cargo deny check
outdated:
name: Outdated Dependencies
runs-on: ubuntu-latest
if: github.event_name == 'schedule'
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- name: Install cargo-outdated
run: cargo install cargo-outdated
- name: Check outdated dependencies
run: cargo outdated --exit-code 1
continue-on-error: true
# ============================================================================
# PR Dependency Review
# ============================================================================
dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v6
- uses: actions/dependency-review-action@v4
continue-on-error: true
# ============================================================================
# Status Checks
# ============================================================================
ci-success:
name: CI Success
runs-on: ubuntu-latest
needs: [format, clippy, test-quick, docs]
if: always() && (github.event_name == 'pull_request' || github.event_name == 'push')
steps:
- name: Check all jobs
run: |
if [ "${{ needs.format.result }}" != "success" ]; then
echo "❌ Format check failed"
exit 1
fi
if [ "${{ needs.clippy.result }}" != "success" ]; then
echo "❌ Clippy check failed"
exit 1
fi
if [ "${{ needs.test-quick.result }}" != "success" ]; then
echo "❌ Quick tests failed"
exit 1
fi
if [ "${{ needs.docs.result }}" != "success" ]; then
echo "❌ Documentation check failed"
exit 1
fi
echo "✅ All CI checks passed!"
# ============================================================================
# Issue Creation on Failure (Schedule Only)
# ============================================================================
create-issue:
name: Create Issue on Failure
runs-on: ubuntu-latest
needs: [security, outdated]
if: always() && github.event_name == 'schedule' && (needs.security.result == 'failure' || needs.outdated.result == 'failure')
steps:
- uses: actions/github-script@v8
with:
script: |
const date = new Date().toISOString().split('T')[0];
const failures = [];
if ('${{ needs.security.result }}' === 'failure') {
failures.push('🔒 Security Audit');
}
if ('${{ needs.outdated.result }}' === 'failure') {
failures.push('📦 Outdated Dependencies');
}
const body = `## 🚨 Scheduled CI Failed - ${date}\n\n` +
`The following checks failed:\n\n` +
failures.map(f => `- ❌ ${f}`).join('\n') + '\n\n' +
`[View workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})\n\n` +
`---\n` +
`<sub>Auto-created by scheduled CI</sub>`;
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `🚨 CI Failure - ${date}`,
body: body,
labels: ['ci', 'automated', 'security']
});