Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 227 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: short
# sccache config
SCCACHE_GHA_ENABLED: true
RUSTC_WRAPPER: sccache

jobs:
# ──────────────────────────────────────────────
# Rust lint: fmt + clippy (fast, catches issues early)
# ──────────────────────────────────────────────
rust-lint:
name: Rust Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y protobuf-compiler libwebkit2gtk-4.1-dev libayatana-appindicator3-dev libgtk-3-dev libssl-dev

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Setup sccache
uses: SeedyROM/sccache-action@v0.0.10

- name: Cargo registry cache
uses: actions/cache@v5
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-registry-

- name: Check formatting
run: cargo fmt --all -- --check

- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings

# ──────────────────────────────────────────────
# Rust tests: full test suite
# ──────────────────────────────────────────────
rust-test:
name: Rust Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y protobuf-compiler libwebkit2gtk-4.1-dev libayatana-appindicator3-dev libgtk-3-dev libssl-dev

- uses: dtolnay/rust-toolchain@stable

- name: Setup sccache
uses: SeedyROM/sccache-action@v0.0.10

- name: Cargo registry cache
uses: actions/cache@v5
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-registry-

- name: Run tests
run: cargo test --all-features

# ──────────────────────────────────────────────
# Frontend: vitest unit tests + typecheck
# ──────────────────────────────────────────────
frontend-test:
name: Frontend Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: pnpm/action-setup@v4
with:
version: latest

- uses: actions/setup-node@v5
with:
node-version: 22

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"

- name: Cache pnpm store
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: pnpm-store-${{ runner.os }}-${{ hashFiles('app/pnpm-lock.yaml') }}
restore-keys: pnpm-store-${{ runner.os }}-

- name: Install dependencies
run: pnpm install
working-directory: app

- name: TypeScript check
run: pnpm exec tsc --noEmit
working-directory: app

- name: Vitest
run: pnpm test
working-directory: app

# ──────────────────────────────────────────────
# E2E: Playwright (needs Vite dev server + variance binary)
# ──────────────────────────────────────────────
e2e-test:
name: E2E Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y protobuf-compiler libwebkit2gtk-4.1-dev libayatana-appindicator3-dev libgtk-3-dev libssl-dev

- uses: dtolnay/rust-toolchain@stable

- name: Setup sccache
uses: SeedyROM/sccache-action@v0.0.10

- name: Cargo registry cache
uses: actions/cache@v5
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-registry-

- name: Build variance CLI binary
run: cargo build --bin variance

- uses: pnpm/action-setup@v4
with:
version: latest

- uses: actions/setup-node@v5
with:
node-version: 22

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"

- name: Cache pnpm store
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: pnpm-store-${{ runner.os }}-${{ hashFiles('app/pnpm-lock.yaml') }}
restore-keys: pnpm-store-${{ runner.os }}-

- name: Install dependencies
run: pnpm install
working-directory: app

- name: Install Playwright browsers
run: pnpm exec playwright install --with-deps chromium
working-directory: app

- name: Run E2E tests
run: pnpm exec playwright test
working-directory: app
env:
CI: true

- name: Upload Playwright report
uses: actions/upload-artifact@v6
if: ${{ !cancelled() }}
with:
name: playwright-report
path: |
app/test-results/
app/playwright-report/
if-no-files-found: ignore
retention-days: 14

# ──────────────────────────────────────────────
# Gate: all checks must pass
# ──────────────────────────────────────────────
ci-pass:
name: CI Pass
if: always()
needs: [rust-lint, rust-test, frontend-test, e2e-test]
runs-on: ubuntu-latest
steps:
- name: Check results
run: |
if [[ "${{ needs.rust-lint.result }}" != "success" ||
"${{ needs.rust-test.result }}" != "success" ||
"${{ needs.frontend-test.result }}" != "success" ||
"${{ needs.e2e-test.result }}" != "success" ]]; then
echo "One or more CI jobs failed"
exit 1
fi
echo "All CI checks passed"
Loading
Loading