Remove deleted foxhunt-deploy COPY from all Dockerfiles, update sccache default region to fr-par, add build-and-push.sh for building all service images and pushing to rg.fr-par.scw.cloud/foxhunt/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
264 lines
7.5 KiB
Bash
Executable File
264 lines
7.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# build-and-push.sh - Build and push service images to Scaleway registry
|
|
# ---------------------------------------------------------------------------
|
|
# Builds all Foxhunt service Docker images and pushes to the Scaleway
|
|
# Container Registry. Supports parallel builds, selective service builds,
|
|
# and sccache for faster compilation.
|
|
#
|
|
# Usage:
|
|
# ./infra/scripts/build-and-push.sh # Build & push all
|
|
# ./infra/scripts/build-and-push.sh --no-push # Build only
|
|
# ./infra/scripts/build-and-push.sh --services "api_gateway trading_service"
|
|
# ./infra/scripts/build-and-push.sh --parallel 3 # 3 concurrent builds
|
|
# ./infra/scripts/build-and-push.sh --dry-run # Show what would run
|
|
# ---------------------------------------------------------------------------
|
|
|
|
REGISTRY="rg.fr-par.scw.cloud"
|
|
NAMESPACE="foxhunt"
|
|
GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
|
TIMESTAMP=$(date -u +"%Y%m%d-%H%M%S")
|
|
|
|
# Services built with Dockerfile.service (--build-arg SERVICE=<name>)
|
|
STANDARD_SERVICES=(
|
|
api_gateway
|
|
trading_service
|
|
trading_agent_service
|
|
ml_training_service
|
|
backtesting_service
|
|
broker_gateway_service
|
|
)
|
|
|
|
# Defaults
|
|
DO_PUSH=true
|
|
DRY_RUN=false
|
|
PARALLEL=1
|
|
SELECTED_SERVICES=()
|
|
SKIP_STANDARD=false
|
|
SKIP_WEBGW=false
|
|
SKIP_TRAINING=false
|
|
TAG_LATEST=true
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $(basename "$0") [OPTIONS]
|
|
|
|
Options:
|
|
--no-push Build only, don't push to registry
|
|
--dry-run Show what would be built
|
|
--services "s1 s2" Build only these standard services
|
|
--skip-webgw Skip web-gateway build
|
|
--skip-training Skip training image build
|
|
--parallel N Run N builds concurrently (default: 1)
|
|
--no-latest Don't tag images as :latest
|
|
-h, --help Show this help
|
|
EOF
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--no-push) DO_PUSH=false; shift ;;
|
|
--dry-run) DRY_RUN=true; shift ;;
|
|
--services) IFS=' ' read -ra SELECTED_SERVICES <<< "$2"; shift 2 ;;
|
|
--skip-webgw) SKIP_WEBGW=true; shift ;;
|
|
--skip-training) SKIP_TRAINING=true; shift ;;
|
|
--parallel) PARALLEL="$2"; shift 2 ;;
|
|
--no-latest) TAG_LATEST=false; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) echo "Unknown option: $1"; usage; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# If --services was given, use only those; otherwise use all standard services
|
|
if [[ ${#SELECTED_SERVICES[@]} -gt 0 ]]; then
|
|
SERVICES=("${SELECTED_SERVICES[@]}")
|
|
SKIP_WEBGW=true
|
|
SKIP_TRAINING=true
|
|
else
|
|
SERVICES=("${STANDARD_SERVICES[@]}")
|
|
fi
|
|
|
|
# Dirty check
|
|
if ! git diff-index --quiet HEAD -- 2>/dev/null; then
|
|
GIT_COMMIT="${GIT_COMMIT}-dirty"
|
|
fi
|
|
|
|
TAG_COMMIT="${GIT_COMMIT}"
|
|
TAG_TS="${TIMESTAMP}"
|
|
|
|
echo "=== Foxhunt Docker Build ==="
|
|
echo "Registry: ${REGISTRY}/${NAMESPACE}"
|
|
echo "Commit: ${TAG_COMMIT}"
|
|
echo "Timestamp: ${TAG_TS}"
|
|
echo "Parallel: ${PARALLEL}"
|
|
echo ""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
FAILURES=()
|
|
|
|
build_and_tag() {
|
|
local image_name="$1"
|
|
local dockerfile="$2"
|
|
shift 2
|
|
local extra_args=("$@")
|
|
|
|
local full="${REGISTRY}/${NAMESPACE}/${image_name}"
|
|
|
|
local tags=("-t" "${full}:${TAG_COMMIT}" "-t" "${full}:${TAG_TS}")
|
|
if [[ "$TAG_LATEST" == "true" ]]; then
|
|
tags+=("-t" "${full}:latest")
|
|
fi
|
|
|
|
local cmd=(docker build "${tags[@]}" -f "$dockerfile" "${extra_args[@]}" .)
|
|
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo " [DRY] ${cmd[*]}"
|
|
return 0
|
|
fi
|
|
|
|
echo " Building ${image_name}..."
|
|
local start
|
|
start=$(date +%s)
|
|
|
|
if DOCKER_BUILDKIT=1 "${cmd[@]}" 2>&1 | tail -5; then
|
|
local elapsed=$(( $(date +%s) - start ))
|
|
echo " [OK] ${image_name} (${elapsed}s)"
|
|
(( PASS++ ))
|
|
else
|
|
echo " [FAIL] ${image_name}"
|
|
(( FAIL++ ))
|
|
FAILURES+=("${image_name}")
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
push_image() {
|
|
local image_name="$1"
|
|
local full="${REGISTRY}/${NAMESPACE}/${image_name}"
|
|
|
|
for tag in "${TAG_COMMIT}" "${TAG_TS}" $( [[ "$TAG_LATEST" == "true" ]] && echo "latest" ); do
|
|
if [[ "$DRY_RUN" == "true" ]]; then
|
|
echo " [DRY] docker push ${full}:${tag}"
|
|
else
|
|
echo " Pushing ${full}:${tag}"
|
|
docker push "${full}:${tag}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Ensure registry login
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if [[ "$DRY_RUN" != "true" && "$DO_PUSH" == "true" ]]; then
|
|
echo "--- Registry Login ---"
|
|
if ! docker login "${REGISTRY}" -u nologin --password-stdin <<< "$(scw registry login -o json 2>/dev/null | python3 -c 'import sys,json; print(json.load(sys.stdin).get("password",""))' 2>/dev/null)" 2>/dev/null; then
|
|
echo " Trying scw registry login..."
|
|
scw registry login
|
|
fi
|
|
echo ""
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build standard services (Dockerfile.service)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
echo "--- Standard Services ---"
|
|
|
|
if [[ "$PARALLEL" -gt 1 ]]; then
|
|
# Parallel builds using background jobs
|
|
PIDS=()
|
|
for svc in "${SERVICES[@]}"; do
|
|
(
|
|
build_and_tag "$svc" "infra/docker/Dockerfile.service" --build-arg "SERVICE=${svc}"
|
|
) &
|
|
PIDS+=($!)
|
|
# Throttle to PARALLEL concurrent jobs
|
|
while [[ $(jobs -r | wc -l) -ge $PARALLEL ]]; do
|
|
sleep 1
|
|
done
|
|
done
|
|
# Wait for all builds
|
|
for pid in "${PIDS[@]}"; do
|
|
wait "$pid" || (( FAIL++ ))
|
|
done
|
|
else
|
|
for svc in "${SERVICES[@]}"; do
|
|
build_and_tag "$svc" "infra/docker/Dockerfile.service" --build-arg "SERVICE=${svc}" || true
|
|
done
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build web-gateway (Dockerfile.web-gateway)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if [[ "$SKIP_WEBGW" != "true" ]]; then
|
|
echo ""
|
|
echo "--- Web Gateway ---"
|
|
build_and_tag "web-gateway" "infra/docker/Dockerfile.web-gateway" || true
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build training image (Dockerfile.training)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if [[ "$SKIP_TRAINING" != "true" ]]; then
|
|
echo ""
|
|
echo "--- Training Image ---"
|
|
build_and_tag "training" "infra/docker/Dockerfile.training" || true
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Push
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if [[ "$DO_PUSH" == "true" ]]; then
|
|
echo ""
|
|
echo "--- Pushing Images ---"
|
|
|
|
for svc in "${SERVICES[@]}"; do
|
|
push_image "$svc"
|
|
done
|
|
|
|
if [[ "$SKIP_WEBGW" != "true" ]]; then
|
|
push_image "web-gateway"
|
|
fi
|
|
|
|
if [[ "$SKIP_TRAINING" != "true" ]]; then
|
|
push_image "training"
|
|
fi
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Summary
|
|
# ---------------------------------------------------------------------------
|
|
|
|
echo ""
|
|
echo "======================================================================"
|
|
printf " Results: %d built, %d failed\n" "$PASS" "$FAIL"
|
|
echo "======================================================================"
|
|
|
|
if [[ $FAIL -gt 0 ]]; then
|
|
echo ""
|
|
echo " Failed:"
|
|
for f in "${FAILURES[@]}"; do
|
|
echo " - ${f}"
|
|
done
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo " All images built successfully."
|
|
if [[ "$DO_PUSH" == "true" && "$DRY_RUN" != "true" ]]; then
|
|
echo " Pushed to: ${REGISTRY}/${NAMESPACE}/"
|
|
fi
|
|
exit 0
|