deps(actions): bump codecov/codecov-action from 5 to 6 #736
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: Stack Tests | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ['v*'] | |
| paths: | |
| - 'backend/**' | |
| - 'frontend/**' | |
| - 'cert-generator/**' | |
| - 'docker-compose.yaml' | |
| - 'deploy.sh' | |
| - '.github/workflows/stack-tests.yml' | |
| - '.github/actions/**' | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - 'backend/**' | |
| - 'frontend/**' | |
| - 'cert-generator/**' | |
| - 'docker-compose.yaml' | |
| - 'deploy.sh' | |
| - '.github/workflows/stack-tests.yml' | |
| - '.github/actions/**' | |
| workflow_dispatch: | |
| env: | |
| REGISTRY: ghcr.io | |
| MONGO_IMAGE: mongo:8.0 | |
| REDIS_IMAGE: redis:7-alpine | |
| KAFKA_IMAGE: confluentinc/cp-kafka:7.8.2 | |
| K3S_VERSION: v1.32.11+k3s1 | |
| K3S_INSTALL_SHA256: d75e014f2d2ab5d30a318efa5c326f3b0b7596f194afcff90fa7a7a91166d5f7 | |
| KUEUE_VERSION: v0.16.1 | |
| KUEUE_MANIFEST_SHA256: 3201a66ff731be440ecfcf3c0fa5979d001b834f68389208fe7ee18017fbcfe8 | |
| jobs: | |
| # Fast unit tests (no infrastructure needed) | |
| backend-unit: | |
| name: Backend Unit Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "backend/uv.lock" | |
| - name: Install Python dependencies | |
| run: | | |
| cd backend | |
| uv python install 3.12 | |
| uv sync --frozen --group test --no-dev | |
| - name: Run unit tests | |
| timeout-minutes: 5 | |
| run: | | |
| cd backend | |
| uv run --no-sync pytest tests/unit -v -rs \ | |
| --durations=0 \ | |
| --cov=app \ | |
| --cov-report=xml --cov-report=term | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v6 | |
| if: always() | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: backend/coverage.xml | |
| flags: backend-unit | |
| name: backend-unit-coverage | |
| fail_ci_if_error: false | |
| verbose: true | |
| frontend-unit: | |
| name: Frontend Unit Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Run unit tests with coverage | |
| working-directory: frontend | |
| run: npm run test:coverage | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v6 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: frontend/coverage/lcov.info | |
| flags: frontend-unit | |
| name: frontend-unit-coverage | |
| fail_ci_if_error: false | |
| verbose: true | |
| # Build all images, push to GHCR with immutable SHA tag. | |
| # Fork PRs skip GHCR push (no write access) — E2E tests require pushed images. | |
| build-images: | |
| name: Build & Push Images | |
| needs: [backend-unit, frontend-unit] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| sha-tag: ${{ steps.tags.outputs.sha-tag }} | |
| image-prefix: ${{ steps.tags.outputs.image-prefix }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| if: ${{ !github.event.pull_request.head.repo.fork }} | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compute image tags | |
| id: tags | |
| run: | | |
| PREFIX="${GITHUB_REPOSITORY_OWNER,,}/integr8scode" | |
| SHA_TAG="sha-${GITHUB_SHA::7}" | |
| echo "sha-tag=$SHA_TAG" >> "$GITHUB_OUTPUT" | |
| echo "image-prefix=$PREFIX" >> "$GITHUB_OUTPUT" | |
| # ── Base image (cached separately — rarely changes) ────────────── | |
| - name: Cache base image | |
| uses: actions/cache@v5 | |
| id: base-cache | |
| with: | |
| path: /tmp/base-image.tar.zst | |
| key: base-image-${{ runner.os }}-${{ hashFiles('backend/Dockerfile.base', 'backend/pyproject.toml', 'backend/uv.lock') }} | |
| - name: Load base image from cache | |
| if: steps.base-cache.outputs.cache-hit == 'true' | |
| run: zstd -d -c /tmp/base-image.tar.zst | docker load | |
| - name: Build base image | |
| if: steps.base-cache.outputs.cache-hit != 'true' | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./backend | |
| file: ./backend/Dockerfile.base | |
| load: true | |
| tags: integr8scode-base:latest | |
| cache-from: type=gha,scope=backend-base | |
| cache-to: type=gha,mode=max,scope=backend-base | |
| - name: Save base image to cache | |
| if: steps.base-cache.outputs.cache-hit != 'true' | |
| run: docker save integr8scode-base:latest | zstd -T0 -3 > /tmp/base-image.tar.zst | |
| # ── Backend (depends on local base image) ─────────────── | |
| - name: Build backend image | |
| run: | | |
| docker build -t integr8scode-backend:latest \ | |
| --build-context base=docker-image://integr8scode-base:latest \ | |
| -f ./backend/Dockerfile ./backend | |
| # ── Utility images (GHA-cached, independent of base) ──────────── | |
| - name: Build cert-generator image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./cert-generator | |
| file: ./cert-generator/Dockerfile | |
| load: true | |
| tags: integr8scode-cert-generator:latest | |
| cache-from: type=gha,scope=cert-generator | |
| cache-to: type=gha,mode=max,scope=cert-generator | |
| # ── Frontend (nginx + SSL) ───────────────────────────────────── | |
| - name: Build frontend image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./frontend | |
| file: ./frontend/Dockerfile | |
| load: true | |
| tags: integr8scode-frontend:latest | |
| cache-from: type=gha,scope=frontend | |
| cache-to: type=gha,mode=max,scope=frontend | |
| # ── Push all images to GHCR in parallel ──────────────────────── | |
| - name: Push all images to GHCR | |
| if: ${{ !github.event.pull_request.head.repo.fork }} | |
| env: | |
| TAG: ${{ steps.tags.outputs.sha-tag }} | |
| IMG: ${{ env.REGISTRY }}/${{ steps.tags.outputs.image-prefix }} | |
| run: | | |
| # Tag all images for GHCR | |
| docker tag integr8scode-base:latest "$IMG/base:$TAG" | |
| docker tag integr8scode-backend:latest "$IMG/backend:$TAG" | |
| docker tag integr8scode-cert-generator:latest "$IMG/cert-generator:$TAG" | |
| docker tag integr8scode-frontend:latest "$IMG/frontend:$TAG" | |
| # Push all 4 images in parallel, tracking each PID | |
| declare -A PIDS | |
| for name in base backend cert-generator frontend; do | |
| docker push "$IMG/$name:$TAG" & | |
| PIDS[$name]=$! | |
| done | |
| FAILED=0 | |
| for name in "${!PIDS[@]}"; do | |
| if ! wait "${PIDS[$name]}"; then | |
| echo "::error::Failed to push $name" | |
| FAILED=1 | |
| fi | |
| done | |
| [ "$FAILED" -eq 0 ] || exit 1 | |
| # Parallel E2E test jobs — compose pulls from GHCR using IMAGE_TAG | |
| backend-e2e: | |
| name: Backend E2E Tests | |
| needs: [build-images] | |
| if: ${{ !github.event.pull_request.head.repo.fork }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: read | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Boot E2E environment | |
| uses: ./.github/actions/e2e-boot | |
| with: | |
| image-tag: ${{ needs.build-images.outputs.sha-tag }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Finalize k3s & start stack | |
| uses: ./.github/actions/e2e-ready | |
| with: | |
| image-tag: ${{ needs.build-images.outputs.sha-tag }} | |
| - name: Run E2E tests | |
| timeout-minutes: 15 | |
| run: | | |
| docker compose exec -T backend \ | |
| sh -c 'uv sync --group test --no-dev --frozen --no-install-project && pytest tests/e2e -v -rs \ | |
| --durations=0 \ | |
| --cov=app \ | |
| --cov-report=xml:coverage-e2e.xml \ | |
| --cov-report=term' | |
| - name: Copy coverage | |
| if: always() | |
| run: docker compose cp backend:/app/coverage-e2e.xml backend/coverage-e2e.xml || true | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v6 | |
| if: always() | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: backend/coverage-e2e.xml | |
| flags: backend-e2e | |
| name: backend-e2e-coverage | |
| fail_ci_if_error: false | |
| - name: Collect logs on failure | |
| if: failure() | |
| run: | | |
| mkdir -p logs | |
| docker compose logs --timestamps > logs/docker-compose.log 2>&1 | |
| for svc in backend mongo redis kafka \ | |
| k8s-worker pod-monitor result-processor \ | |
| saga-orchestrator event-replay dlq-processor; do | |
| docker compose logs --timestamps "$svc" > "logs/$svc.log" 2>&1 || true | |
| done | |
| kubectl get events --sort-by='.metadata.creationTimestamp' -A > logs/k8s-events.log 2>&1 || true | |
| - name: Upload logs | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: backend-e2e-logs | |
| path: logs/ | |
| frontend-e2e: | |
| name: Frontend E2E (${{ matrix.shardIndex }}/${{ matrix.shardTotal }}) | |
| needs: [build-images] | |
| if: ${{ !github.event.pull_request.head.repo.fork }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shardIndex: [1, 2] | |
| shardTotal: [2] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| # Phase 1: kick off image pull + infra + k3s in background | |
| - name: Boot E2E environment | |
| uses: ./.github/actions/e2e-boot | |
| with: | |
| image-tag: ${{ needs.build-images.outputs.sha-tag }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| # Phase 2: Node + Playwright setup (overlaps with k3s boot + image pull) | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install frontend dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v5 | |
| id: playwright-cache | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ hashFiles('frontend/package-lock.json') }} | |
| - name: Install Playwright system dependencies | |
| working-directory: frontend | |
| run: npx playwright install-deps chromium | |
| - name: Install Playwright browsers | |
| if: steps.playwright-cache.outputs.cache-hit != 'true' | |
| working-directory: frontend | |
| run: npx playwright install chromium | |
| # Phase 3: finalize k3s + start stack (k3s has been booting since e2e-boot) | |
| - name: Finalize k3s & start stack | |
| uses: ./.github/actions/e2e-ready | |
| with: | |
| image-tag: ${{ needs.build-images.outputs.sha-tag }} | |
| wait-for-frontend: 'true' | |
| install-kueue: 'false' | |
| - name: Run Playwright tests | |
| timeout-minutes: 10 | |
| working-directory: frontend | |
| run: CI=true npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} | |
| - name: Upload Playwright report | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: playwright-report-${{ matrix.shardIndex }} | |
| path: frontend/playwright-report/ | |
| - name: Collect logs on failure | |
| if: failure() | |
| run: | | |
| mkdir -p logs | |
| docker compose logs --timestamps > logs/docker-compose.log 2>&1 | |
| for svc in backend frontend; do | |
| docker compose logs --timestamps "$svc" > "logs/$svc.log" 2>&1 || true | |
| done | |
| - name: Upload logs | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: frontend-e2e-logs-${{ matrix.shardIndex }} | |
| path: logs/ |