#!/usr/bin/env bash set -euo pipefail root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) cd "$root" tag=${IMAGE_TAG:-} registry=${AI_GATEWAY_IMAGE_REGISTRY:-registry.cn-shanghai.aliyuncs.com/easyaigc} builder=${AI_GATEWAY_BUILDX_BUILDER:-easyai-gateway-ci} cache_limit=${AI_GATEWAY_BUILDX_CACHE_LIMIT:-2gb} platform=${AI_GATEWAY_PLATFORM:-linux/amd64} keep_images=0 build_complete=0 case ${1:-} in '') ;; --keep-images) keep_images=1 ;; *) echo 'usage: ci-build-images.sh [--keep-images]' >&2 exit 64 ;; esac if [[ ! $tag =~ ^[0-9a-f]{40}$ ]]; then echo 'IMAGE_TAG must be a full lowercase Git SHA' >&2 exit 1 fi if [[ ! $registry =~ ^[A-Za-z0-9.-]+(:[0-9]+)?(/[A-Za-z0-9._/-]+)+$ ]]; then echo 'AI_GATEWAY_IMAGE_REGISTRY has an invalid format' >&2 exit 1 fi if [[ ! $cache_limit =~ ^[1-9][0-9]*(kb|mb|gb)$ ]]; then echo 'AI_GATEWAY_BUILDX_CACHE_LIMIT has an invalid format' >&2 exit 1 fi api_image="$registry/ai-gateway:$tag" web_image="$registry/ai-gateway-web:$tag" cleanup() { original_status=$? trap - EXIT HUP INT TERM cleanup_status=0 docker buildx prune --builder "$builder" --force --max-used-space "$cache_limit" >/dev/null || { cleanup_status=$? echo 'failed to prune the CI BuildKit cache' >&2 } if [[ $keep_images -ne 1 || $build_complete -ne 1 ]]; then docker image rm "$api_image" "$web_image" >/dev/null 2>&1 || { image_rm_status=$? [[ $cleanup_status -ne 0 ]] || cleanup_status=$image_rm_status echo 'failed to remove CI image tags' >&2 } fi if [[ $original_status -ne 0 ]]; then exit "$original_status" fi exit "$cleanup_status" } trap cleanup EXIT trap 'exit 129' HUP trap 'exit 130' INT trap 'exit 143' TERM if ! docker buildx inspect "$builder" >/dev/null 2>&1; then docker buildx create --name "$builder" --driver docker-container --use >/dev/null fi docker buildx inspect "$builder" --bootstrap >/dev/null common_args=( --builder "$builder" --platform "$platform" --file Dockerfile --pull --load ) docker buildx build --builder "$builder" \ "${common_args[@]:2}" \ --target api \ --build-arg "GO_BUILD_IMAGE=${AI_GATEWAY_GO_BUILD_IMAGE:-docker.m.daocloud.io/library/golang:1.26.5-alpine}" \ --build-arg "API_RUNTIME_IMAGE=${AI_GATEWAY_API_RUNTIME_IMAGE:-docker.m.daocloud.io/library/alpine:3.22}" \ --tag "$api_image" . docker buildx build --builder "$builder" \ "${common_args[@]:2}" \ --target web \ --build-arg "NODE_BUILD_IMAGE=${AI_GATEWAY_NODE_BUILD_IMAGE:-docker.m.daocloud.io/library/node:24-alpine}" \ --build-arg "WEB_RUNTIME_IMAGE=${AI_GATEWAY_WEB_RUNTIME_IMAGE:-docker.m.daocloud.io/library/nginx:1.27-alpine}" \ --tag "$web_image" . for image in "$api_image" "$web_image"; do trivy image --scanners vuln,secret --severity HIGH,CRITICAL --ignore-unfixed \ --exit-code 1 --timeout 15m "$image" done build_complete=1 printf 'gateway_images=PASS git_sha=%s api=%s web=%s\n' "$tag" "$api_image" "$web_image"