#!/usr/bin/env bash # ci.yml › frontend and deploy.yml › frontend — build (or reuse) image erp-web:. # # `npm ci` + `next build` run in a capped node container; the image itself is runtime-only # (Frontend/erp-system/Dockerfile). The PR check builds the same tag with WITH_CHECKS=true # (type-check + lint first), so the deploy after a merge normally just reuses that image. # shellcheck source=common.sh source "$(dirname "${BASH_SOURCE[0]}")/common.sh" : "${FRONTEND_HASH:?FRONTEND_HASH is required}" image="$WEB_IMAGE_REPO:$FRONTEND_HASH" with_checks="${WITH_CHECKS:-false}" app="$PWD/$FRONTEND_PATH" checks="npx tsc --noEmit && npx eslint ." image_exists() { docker image inspect "$image" >/dev/null 2>&1; } image_checked() { [[ "$(docker image inspect -f '{{ index .Config.Labels "erp.checked" }}' "$image" 2>/dev/null)" == true ]]; } # run_node — run steps in the frontend folder inside a capped node container. run_node() { local z z="$(selinux_mount_suffix)" docker run --rm --cpus=2 --cpu-shares=512 --memory=2500m \ -e CI=true -e NEXT_TELEMETRY_DISABLED=1 -e NODE_OPTIONS=--max-old-space-size=2048 \ -v "$app:/app$z" \ -v erp-npm-cache:/root/.npm \ -v erp-next-cache:/app/.next/cache \ -w /app "$NODE_IMAGE" sh -ec "$1" } with_build_lock if image_exists; then if [[ "$with_checks" == true ]] && ! image_checked; then # Same content was built earlier by a deploy (no checks) — the PR still has to pass them. log "$image exists but was built without checks → running type-check + lint only" run_node "npm ci --no-audit --no-fund && $checks" fi log "$image already built → reused" set_output reused true exit 0 fi [[ "$(tree_hash "$FRONTEND_PATH")" == "$FRONTEND_HASH" ]] || fail "no image for $FRONTEND_HASH, and this checkout's $FRONTEND_PATH is a different tree (pruned rollback target?)" steps="npm ci --no-audit --no-fund" if [[ "$with_checks" == true ]]; then steps="$steps && $checks"; fi steps="$steps && npm run build" log "building frontend $FRONTEND_HASH (checks=$with_checks, capped: 2 CPU / 2500 MB)" run_node "$steps" [[ -f "$app/.next/standalone/server.js" ]] || fail "next build did not produce .next/standalone/server.js (is output: \"standalone\" set in next.config.ts?)" docker build \ --label "erp.frontend-tree=$FRONTEND_HASH" \ --label "erp.source-sha=${GITHUB_SHA:-local}" \ --label "erp.checked=$with_checks" \ -t "$image" "$app" log "frontend image ready: $image" set_output reused false