name: Build and Push Frontend # Migrated from .woodpecker/frontend.yml on 2026-05-18. GHA builds + pushes # to DockerHub; Keel polls :latest and rolls the realestate-crawler-ui # Deployment. The .env.production file carries VITE_MAPBOX_TOKEN at build # time (Vite reads it from the build context) — same shape as the # Woodpecker pipeline, just sourced from a GHA secret instead. on: push: branches: [master] paths: - 'frontend/**' - '.github/workflows/build-frontend.yml' concurrency: group: build-frontend-${{ github.ref }} cancel-in-progress: true env: IMAGE: viktorbarzin/immoweb jobs: test-and-build: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '24' cache: 'npm' cache-dependency-path: frontend/package-lock.json - name: Install deps working-directory: frontend run: npm ci # Vitest runs all 4 Woodpecker shards in one job — single GHA runner # is plenty fast and avoids matrix-cost x4. - name: Vitest working-directory: frontend run: npx vitest run --reporter=verbose # Writes .env.production for Vite's build-time read. Secret is piped # via env (not `${{ }}` directly in run:) so shell metacharacters in # the value, if any, can't break out. - name: Write .env.production for Vite build env: MAPBOX_TOKEN: ${{ secrets.MAPBOX_TOKEN }} run: printf 'VITE_MAPBOX_TOKEN=%s\n' "$MAPBOX_TOKEN" > frontend/.env.production - uses: docker/setup-buildx-action@v3 - uses: docker/login-action@v3 with: username: viktorbarzin password: ${{ secrets.DOCKERHUB_TOKEN }} - id: meta env: GIT_SHA: ${{ github.sha }} run: echo "sha=$(printf '%s' "$GIT_SHA" | cut -c1-8)" >> "$GITHUB_OUTPUT" - uses: docker/build-push-action@v6 with: context: frontend file: frontend/Dockerfile target: production platforms: linux/amd64 push: true tags: | ${{ env.IMAGE }}:${{ steps.meta.outputs.sha }} ${{ env.IMAGE }}:latest cache-from: type=gha,scope=frontend cache-to: type=gha,scope=frontend,mode=max