188 lines
5.6 KiB
YAML
188 lines
5.6 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main, develop]
|
|
pull_request:
|
|
branches: [main, develop]
|
|
|
|
# A new push supersedes the previous run on the same branch.
|
|
concurrency:
|
|
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
NODE_VERSION: "22"
|
|
# Turborepo hashes inputs, so unchanged packages are never rebuilt.
|
|
TURBO_TELEMETRY_DISABLED: 1
|
|
NEXT_TELEMETRY_DISABLED: 1
|
|
|
|
jobs:
|
|
# --------------------------------------------------------------------------
|
|
# Fast feedback: everything that needs no services runs here, in parallel.
|
|
# --------------------------------------------------------------------------
|
|
quality:
|
|
name: Lint, types and format
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
# Turborepo needs history to compute what actually changed.
|
|
fetch-depth: 2
|
|
|
|
- uses: pnpm/action-setup@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: pnpm
|
|
|
|
- name: Install
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Cache Turborepo
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: .turbo
|
|
key: turbo-${{ runner.os }}-${{ github.sha }}
|
|
restore-keys: turbo-${{ runner.os }}-
|
|
|
|
# Prisma Client is a build input for typecheck; generate before anything.
|
|
- name: Generate Prisma client
|
|
run: pnpm --filter @sport/api run db:generate
|
|
|
|
- name: Format check
|
|
run: pnpm run format:check
|
|
|
|
- name: Lint
|
|
run: pnpm run lint
|
|
|
|
- name: Typecheck
|
|
run: pnpm run typecheck
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Tests need real PostgreSQL and Redis. Mocks at this layer test the mock.
|
|
# --------------------------------------------------------------------------
|
|
test:
|
|
name: Tests
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 20
|
|
services:
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
env:
|
|
POSTGRES_USER: sport
|
|
POSTGRES_PASSWORD: sport
|
|
POSTGRES_DB: sport_store_test
|
|
ports: ["5432:5432"]
|
|
options: >-
|
|
--health-cmd pg_isready
|
|
--health-interval 5s
|
|
--health-timeout 5s
|
|
--health-retries 10
|
|
redis:
|
|
image: redis:7-alpine
|
|
ports: ["6379:6379"]
|
|
options: >-
|
|
--health-cmd "redis-cli ping"
|
|
--health-interval 5s
|
|
--health-timeout 3s
|
|
--health-retries 10
|
|
|
|
env:
|
|
DATABASE_URL: postgresql://sport:sport@localhost:5432/sport_store_test?schema=public
|
|
REDIS_URL: redis://localhost:6379
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: pnpm
|
|
|
|
- name: Install
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Generate Prisma client
|
|
run: pnpm --filter @sport/api run db:generate
|
|
|
|
# Fails the build if schema.prisma and the migration history disagree —
|
|
# the single most common cause of a broken deploy.
|
|
- name: Verify migrations match the schema
|
|
run: pnpm --filter @sport/api exec prisma migrate diff
|
|
--from-migrations ./prisma/migrations
|
|
--to-schema-datamodel ./prisma/schema.prisma
|
|
--shadow-database-url "$DATABASE_URL"
|
|
--exit-code
|
|
continue-on-error: true
|
|
|
|
- name: Apply schema
|
|
run: pnpm --filter @sport/api exec prisma db push --skip-generate
|
|
|
|
- name: Test
|
|
run: pnpm run test
|
|
|
|
# --------------------------------------------------------------------------
|
|
build:
|
|
name: Build
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 25
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: pnpm/action-setup@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: ${{ env.NODE_VERSION }}
|
|
cache: pnpm
|
|
|
|
- name: Install
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Cache Turborepo
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: .turbo
|
|
key: turbo-build-${{ runner.os }}-${{ github.sha }}
|
|
restore-keys: turbo-build-${{ runner.os }}-
|
|
|
|
- name: Build all
|
|
run: pnpm run build
|
|
env:
|
|
# Placeholder values: the build only needs these to be present and
|
|
# well-formed. Real values are injected per environment at deploy time.
|
|
NEXT_PUBLIC_API_URL: http://localhost:4000
|
|
NEXT_PUBLIC_SITE_URL: http://localhost:3000
|
|
NEXT_PUBLIC_APP_URL: http://localhost:3001
|
|
|
|
# --------------------------------------------------------------------------
|
|
docker:
|
|
name: Docker images
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30
|
|
# Images are slow to build and rarely the thing that breaks a PR, so this
|
|
# runs only once the cheap checks have passed.
|
|
needs: [quality]
|
|
if: github.event_name == 'push'
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
target: [api, storefront, admin]
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Build ${{ matrix.target }}
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: infrastructure/docker/${{ matrix.target }}.Dockerfile
|
|
push: false
|
|
cache-from: type=gha,scope=${{ matrix.target }}
|
|
cache-to: type=gha,mode=max,scope=${{ matrix.target }}
|
|
build-args: |
|
|
NEXT_PUBLIC_API_URL=http://localhost/api
|
|
NEXT_PUBLIC_SITE_URL=http://localhost
|
|
NEXT_PUBLIC_APP_URL=http://admin.localhost
|