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
80 changes: 80 additions & 0 deletions .github/workflows/accessibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Accessibility Tests

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
force_full_run:
description: 'Force a full accessibility run'
type: boolean
default: false

jobs:
changes:
runs-on: ubuntu-latest
outputs:
client: ${{ steps.filter.outputs.client }}
force_full_run: ${{ github.event.inputs.force_full_run || 'false' }}
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
client:
- 'client/**'
- 'shared/**'
- '.github/workflows/accessibility.yml'

a11y-tests:
name: Axe Accessibility Checks
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: "20"
cache: "npm"
cache-dependency-path: client/package-lock.json

- name: Install dependencies
working-directory: client
run: npm ci

- name: Install Playwright browsers
working-directory: client
run: npx playwright install --with-deps chromium

- name: Build client
working-directory: client
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
NEXT_PUBLIC_API_URL: http://localhost:3000
run: npm run build

- name: Run accessibility tests
working-directory: client
env:
E2E_BASE_URL: http://localhost:3000
run: |
npm start &
npx wait-on http://localhost:3000 --timeout 60000
npm run test:a11y

- name: Upload accessibility report
if: always()
uses: actions/upload-artifact@v7
with:
name: a11y-report
path: client/playwright-report/
retention-days: 14
74 changes: 68 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,60 @@ on:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
force_full_run:
description: 'Force a full CI run'
type: boolean
default: false

jobs:
# ──────────────────────────────────────────────
# Job 0: Detect changes
# ──────────────────────────────────────────────
changes:
runs-on: ubuntu-latest
outputs:
backend: ${{ steps.filter.outputs.backend }}
client: ${{ steps.filter.outputs.client }}
sdk: ${{ steps.filter.outputs.sdk }}
shared: ${{ steps.filter.outputs.shared }}
force_full_run: ${{ github.event.inputs.force_full_run || 'false' }}
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
backend:
- 'backend/**'
- 'shared/**'
- 'package.json'
- 'package-lock.json'
client:
- 'client/**'
- 'shared/**'
- 'package.json'
- 'package-lock.json'
sdk:
- 'sdk/**'
- 'shared/**'
- 'package.json'
- 'package-lock.json'
shared:
- 'shared/**'
- 'package.json'
- 'package-lock.json'

# ──────────────────────────────────────────────
# Job 1: Validate environment variables
# Must pass before the build job starts.
# ──────────────────────────────────────────────
validate-env:
name: Validate Environment Variables
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.client == 'true' || needs.changes.outputs.sdk == 'true' }}

steps:
- name: Checkout repository
Expand All @@ -25,6 +70,7 @@ jobs:
node-version: "20"

- name: Validate client environment variables
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
Expand All @@ -35,6 +81,7 @@ jobs:
run: node client/scripts/validate-env.js

- name: Validate backend environment variables
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' }}
env:
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
Expand All @@ -58,7 +105,8 @@ jobs:
validate-dependencies:
name: Validate Dependencies
runs-on: ubuntu-latest
needs: validate-env
needs: [changes, validate-env]
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.client == 'true' || needs.changes.outputs.sdk == 'true' }}

steps:
- name: Checkout repository
Expand All @@ -70,6 +118,7 @@ jobs:
node-version: "20"

- name: Check for 'latest' in client package.json
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}
run: |
if grep -q '"latest"' client/package.json; then
echo "❌ Error: 'latest' version found in client/package.json"
Expand All @@ -79,6 +128,7 @@ jobs:
echo "✅ No 'latest' versions found in client/package.json"

- name: Check for 'latest' in backend package.json
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' }}
run: |
if grep -q '"latest"' backend/package.json; then
echo "❌ Error: 'latest' version found in backend/package.json"
Expand All @@ -88,10 +138,12 @@ jobs:
echo "✅ No 'latest' versions found in backend/package.json"

- name: Validate client dependencies
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}
working-directory: client
run: node scripts/validate-deps.js

- name: Verify client lockfile is committed
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}
run: |
if [ ! -f "client/package-lock.json" ]; then
echo "❌ Error: client/package-lock.json not found"
Expand All @@ -101,6 +153,7 @@ jobs:
echo "✅ Client lockfile is committed"

- name: Verify backend lockfile is committed
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' }}
run: |
if [ ! -f "backend/package-lock.json" ]; then
echo "❌ Error: backend/package-lock.json not found"
Expand All @@ -110,6 +163,7 @@ jobs:
echo "✅ Backend lockfile is committed"

- name: Install client dependencies and verify lockfile
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}
working-directory: client
run: |
npm ci
Expand All @@ -121,6 +175,7 @@ jobs:
echo "✅ Client lockfile is up to date"

- name: Install backend dependencies and verify lockfile
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' }}
working-directory: backend
run: |
npm ci
Expand All @@ -138,7 +193,8 @@ jobs:
security-audit:
name: Security Audit
runs-on: ubuntu-latest
needs: validate-dependencies
needs: [changes, validate-dependencies]
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.client == 'true' }}

steps:
- name: Checkout repository
Expand All @@ -152,10 +208,12 @@ jobs:
cache-dependency-path: client/package-lock.json

- name: Audit client dependencies
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}
working-directory: client
run: npm audit --audit-level=high --omit=dev

- name: Audit backend dependencies
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' }}
working-directory: backend
run: npm audit --audit-level=high --omit=dev

Expand All @@ -166,7 +224,8 @@ jobs:
build-client:
name: Build Client
runs-on: ubuntu-latest
needs: [validate-dependencies, security-audit]
needs: [changes, validate-dependencies, security-audit]
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}

steps:
- name: Checkout repository
Expand Down Expand Up @@ -202,7 +261,8 @@ jobs:
test-sdk:
name: SDK — Build & Test
runs-on: ubuntu-latest
needs: [validate-env, security-audit]
needs: [changes, validate-env, security-audit]
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.sdk == 'true' }}

defaults:
run:
Expand Down Expand Up @@ -254,7 +314,8 @@ jobs:
test-client:
name: Test Client
runs-on: ubuntu-latest
needs: [validate-env, security-audit]
needs: [changes, validate-env, security-audit]
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}

steps:
- name: Checkout repository
Expand All @@ -278,7 +339,8 @@ jobs:
test-backend:
name: Test Backend
runs-on: ubuntu-latest
needs: [validate-dependencies, security-audit]
needs: [changes, validate-dependencies, security-audit]
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' }}

steps:
- name: Checkout repository
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ name: E2E Tests
on:
pull_request:
branches: [main]
paths:
- 'client/**'
- 'shared/**'
- '.github/workflows/e2e.yml'
workflow_dispatch:
inputs:
force_full_run:
description: 'Force a full E2E run'
type: boolean
default: false

jobs:
playwright:
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,38 @@ on:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
force_full_run:
description: 'Force a full lint run'
type: boolean
default: false

jobs:
changes:
runs-on: ubuntu-latest
outputs:
backend: ${{ steps.filter.outputs.backend }}
client: ${{ steps.filter.outputs.client }}
force_full_run: ${{ github.event.inputs.force_full_run || 'false' }}
steps:
- uses: actions/checkout@v6
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
backend:
- 'backend/**'
- 'shared/**'
client:
- 'client/**'
- 'shared/**'

lint-backend:
name: Lint Backend
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.backend == 'true' }}
defaults:
run:
working-directory: backend
Expand All @@ -32,6 +59,8 @@ jobs:
lint-client:
name: Lint Client
runs-on: ubuntu-latest
needs: changes
if: ${{ needs.changes.outputs.force_full_run == 'true' || needs.changes.outputs.client == 'true' }}
defaults:
run:
working-directory: client
Expand Down
Loading
Loading