.github/workflows/ci.yml
此代码来自构建时的仓库快照。修改源码后重新构建即可更新。
name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
quality:
name: 代码检查、测试与构建
runs-on: ubuntu-latest
timeout-minutes: 20
services:
postgres:
image: postgres:17-alpine
env:
POSTGRES_USER: teamdesk
POSTGRES_PASSWORD: ci-only-password
POSTGRES_DB: teamdesk_test
ports: ['5432:5432']
options: >-
--health-cmd "pg_isready -U teamdesk -d teamdesk_test"
--health-interval 5s --health-timeout 3s --health-retries 20
redis:
image: redis:7-alpine
ports: ['6379:6379']
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s --health-timeout 3s --health-retries 20
env:
HUSKY: '0'
NEXT_TELEMETRY_DISABLED: '1'
DATABASE_URL: postgresql://teamdesk:ci-only-password@localhost:5432/teamdesk_test
TEST_DATABASE_URL: postgresql://teamdesk:ci-only-password@localhost:5432/teamdesk_test
TEST_REDIS_URL: redis://localhost:6379
BETTER_AUTH_URL: http://localhost:3000
BETTER_AUTH_SECRET: ci-only-not-a-production-secret-at-least-32-characters
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- uses: pnpm/action-setup@f520eceda224fe1a4aed5a2a27a194379a409996 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: '24'
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm format:check
- run: pnpm lint
- run: pnpm typecheck
# 推送校验本轮提交;PR 校验分支提交,不能只依赖可跳过的本地 hook。
- name: 校验 PR 提交信息
if: github.event_name == 'pull_request'
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: pnpm exec commitlint --from "$BASE_SHA" --to "$HEAD_SHA" --verbose
- name: 校验最新提交信息
if: github.event_name != 'pull_request'
run: git log -1 --pretty=%B | pnpm exec commitlint
- run: pnpm db:migrate
# 一个命令覆盖单元与真实数据库/Redis 测试,避免重复跑集成测试。
- run: pnpm test
- run: pnpm build
containers:
name: 部署镜像构建与验收
runs-on: ubuntu-latest
needs: quality
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
with:
node-version: '24'
- name: 生成一次性验收配置
run: |
cp .env.deploy.example .env.deploy
sed -i "s/^POSTGRES_PASSWORD=$/POSTGRES_PASSWORD=$(openssl rand -hex 24)/; s/^REDIS_PASSWORD=$/REDIS_PASSWORD=$(openssl rand -hex 24)/; s/^BETTER_AUTH_SECRET=$/BETTER_AUTH_SECRET=$(openssl rand -hex 32)/" .env.deploy
- name: 构建并启动独立部署
run: docker compose --env-file .env.deploy -f compose.deploy.yaml up --build --wait --wait-timeout 240
- name: 验证 Web 就绪
run: curl --fail --retry 5 --retry-delay 2 http://localhost:3100/api/health
- name: 验证 Worker 心跳
run: docker compose --env-file .env.deploy -f compose.deploy.yaml exec -T worker node --import tsx scripts/worker-health.ts
- name: 验证生产镜像业务链路
env:
SMOKE_ALLOW_CREATE: '1'
SMOKE_BASE_URL: http://localhost:3100
run: node scripts/deployment-smoke.mjs
- name: 输出失败任务日志
if: failure()
run: docker compose --env-file .env.deploy -f compose.deploy.yaml logs --tail 100 worker migrate
- name: 清理验收容器
if: always()
run: docker compose --env-file .env.deploy -f compose.deploy.yaml down --volumes