403 lines
12 KiB
YAML
403 lines
12 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
pull_request:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
quality:
|
|
name: Quality Gates
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 45
|
|
env:
|
|
DATABASE_URL: postgresql://toolctrl:toolctrl@localhost:5432/toolctrl?schema=public
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Enable Corepack
|
|
run: corepack enable
|
|
|
|
- name: Prepare pnpm 10.33.0
|
|
run: corepack prepare pnpm@10.33.0 --activate
|
|
|
|
- name: Configure pnpm store
|
|
run: pnpm config set store-dir .pnpm-store
|
|
|
|
- name: Cache pnpm store
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: .pnpm-store
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile --prefer-offline
|
|
|
|
- name: Verify GitHub CI workflow
|
|
run: pnpm run verify:github-ci-workflow
|
|
|
|
- name: Verify Gitea CI workflow
|
|
run: pnpm run verify:gitea-ci-workflow
|
|
|
|
- name: Verify Gitea deploy workflow
|
|
run: pnpm run verify:deploy-workflow
|
|
|
|
- name: Verify deploy readiness
|
|
run: pnpm run verify:deploy-readiness
|
|
|
|
- name: Verify CI baseline
|
|
run: pnpm run verify:ci-baseline
|
|
|
|
- name: Verify source health
|
|
run: pnpm run verify:source-health
|
|
|
|
- name: Verify ESLint baseline
|
|
run: pnpm run verify:eslint-baseline
|
|
|
|
- name: Verify env drift
|
|
run: pnpm run verify:env-drift
|
|
|
|
- name: Verify health baseline
|
|
run: pnpm run verify:health-baseline
|
|
|
|
- name: Verify API inventory
|
|
run: pnpm run verify:api-inventory
|
|
|
|
- name: Verify tenant isolation report
|
|
run: pnpm run verify:tenant-isolation-report
|
|
|
|
- name: Verify sidebar routes
|
|
run: pnpm run verify:sidebar-routes
|
|
|
|
- name: Verify i18n keys
|
|
run: pnpm run verify:i18n
|
|
|
|
- name: Verify Tenant Auth tenant and onboarding gates
|
|
run: |
|
|
pnpm run verify:tenant-auth-baseline
|
|
pnpm run verify:onboarding-flow
|
|
|
|
- name: Verify Phase C package boundaries
|
|
run: pnpm run verify:phase-c-boundaries
|
|
|
|
- name: Verify Feature Manifest plugin removal gates
|
|
run: |
|
|
pnpm run verify:core-build-without-plugins-smoke
|
|
pnpm run verify:removed-modules
|
|
|
|
- name: Verify UI mock static baseline
|
|
run: pnpm run verify:ui-visual
|
|
|
|
- name: Test UI mock hot-swap
|
|
run: pnpm run test:hot-swap
|
|
|
|
- name: Verify accessibility coverage
|
|
run: pnpm run verify:a11y-coverage
|
|
|
|
- name: Test accessibility smoke
|
|
run: pnpm run test:a11y
|
|
|
|
- name: Verify documentation gates
|
|
run: |
|
|
pnpm run verify:porting-docs-baseline
|
|
pnpm run verify:production-docs
|
|
pnpm run verify:release-docs
|
|
pnpm run verify:docs-links
|
|
|
|
- name: Typecheck
|
|
run: pnpm typecheck
|
|
|
|
- name: Lint
|
|
run: pnpm lint
|
|
|
|
- name: Foundation package tests
|
|
run: pnpm run test:foundation
|
|
|
|
- name: Workspace package tests
|
|
run: pnpm run test:packages
|
|
|
|
- name: Mobile wrapper tests
|
|
run: pnpm run test:mobile
|
|
|
|
- name: Unit tests
|
|
run: pnpm test
|
|
|
|
- name: Build
|
|
env:
|
|
TOOLCTRL_BUILD_SOURCEMAPS: "1"
|
|
run: pnpm run build:ci
|
|
|
|
- name: Verify bundle size
|
|
run: pnpm run verify:bundle-size
|
|
|
|
- name: Verify web Sentry sourcemaps
|
|
run: test -n "$(find apps/web/build/client -type f -name '*.map' -print -quit)"
|
|
|
|
- name: Upload web Sentry sourcemaps
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: web-client-sourcemaps
|
|
path: apps/web/build/client
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
- name: Verify production seed artifact
|
|
run: pnpm run verify:production-seed-artifact
|
|
|
|
api:
|
|
name: API Service
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 25
|
|
env:
|
|
DATABASE_URL: postgresql://toolctrl:toolctrl@localhost:5432/toolctrl?schema=public
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Enable Corepack
|
|
run: corepack enable
|
|
|
|
- name: Prepare pnpm 10.33.0
|
|
run: corepack prepare pnpm@10.33.0 --activate
|
|
|
|
- name: Configure pnpm store
|
|
run: pnpm config set store-dir .pnpm-store
|
|
|
|
- name: Cache pnpm store
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: .pnpm-store
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile --prefer-offline
|
|
|
|
- name: Verify OpenAPI security
|
|
run: pnpm run verify:openapi-security
|
|
|
|
- name: Typecheck API
|
|
run: pnpm --filter @toolctrl/api typecheck
|
|
|
|
- name: Test API
|
|
run: pnpm exec vitest run apps/api/src
|
|
|
|
- name: Build API
|
|
run: pnpm --filter @toolctrl/api build
|
|
|
|
worker:
|
|
name: Worker Service
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 25
|
|
env:
|
|
DATABASE_URL: postgresql://toolctrl:toolctrl@localhost:5432/toolctrl?schema=public
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Enable Corepack
|
|
run: corepack enable
|
|
|
|
- name: Prepare pnpm 10.33.0
|
|
run: corepack prepare pnpm@10.33.0 --activate
|
|
|
|
- name: Configure pnpm store
|
|
run: pnpm config set store-dir .pnpm-store
|
|
|
|
- name: Cache pnpm store
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: .pnpm-store
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile --prefer-offline
|
|
|
|
- name: Typecheck Worker
|
|
run: pnpm --filter @toolctrl/worker typecheck
|
|
|
|
- name: Test Worker
|
|
run: pnpm --filter @toolctrl/worker exec vitest run
|
|
|
|
- name: Build Worker
|
|
run: pnpm --filter @toolctrl/worker build
|
|
|
|
- name: Health Check Worker
|
|
run: pnpm --filter @toolctrl/worker health
|
|
env:
|
|
WORKER_ENABLED: "false"
|
|
|
|
database:
|
|
name: Database Checks
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Enable Corepack
|
|
run: corepack enable
|
|
|
|
- name: Prepare pnpm 10.33.0
|
|
run: corepack prepare pnpm@10.33.0 --activate
|
|
|
|
- name: Configure pnpm store
|
|
run: pnpm config set store-dir .pnpm-store
|
|
|
|
- name: Cache pnpm store
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: .pnpm-store
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile --prefer-offline
|
|
|
|
- name: Generate database client
|
|
run: pnpm run db:generate
|
|
env:
|
|
DATABASE_URL: postgresql://toolctrl:toolctrl@localhost:5432/toolctrl?schema=public
|
|
|
|
- name: Verify database migration status
|
|
if: github.event_name != 'pull_request'
|
|
run: pnpm run verify:db-migrate-status
|
|
env:
|
|
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
|
|
- name: Test database package
|
|
run: pnpm --filter @toolctrl/db test
|
|
|
|
docker-smoke:
|
|
name: Docker Smoke
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
needs: [quality, api, worker, database]
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Build web Docker target
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: .
|
|
target: web
|
|
build-args: APP_REVISION=ci-smoke-revision
|
|
tags: toolctrl-web:smoke
|
|
load: true
|
|
push: false
|
|
cache-from: type=gha,scope=toolctrl-web-smoke
|
|
cache-to: type=gha,mode=max,scope=toolctrl-web-smoke
|
|
|
|
- name: Validate web Docker artifacts
|
|
run: docker run --rm --entrypoint /bin/sh toolctrl-web:smoke -lc 'test -f /myapp/apps/web/build/server/index.js && test -d /myapp/apps/web/build/client && test -f /myapp/build/server-runtime/server.js'
|
|
|
|
- name: Validate web Docker runtime
|
|
run: bash scripts/docker-web-runtime-smoke.sh toolctrl-web:smoke
|
|
|
|
- name: Build API Docker target
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: .
|
|
target: api
|
|
build-args: APP_REVISION=ci-smoke-revision
|
|
tags: toolctrl-api:smoke
|
|
load: true
|
|
push: false
|
|
cache-from: type=gha,scope=toolctrl-api-smoke
|
|
cache-to: type=gha,mode=max,scope=toolctrl-api-smoke
|
|
|
|
- name: Validate API Docker runtime
|
|
run: bash scripts/docker-api-runtime-smoke.sh toolctrl-api:smoke
|
|
|
|
- name: Build worker Docker target
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: .
|
|
target: worker
|
|
build-args: APP_REVISION=ci-smoke-revision
|
|
tags: toolctrl-worker:smoke
|
|
load: true
|
|
push: false
|
|
cache-from: type=gha,scope=toolctrl-worker-smoke
|
|
cache-to: type=gha,mode=max,scope=toolctrl-worker-smoke
|
|
|
|
- name: Validate worker Docker runtime
|
|
run: bash scripts/docker-worker-runtime-smoke.sh toolctrl-worker:smoke
|
|
|
|
- name: Validate Docker Compose config
|
|
run: docker compose config
|
|
|
|
resolve-sentry-environment:
|
|
name: Resolve Sentry environment
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
needs: docker-smoke
|
|
outputs:
|
|
environment: ${{ steps.resolve.outputs.environment }}
|
|
steps:
|
|
- name: Resolve target environment from ref
|
|
id: resolve
|
|
run: |
|
|
REF="${GITHUB_REF:-}"
|
|
if [ "$REF" = "refs/heads/main" ]; then
|
|
echo "environment=production" >> "$GITHUB_OUTPUT"
|
|
elif [ "$REF" = "refs/heads/staging" ]; then
|
|
echo "environment=staging" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "environment=preview" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
sentry-release-api:
|
|
name: Sentry release (api)
|
|
needs: resolve-sentry-environment
|
|
uses: ./.github/workflows/_sentry-release.yml
|
|
with:
|
|
project: boilerplate-api
|
|
environment: ${{ needs.resolve-sentry-environment.outputs.environment }}
|
|
sourcemaps-path: none
|
|
secrets:
|
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
SENTRY_URL: ${{ secrets.SENTRY_URL }}
|
|
|
|
sentry-release-worker:
|
|
name: Sentry release (worker)
|
|
needs: resolve-sentry-environment
|
|
uses: ./.github/workflows/_sentry-release.yml
|
|
with:
|
|
project: boilerplate-worker
|
|
environment: ${{ needs.resolve-sentry-environment.outputs.environment }}
|
|
sourcemaps-path: none
|
|
secrets:
|
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
SENTRY_URL: ${{ secrets.SENTRY_URL }}
|
|
|
|
sentry-release-web:
|
|
name: Sentry release (web)
|
|
needs: resolve-sentry-environment
|
|
uses: ./.github/workflows/_sentry-release.yml
|
|
with:
|
|
project: boilerplate-web
|
|
environment: ${{ needs.resolve-sentry-environment.outputs.environment }}
|
|
sourcemaps-path: apps/web/build/client
|
|
sourcemaps-artifact: web-client-sourcemaps
|
|
secrets:
|
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
SENTRY_URL: ${{ secrets.SENTRY_URL }}
|