Skip to content

feat: Turborepo remote caching for all CI steps #5

feat: Turborepo remote caching for all CI steps

feat: Turborepo remote caching for all CI steps #5

Workflow file for this run

name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
web:
name: Web (lint + type-check + test + build)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Restore Next.js build cache
uses: actions/cache@v4
with:
path: apps/web/.next/cache
key: nextjs-${{ runner.os }}-${{ hashFiles('apps/web/**.[jt]s', 'apps/web/**.[jt]sx', 'pnpm-lock.yaml') }}
restore-keys: nextjs-${{ runner.os }}-
- name: lint (ESLint)
run: pnpm lint
working-directory: apps/web
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
- name: format check (Prettier)
run: pnpm prettier --check "**/*.{ts,tsx,md,json}" --ignore-path .gitignore
- name: type-check
run: pnpm type-check
working-directory: apps/web
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
- run: pnpm test
working-directory: apps/web
- name: Run tests with coverage
run: pnpm vitest run --coverage
working-directory: apps/web
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: apps/web/coverage/lcov.info
flags: web
fail_ci_if_error: false
- run: pnpm build
working-directory: apps/web
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
NEXT_PUBLIC_STELLAR_NETWORK: testnet
NEXT_PUBLIC_ENERGY_TOKEN_ID: placeholder
NEXT_PUBLIC_AUDIT_REGISTRY_ID: placeholder
NEXT_PUBLIC_COMMUNITY_GOVERNANCE_ID: placeholder
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
MINTER_SECRET_KEY: ${{ secrets.MINTER_SECRET_KEY }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
playwright-e2e:
name: Playwright E2E
runs-on: ubuntu-latest
needs: web
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm --filter @solarproof/web exec playwright install chromium
- run: pnpm e2e
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL || 'https://placeholder.supabase.co' }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY || 'placeholder' }}
NEXT_PUBLIC_STELLAR_NETWORK: testnet
NEXT_PUBLIC_ENERGY_TOKEN_ID: placeholder
NEXT_PUBLIC_AUDIT_REGISTRY_ID: placeholder
NEXT_PUBLIC_COMMUNITY_GOVERNANCE_ID: placeholder
- name: Upload Playwright artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-test-results
path: apps/web/test-results
openapi:
name: OpenAPI spec validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Validate openapi.yaml
run: npx --yes @redocly/cli@1 lint openapi.yaml --format=github-actions
license-compliance:
name: License compliance check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: npx license-checker --onlyAllow "$(node -e "const c=require('./.license-checker.json');console.log(c.allowedLicenses.join(';'))")" --excludePrivatePackages
contracts:
name: Contracts (fmt + clippy + test)
runs-on: ubuntu-latest
env:
# Rotate accounts per run to avoid faucet rate limits
CI_ADMIN_ADDRESS: ${{ vars.CI_ADMIN_ADDRESS || '' }}
CI_MINTER_ADDRESS: ${{ vars.CI_MINTER_ADDRESS || '' }}
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain (pinned via rust-toolchain.toml)
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.88.0"
targets: wasm32-unknown-unknown
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: apps/contracts
- name: fmt
run: cargo fmt --all -- --check
working-directory: apps/contracts
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
- name: clippy
run: cargo clippy --all-targets --all-features -- -D warnings
working-directory: apps/contracts
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
- name: test
run: cargo test --all
working-directory: apps/contracts
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
proptest:
name: Property-based tests (proptest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain (pinned via rust-toolchain.toml)
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.88.0"
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
workspaces: apps/contracts/proptest
- name: Run proptest suite
run: cargo test
working-directory: apps/contracts/proptest
fuzz:
name: Fuzz (time-limited, corpus only)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust nightly (required by cargo-fuzz)
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
- uses: Swatinem/rust-cache@v2
with:
workspaces: apps/contracts/fuzz
- name: Install cargo-fuzz
run: cargo install cargo-fuzz --locked
- name: fuzz_mint (30 s)
run: cargo fuzz run fuzz_mint -- -max_total_time=30 corpus/fuzz_mint
working-directory: apps/contracts/fuzz
- name: fuzz_anchor (30 s)
run: cargo fuzz run fuzz_anchor -- -max_total_time=30 corpus/fuzz_anchor
working-directory: apps/contracts/fuzz
- name: fuzz_vote (30 s)
run: cargo fuzz run fuzz_vote -- -max_total_time=30 corpus/fuzz_vote
working-directory: apps/contracts/fuzz
image-scan:
name: Docker image vulnerability scan (Trivy)
runs-on: ubuntu-latest
needs: web
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build \
--file apps/web/Dockerfile \
--tag solarproof/web:${{ github.sha }} \
.
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.28.0
with:
image-ref: solarproof/web:${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: CRITICAL
exit-code: '1'
ignore-unfixed: true
- name: Upload Trivy SARIF results as artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: trivy-scan-results
path: trivy-results.sarif
retention-days: 30
- name: Upload SARIF to GitHub Security tab
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif