From decd79d547208c5365bcb18e3dfe6b65cd26f250 Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 24 Mar 2026 21:23:59 +0100 Subject: [PATCH] ci: add Docker build validation workflow for PRs Validates Dockerfiles and builds 5 representative images in parallel on PRs. Catches missing COPY statements and build errors before deploy. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/docker-validate.yml | 123 ++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 .github/workflows/docker-validate.yml diff --git a/.github/workflows/docker-validate.yml b/.github/workflows/docker-validate.yml new file mode 100644 index 000000000..97dbf3ab8 --- /dev/null +++ b/.github/workflows/docker-validate.yml @@ -0,0 +1,123 @@ +# Docker Validation: Validates Dockerfiles and builds representative images on PRs +# +# Flow: +# PR → main : Validates Dockerfiles + builds representative Docker images +# Push → main : Same validation (catches force-merges) +# +# The build job tests a representative subset of images that covers +# all shared packages without building all 40+ services. + +name: Docker Validate + +on: + push: + branches: + - main + paths: + - '**/Dockerfile' + - '**/package.json' + - 'packages/**' + - 'apps/**' + - 'services/**' + - 'pnpm-lock.yaml' + - 'pnpm-workspace.yaml' + - '.github/workflows/docker-validate.yml' + pull_request: + branches: + - main + paths: + - '**/Dockerfile' + - '**/package.json' + - 'packages/**' + - 'apps/**' + - 'services/**' + - 'pnpm-lock.yaml' + - 'pnpm-workspace.yaml' + - '.github/workflows/docker-validate.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: '20' + PNPM_VERSION: '9.15.0' + +jobs: + # =========================================== + # Job 1: Validate Dockerfiles (fast, no Docker needed) + # =========================================== + validate-dockerfiles: + name: Validate Dockerfiles + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + 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: Validate Dockerfiles + run: pnpm validate:dockerfiles + + # =========================================== + # Job 2: Build representative Docker images + # =========================================== + # Builds a subset that covers all shared packages: + # - mana-core-auth: covers shared-storage, shared-nestjs-auth, shared-llm + # - todo-web: covers most shared-* web packages + # - zitare-web: covers content packages, shared-pwa + # - calendar-web: covers calendar shared packages + # - todo-backend: covers NestJS backend pattern + shared packages + # =========================================== + build-docker-images: + name: Build ${{ matrix.service }} + runs-on: ubuntu-latest + needs: validate-dockerfiles + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + include: + - service: mana-core-auth + dockerfile: services/mana-core-auth/Dockerfile + context: . + - service: todo-backend + dockerfile: apps/todo/apps/backend/Dockerfile + context: . + - service: todo-web + dockerfile: apps/todo/apps/web/Dockerfile + context: . + - service: zitare-web + dockerfile: apps/zitare/apps/web/Dockerfile + context: . + - service: calendar-web + dockerfile: apps/calendar/apps/web/Dockerfile + context: . + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build ${{ matrix.service }} + uses: docker/build-push-action@v5 + with: + context: ${{ matrix.context }} + file: ${{ matrix.dockerfile }} + push: false + cache-from: type=gha,scope=${{ matrix.service }} + cache-to: type=gha,scope=${{ matrix.service }},mode=max