# GitHub Actions 工作流示例(放到 .github/workflows/ci.yml)。 # Gitea Actions 的语法与之基本兼容;GitLab CI 语法不同,思路一样。具体字段以所用平台的官方文档为准。 # 仓库结构假设:api/(Go)、ai/(Python)、web/(前端) name: ci on: push: branches: [main] pull_request: concurrency: # 同一分支新的提交会取消旧的运行 group: ci-${{ github.ref }} cancel-in-progress: true jobs: changes: # 只构建改动过的部分 runs-on: ubuntu-latest outputs: api: ${{ steps.filter.outputs.api }} ai: ${{ steps.filter.outputs.ai }} web: ${{ steps.filter.outputs.web }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 id: filter with: filters: | api: ['api/**'] ai: ['ai/**'] web: ['web/**'] api: needs: changes if: needs.changes.outputs.api == 'true' runs-on: ubuntu-latest services: postgres: # 集成测试用的数据库 image: postgres:17 env: POSTGRES_USER: test POSTGRES_PASSWORD: test POSTGRES_DB: test ports: ['5432:5432'] options: >- --health-cmd "pg_isready -U test" --health-interval 5s --health-retries 10 defaults: run: working-directory: api steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: api/go.mod - run: go vet ./... - run: go test -race -count=1 ./... env: TEST_DATABASE_URL: postgres://test:test@localhost:5432/test?sslmode=disable ai: needs: changes if: needs.changes.outputs.ai == 'true' runs-on: ubuntu-latest defaults: run: working-directory: ai steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' cache: pip - run: pip install -r requirements.txt -r requirements-dev.txt - run: ruff check . - run: pytest -q # 单元测试里用假的模型客户端,不调用真实模型 API web: needs: changes if: needs.changes.outputs.web == 'true' runs-on: ubuntu-latest defaults: run: working-directory: web steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: npm cache-dependency-path: web/package-lock.json - run: npm ci - run: npm run lint - run: npm run test -- --run - run: npm run build image: # 只在 main 分支、测试全部通过后构建并推送镜像 needs: [api, ai, web] # 依赖的任务被跳过时(没改动),默认会连带跳过本任务,所以要显式写 always() 再判断结果 if: >- always() && github.ref == 'refs/heads/main' && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # 密钥来自平台,不写进仓库 - name: build and push run: | tag=${GITHUB_SHA::12} # 用提交哈希做标签,可追溯、可回滚 docker build -t ghcr.io/${{ github.repository }}/api:$tag api docker push ghcr.io/${{ github.repository }}/api:$tag