Files
web_sport/.github/workflows/ci.yml
T

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