#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)" IMAGE_PREFIX="${IMAGE_PREFIX:-juwan}" IMAGE_TAG="${1:-dev}" cd "$ROOT_DIR" bakefile=$(mktemp "${TMPDIR:-/tmp}/juwan-bake-XXXXXX") mv "$bakefile" "${bakefile}.json" bakefile="${bakefile}.json" python3 - "$IMAGE_PREFIX" "$IMAGE_TAG" "$bakefile" <<'PYEOF' import json, os, subprocess, sys, glob prefix, tag, outpath = sys.argv[1], sys.argv[2], sys.argv[3] dockerfile_tpl = """\ # syntax=docker/dockerfile:1.7 FROM golang:1.25-alpine AS builder RUN apk add --no-cache tzdata WORKDIR /build COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod go mod download COPY . . RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ go build -ldflags="-s -w" -o /app/main ./{service_dir} FROM alpine:latest COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai ENV TZ=Asia/Shanghai WORKDIR /app COPY --from=builder /app/main /app/main COPY {service_dir}/etc /app/etc CMD ["./main", "-f", "etc/{config_name}"] """ dockerfile_no_config_tpl = """\ # syntax=docker/dockerfile:1.7 FROM golang:1.25-alpine AS builder RUN apk add --no-cache tzdata WORKDIR /build COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod go mod download COPY . . RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ go build -ldflags="-s -w" -o /app/main ./{service_dir} FROM alpine:latest COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai ENV TZ=Asia/Shanghai WORKDIR /app COPY --from=builder /app/main /app/main CMD ["./main"] """ targets = {} for service_dir in sorted(glob.glob("app/*/*")): service_dir = service_dir.replace("\\", "/") service_type = os.path.basename(service_dir) if service_type not in ("api", "rpc", "mq", "adapter"): continue go_files = glob.glob(os.path.join(service_dir, "*.go")) has_main = any("package main" in open(f).read() for f in go_files) if go_files else False if not has_main: continue yamls = glob.glob(os.path.join(service_dir, "etc", "*.yaml")) service_name = os.path.basename(os.path.dirname(service_dir)) target_name = f"{service_name}-{service_type}" if yamls: config_name = os.path.basename(yamls[0]) dockerfile = dockerfile_tpl.format(service_dir=service_dir, config_name=config_name) else: dockerfile = dockerfile_no_config_tpl.format(service_dir=service_dir) targets[target_name] = { "dockerfile-inline": dockerfile, "tags": [f"{prefix}/{target_name}:{tag}"], } bake = { "group": {"default": {"targets": list(targets.keys())}}, "target": targets, } with open(outpath, "w") as f: json.dump(bake, f, indent=2) print(f"Generated {len(targets)} targets -> {outpath}") PYEOF docker buildx bake --load -f "$bakefile" rm -f "$bakefile"