Test and Build #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test and Build | |
| on: | |
| workflow_call: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| test-build: | |
| name: Test and Build | |
| runs-on: blacksmith-8vcpu-ubuntu-2404 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: 1.3.13 | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 | |
| with: | |
| node-version: latest | |
| - name: Mount Bun cache (Sticky Disk) | |
| uses: useblacksmith/stickydisk@4c034ba57b706cf0e3b4b0ce098c2a3b1071580c # v1 | |
| with: | |
| key: ${{ github.repository }}-bun-cache | |
| path: ~/.bun/install/cache | |
| - name: Mount node_modules (Sticky Disk) | |
| uses: useblacksmith/stickydisk@4c034ba57b706cf0e3b4b0ce098c2a3b1071580c # v1 | |
| with: | |
| key: ${{ github.repository }}-node-modules | |
| path: ./node_modules | |
| - name: Mount Turbo cache (Sticky Disk) | |
| uses: useblacksmith/stickydisk@4c034ba57b706cf0e3b4b0ce098c2a3b1071580c # v1 | |
| with: | |
| key: ${{ github.repository }}-turbo-cache | |
| path: ./.turbo | |
| - name: Restore Next.js build cache | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 | |
| with: | |
| path: ./apps/sim/.next/cache | |
| key: ${{ runner.os }}-nextjs-${{ hashFiles('bun.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nextjs- | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| # Surfaces known CVEs in the dependency tree. Non-blocking until the | |
| # existing advisory backlog is triaged, then flip to a required gate by | |
| # removing continue-on-error. | |
| - name: Security audit | |
| run: bun audit | |
| continue-on-error: true | |
| - name: Validate env flags | |
| run: | | |
| FILE="apps/sim/lib/core/config/env-flags.ts" | |
| ERRORS="" | |
| echo "Checking for hardcoded boolean env flags..." | |
| # Use perl for multiline matching to catch both: | |
| # export const isHosted = true | |
| # export const isHosted = | |
| # true | |
| HARDCODED=$(perl -0777 -ne 'while (/export const (is[A-Za-z]+)\s*=\s*\n?\s*(true|false)\b/g) { print " $1 = $2\n" }' "$FILE") | |
| if [ -n "$HARDCODED" ]; then | |
| ERRORS="${ERRORS}\n❌ Env flags must not be hardcoded to boolean literals!\n\nFound hardcoded flags:\n${HARDCODED}\n\nEnv flags should derive their values from environment variables.\n" | |
| fi | |
| echo "Checking env flag naming conventions..." | |
| # Check that all export const (except functions) start with 'is' | |
| # This finds exports like "export const someFlag" that don't start with "is" or "get" | |
| BAD_NAMES=$(grep -E "^export const [a-z]" "$FILE" | grep -vE "^export const (is|get)" | sed 's/export const \([a-zA-Z]*\).*/ \1/') | |
| if [ -n "$BAD_NAMES" ]; then | |
| ERRORS="${ERRORS}\n❌ Env flags must use 'is' prefix for boolean flags!\n\nFound incorrectly named flags:\n${BAD_NAMES}\n\nExample: 'hostedMode' should be 'isHostedMode'\n" | |
| fi | |
| if [ -n "$ERRORS" ]; then | |
| echo "" | |
| echo -e "$ERRORS" | |
| exit 1 | |
| fi | |
| echo "✅ All env flags are properly configured" | |
| - name: Check block registry invariants | |
| run: | | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| BASE_REF="origin/${{ github.base_ref }}" | |
| git fetch --depth=1 origin "${{ github.base_ref }}" 2>/dev/null || true | |
| else | |
| BASE_REF="HEAD~1" | |
| fi | |
| bun run apps/sim/scripts/check-block-registry.ts "$BASE_REF" | |
| - name: Lint code | |
| run: bun run lint:check | |
| - name: Enforce monorepo boundaries | |
| run: bun run check:boundaries | |
| - name: API contract boundary audit | |
| run: bun run check:api-validation:strict | |
| - name: Zustand v5 selector audit | |
| run: bun run check:zustand-v5 | |
| - name: React Query pattern audit | |
| run: bun run check:react-query | |
| - name: Client boundary import audit | |
| run: bun run check:client-boundary | |
| - name: Bare-icon theme-safety audit | |
| run: bun run check:bare-icons | |
| - name: Icon SVG path validity audit | |
| run: bun run check:icon-paths | |
| - name: Verify realtime prune graph | |
| run: bun run check:realtime-prune | |
| - name: Migration safety (zero-downtime) audit | |
| run: | | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| BASE_REF="origin/${{ github.base_ref }}" | |
| git fetch --depth=1 origin "${{ github.base_ref }}" 2>/dev/null || true | |
| else | |
| BASE_REF="HEAD~1" | |
| fi | |
| bun run check:migrations "$BASE_REF" | |
| - name: Type-check realtime server | |
| run: bunx turbo run type-check --filter=@sim/realtime | |
| - name: Run tests with coverage | |
| env: | |
| NODE_OPTIONS: '--no-warnings --max-old-space-size=8192' | |
| NEXT_PUBLIC_APP_URL: 'https://www.sim.ai' | |
| DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/simstudio' | |
| ENCRYPTION_KEY: '7cf672e460e430c1fba707575c2b0e2ad5a99dddf9b7b7e3b5646e630861db1c' # dummy key for CI only | |
| TURBO_CACHE_DIR: .turbo | |
| run: bun run test | |
| - name: Check schema and migrations are in sync | |
| working-directory: packages/db | |
| run: | | |
| bunx drizzle-kit generate --config=./drizzle.config.ts | |
| if [ -n "$(git status --porcelain ./migrations)" ]; then | |
| echo "❌ Schema and migrations are out of sync!" | |
| echo "Run 'cd packages/db && bunx drizzle-kit generate' and commit the new migrations." | |
| git status --porcelain ./migrations | |
| git diff ./migrations | |
| exit 1 | |
| fi | |
| echo "✅ Schema and migrations are in sync" | |
| - name: Build application | |
| env: | |
| NODE_OPTIONS: '--no-warnings --max-old-space-size=8192' | |
| NEXT_PUBLIC_APP_URL: 'https://www.sim.ai' | |
| DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/simstudio' | |
| STRIPE_SECRET_KEY: 'dummy_key_for_ci_only' | |
| STRIPE_WEBHOOK_SECRET: 'dummy_secret_for_ci_only' | |
| RESEND_API_KEY: 'dummy_key_for_ci_only' | |
| AWS_REGION: 'us-west-2' | |
| ENCRYPTION_KEY: '7cf672e460e430c1fba707575c2b0e2ad5a99dddf9b7b7e3b5646e630861db1c' # dummy key for CI only | |
| TURBO_CACHE_DIR: .turbo | |
| run: bunx turbo run build --filter=sim | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@0fb7174895f61a3b6b78fc075e0cd60383518dac # v5 | |
| with: | |
| directory: ./apps/sim/coverage | |
| fail_ci_if_error: false | |
| verbose: true |