Files
HiveGrid-Wireframes/hivegrid-cloud/.github/workflows/ci.yml
T

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 }}