-
Notifications
You must be signed in to change notification settings - Fork 4
151 lines (132 loc) · 4.87 KB
/
Copy pathapps-api-ci.yml
File metadata and controls
151 lines (132 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
name: CI
on:
push:
branches: [main]
paths:
- "apps/api/**"
- ".github/workflows/apps-api-ci.yml"
pull_request:
branches: [main]
# Cancel in-flight runs of the same ref on a new push.
concurrency:
group: apps-api-ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
validate:
name: typecheck + lint + test
defaults:
run:
working-directory: apps/api
runs-on: ubuntu-24.04
timeout-minutes: 10
services:
# Mirrors `docker-compose.yml` so the integration tests under
# tests/api/** can hit a real Postgres rather than skipping. The
# password matches `.env.example` for parity with local dev.
postgres:
image: postgres:17-alpine@sha256:979c4379dd698aba0b890599a6104e082035f98ef31d9b9291ec22f2b13059ca
env:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: app_dev_password
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U app -d app"
--health-interval 5s
--health-timeout 5s
--health-retries 10
valkey:
image: valkey/valkey:8-alpine@sha256:77643d152547b446fc15cbafaff22004545663fcd40c6b28038ad283837baa75
ports:
- 6379:6379
options: >-
--health-cmd "valkey-cli ping"
--health-interval 5s
--health-timeout 5s
--health-retries 10
env:
# Same values used by the test runtime locally. JWT_SECRET is the
# 32+ char placeholder env.ts already accepts in test mode; never
# commit a real secret here.
NODE_ENV: test
DATABASE_URL: postgresql://app:app_dev_password@localhost:5432/app
JWT_SECRET: ci-only-jwt-secret-padded-to-thirty-two-chars
FRONTEND_URL: http://localhost:7331
ALLOWED_ORIGINS: http://localhost:7331
APP_NAME: API Template
LOG_LEVEL: error
# Use `resend` without a key so `buildEmailService()` picks
# `NoopEmailService` (see email.service.utils). A non-empty fake key
# would construct `ResendEmailService` and call the real API, which
# fails and breaks notification email-channel tests that expect `sent`.
EMAIL_PROVIDER: resend
RESEND_API_KEY: ""
EMAIL_FROM: noreply@example.com
VALKEY_HOST: localhost
VALKEY_PORT: "6379"
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Detect relevant changes
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
code:
- 'apps/api/**'
- '.github/workflows/apps-api-ci.yml'
- name: Set up Bun
if: steps.filter.outputs.code == 'true'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: 1.3.14
- name: Cache bun install
if: steps.filter.outputs.code == 'true'
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('apps/api/bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
if: steps.filter.outputs.code == 'true'
run: bun install --frozen-lockfile
- name: Apply DB migrations
if: steps.filter.outputs.code == 'true'
# `db:migrate` applies the committed migrations in drizzle/ —
# non-interactive, deterministic, and creates every schema
# (auth / billing / app / audit) the test suite expects.
# `db:push` is dev-only and prompts on a TTY, which CI doesn't have.
run: bun run db:migrate
- name: Build email templates
if: steps.filter.outputs.code == 'true'
run: bun run build:templates
- name: Typecheck + lint
if: steps.filter.outputs.code == 'true'
run: bun run check
- name: Tests
if: steps.filter.outputs.code == 'true'
env:
REQUIRE_INTEGRATION_DB: "true"
run: bun run test
- name: Test coverage report
if: steps.filter.outputs.code == 'true'
env:
REQUIRE_INTEGRATION_DB: "true"
run: bun run test:coverage
- name: Upload coverage to Codecov
if: steps.filter.outputs.code == 'true'
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
files: apps/api/coverage/lcov.info
flags: api
name: api-coverage
fail_ci_if_error: false
# CODECOV_TOKEN is required for private repos; for public repos
# uploads work tokenless.
token: ${{ secrets.CODECOV_TOKEN }}
- name: Production bundle
if: steps.filter.outputs.code == 'true'
run: bun build src/index.ts --outdir dist --target bun