diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a15b5a280..140264683 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,10 +9,36 @@ env: PNPM_VERSION: '10' jobs: - checks: + # ==================== 变更检测 ==================== + changes: runs-on: ubuntu-latest - timeout-minutes: 30 + outputs: + code: ${{ steps.filter.outputs.code }} + docs: ${{ steps.filter.outputs.docs }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + code: + - 'src/**' + - 'e2e/**' + - 'package.json' + - 'pnpm-lock.yaml' + - 'vite.config.ts' + - 'vitest.config.ts' + - 'playwright.config.ts' + - 'tsconfig*.json' + docs: + - 'docs/**' + - '*.md' + - '.github/**' + # ==================== 类型检查 ==================== + typecheck: + runs-on: ubuntu-latest + timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@v4 @@ -34,14 +60,120 @@ jobs: - name: Type check run: pnpm typecheck + # ==================== 单元测试 ==================== + test: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Unit tests run: pnpm test + # ==================== 构建检查 ==================== + build: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Build run: pnpm build + # ==================== E2E 测试(仅代码变更时运行) ==================== + e2e: + needs: changes + if: needs.changes.outputs.code == 'true' + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Cache Playwright browsers + id: playwright-cache + uses: actions/cache@v4 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} + - name: Install Playwright browsers + if: steps.playwright-cache.outputs.cache-hit != 'true' run: pnpm exec playwright install --with-deps chromium + - name: Install Playwright deps (if cached) + if: steps.playwright-cache.outputs.cache-hit == 'true' + run: pnpm exec playwright install-deps chromium + - name: E2E smoke (Mobile Chrome) run: pnpm e2e e2e/bioforest-chains.spec.ts --project "Mobile Chrome" + + # ==================== 最终状态检查 ==================== + checks: + runs-on: ubuntu-latest + needs: [typecheck, test, build, e2e] + if: always() + steps: + - name: Check results + run: | + if [[ "${{ needs.typecheck.result }}" == "failure" ]]; then + echo "Typecheck failed" + exit 1 + fi + if [[ "${{ needs.test.result }}" == "failure" ]]; then + echo "Tests failed" + exit 1 + fi + if [[ "${{ needs.build.result }}" == "failure" ]]; then + echo "Build failed" + exit 1 + fi + if [[ "${{ needs.e2e.result }}" == "failure" ]]; then + echo "E2E failed" + exit 1 + fi + echo "All checks passed!"