feat(export): implement CSV export for task data #5520
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| types: [opened, synchronize, reopened] | |
| # Cancel outdated runs on the same PR/branch to save CI minutes. | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| typecheck: | |
| name: Type check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| with: | |
| version: 11 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Run tsc | |
| run: pnpm run type-check | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| with: | |
| version: 11 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Run ESLint | |
| run: pnpm run lint | |
| test-coverage: | |
| name: Test coverage | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| with: | |
| version: 11 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Run Vitest with coverage | |
| id: coverage | |
| continue-on-error: true | |
| run: pnpm run test:coverage | |
| - name: Warn when coverage is below soft threshold | |
| run: | | |
| node -e "const fs = require('fs'); const threshold = 60; const file = 'coverage/coverage-summary.json'; if (!fs.existsSync(file)) { console.log('::warning title=Coverage report unavailable::Vitest did not produce a coverage summary. This warning does not fail CI.'); process.exit(0); } const summary = JSON.parse(fs.readFileSync(file, 'utf8')); const pct = summary.total.lines.pct; if (pct < threshold) { console.log('::warning title=Coverage below soft threshold::Line coverage is ' + pct + '%, below the soft target of ' + threshold + '%. This warning does not fail CI.'); } else { console.log('Line coverage is ' + pct + '%, meeting the soft target of ' + threshold + '%.'); }" | |
| - name: Upload coverage to Codecov | |
| if: hashFiles('coverage/lcov.info') != '' | |
| uses: codecov/codecov-action@v7 | |
| with: | |
| files: ./coverage/lcov.info | |
| flags: unit | |
| name: devtrack-vitest | |
| fail_ci_if_error: false | |
| use_oidc: true | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| env: | |
| # Dummy values: API routes are force-dynamic and only run at request time. | |
| NEXTAUTH_SECRET: ci-placeholder-secret-that-is-long-enough-32c | |
| NEXTAUTH_URL: http://localhost:3000 | |
| GITHUB_ID: ci-placeholder | |
| GITHUB_SECRET: ci-placeholder | |
| NEXT_PUBLIC_SUPABASE_URL: https://placeholder.supabase.co | |
| NEXT_PUBLIC_SUPABASE_ANON_KEY: placeholder-anon-key | |
| SUPABASE_SERVICE_ROLE_KEY: placeholder-service-key | |
| NEXT_PUBLIC_APP_URL: http://localhost:3000 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| with: | |
| version: 11 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build Next.js app | |
| run: pnpm run build | |
| dep-check: | |
| name: Dependency audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: pnpm/action-setup@v6 | |
| with: | |
| version: 11 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Check all imports exist in package.json | |
| run: node scripts/check-deps.js | |
| env-security: | |
| name: Environment security check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Check SERVICE_ROLE_KEY exposure | |
| run: bash scripts/check-env-security.sh | |
| ci-pass: | |
| name: CI passed | |
| runs-on: ubuntu-latest | |
| needs: [typecheck, lint, build, dep-check, env-security] | |
| if: always() | |
| steps: | |
| - name: Check all jobs passed | |
| run: | | |
| if [[ "${{ needs.typecheck.result }}" != "success" || | |
| "${{ needs.lint.result }}" != "success" || | |
| "${{ needs.build.result }}" != "success" || | |
| "${{ needs.dep-check.result }}" != "success" || | |
| "${{ needs.env-security.result }}" != "success" ]]; then | |
| echo "One or more CI jobs failed." | |
| exit 1 | |
| fi | |
| echo "All CI jobs passed." |