$npx -y skills add sabahattink/antigravity-fullstack-hq --skill github-actionsCI/CD workflow patterns, testing pipelines, deployment automation. Use when setting up GitHub Actions workflows for testing, building, linting, or deploying a fullstack app.
| 1 | # GitHub Actions |
| 2 | |
| 3 | ## Full CI Pipeline |
| 4 | |
| 5 | ```yaml |
| 6 | # .github/workflows/ci.yml |
| 7 | name: CI |
| 8 | |
| 9 | on: |
| 10 | push: |
| 11 | branches: [main, develop] |
| 12 | pull_request: |
| 13 | branches: [main, develop] |
| 14 | |
| 15 | concurrency: |
| 16 | group: ${{ github.workflow }}-${{ github.ref }} |
| 17 | cancel-in-progress: true # Cancel stale runs on new push |
| 18 | |
| 19 | jobs: |
| 20 | # ─── Lint & Type Check ───────────────────────────────────── |
| 21 | lint: |
| 22 | name: Lint & Type Check |
| 23 | runs-on: ubuntu-latest |
| 24 | steps: |
| 25 | - uses: actions/checkout@v4 |
| 26 | |
| 27 | - uses: pnpm/action-setup@v4 |
| 28 | with: { version: 9 } |
| 29 | |
| 30 | - uses: actions/setup-node@v4 |
| 31 | with: |
| 32 | node-version: 22 |
| 33 | cache: pnpm |
| 34 | |
| 35 | - run: pnpm install --frozen-lockfile |
| 36 | |
| 37 | - name: Type check (API) |
| 38 | run: pnpm --filter api run type-check |
| 39 | |
| 40 | - name: Type check (Web) |
| 41 | run: pnpm --filter web run type-check |
| 42 | |
| 43 | - name: Lint |
| 44 | run: pnpm run lint |
| 45 | |
| 46 | # ─── Unit Tests ──────────────────────────────────────────── |
| 47 | test-unit: |
| 48 | name: Unit Tests |
| 49 | runs-on: ubuntu-latest |
| 50 | needs: lint |
| 51 | steps: |
| 52 | - uses: actions/checkout@v4 |
| 53 | |
| 54 | - uses: pnpm/action-setup@v4 |
| 55 | with: { version: 9 } |
| 56 | |
| 57 | - uses: actions/setup-node@v4 |
| 58 | with: |
| 59 | node-version: 22 |
| 60 | cache: pnpm |
| 61 | |
| 62 | - run: pnpm install --frozen-lockfile |
| 63 | |
| 64 | - name: Run unit tests |
| 65 | run: pnpm --filter api run test:cov |
| 66 | |
| 67 | - name: Upload coverage |
| 68 | uses: codecov/codecov-action@v4 |
| 69 | with: |
| 70 | token: ${{ secrets.CODECOV_TOKEN }} |
| 71 | files: ./apps/api/coverage/lcov.info |
| 72 | |
| 73 | # ─── Integration Tests ───────────────────────────────────── |
| 74 | test-integration: |
| 75 | name: Integration Tests |
| 76 | runs-on: ubuntu-latest |
| 77 | needs: lint |
| 78 | |
| 79 | services: |
| 80 | postgres: |
| 81 | image: postgres:16-alpine |
| 82 | env: |
| 83 | POSTGRES_DB: test_db |
| 84 | POSTGRES_USER: postgres |
| 85 | POSTGRES_PASSWORD: postgres |
| 86 | ports: ["5432:5432"] |
| 87 | options: >- |
| 88 | --health-cmd pg_isready |
| 89 | --health-interval 5s |
| 90 | --health-timeout 5s |
| 91 | --health-retries 5 |
| 92 | |
| 93 | redis: |
| 94 | image: redis:7-alpine |
| 95 | ports: ["6379:6379"] |
| 96 | options: >- |
| 97 | --health-cmd "redis-cli ping" |
| 98 | --health-interval 5s |
| 99 | --health-retries 5 |
| 100 | |
| 101 | steps: |
| 102 | - uses: actions/checkout@v4 |
| 103 | |
| 104 | - uses: pnpm/action-setup@v4 |
| 105 | with: { version: 9 } |
| 106 | |
| 107 | - uses: actions/setup-node@v4 |
| 108 | with: { node-version: 22, cache: pnpm } |
| 109 | |
| 110 | - run: pnpm install --frozen-lockfile |
| 111 | |
| 112 | - name: Run migrations |
| 113 | run: pnpm --filter api run migration:run |
| 114 | env: |
| 115 | DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db |
| 116 | |
| 117 | - name: Run integration tests |
| 118 | run: pnpm --filter api run test:integration |
| 119 | env: |
| 120 | DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db |
| 121 | REDIS_URL: redis://localhost:6379 |
| 122 | JWT_SECRET: test-secret-32-chars-minimum-length |
| 123 | |
| 124 | # ─── E2E Tests ───────────────────────────────────────────── |
| 125 | test-e2e: |
| 126 | name: E2E Tests (Playwright) |
| 127 | runs-on: ubuntu-latest |
| 128 | needs: [test-unit, test-integration] |
| 129 | timeout-minutes: 20 |
| 130 | |
| 131 | services: |
| 132 | postgres: |
| 133 | image: postgres:16-alpine |
| 134 | env: { POSTGRES_DB: e2e_db, POSTGRES_USER: postgres, POSTGRES_PASSWORD: postgres } |
| 135 | ports: ["5432:5432"] |
| 136 | options: --health-cmd pg_isready --health-interval 5s --health-retries 5 |
| 137 | |
| 138 | steps: |
| 139 | - uses: actions/checkout@v4 |
| 140 | |
| 141 | - uses: pnpm/action-setup@v4 |
| 142 | with: { version: 9 } |
| 143 | |
| 144 | - uses: actions/setup-node@v4 |
| 145 | with: { node-version: 22, cache: pnpm } |
| 146 | |
| 147 | - run: pnpm install --frozen-lockfile |
| 148 | |
| 149 | - name: Cache Playwright browsers |
| 150 | uses: actions/cache@v4 |
| 151 | id: pw-cache |
| 152 | with: |
| 153 | path: ~/.cache/ms-playwright |
| 154 | key: playwright-${{ hashFiles('**/package.json') }} |
| 155 | |
| 156 | - name: Install Playwright browsers |
| 157 | if: steps.pw-cache.outputs.cache-hit != 'true' |
| 158 | run: pnpm exec playwright install --with-deps chromium |
| 159 | |
| 160 | - name: Build apps |
| 161 | env: |
| 162 | DATABASE_URL: postgresql://postgres:postgres@localhost:5432/e2e_db |
| 163 | run: pnpm run build |
| 164 | |
| 165 | - name: Run E2E tests |
| 166 | run: pnpm run test:e2e |
| 167 | env: |
| 168 | DATABASE_URL: postgresql://postgres:postgres@localhost:5432/e2e_db |
| 169 | PLAYWRIGHT_BASE_URL: http://localhost:3000 |
| 170 | |
| 171 | - name: Upload Playwright report |
| 172 | if: failure() |
| 173 | uses: actions/upload-artifact@v4 |
| 174 | with: |
| 175 | name: playwright-report |
| 176 | path: playwright-report/ |
| 177 | retention-days: 7 |
| 178 | ``` |
| 179 | |
| 180 | ## Deploy Workflow |
| 181 | |
| 182 | ```yaml |
| 183 | # .github/workflows/deploy.yml |
| 184 | name: Deploy |
| 185 | |
| 186 | on: |
| 187 | push: |
| 188 | branches: [main] |
| 189 | workflow_dispatch: |
| 190 | inputs: |
| 191 | environment: |
| 192 | description: Target envir |