Files
WonderQ-Project/scripts/jenkins-freestyle.sh
2026-08-27 16:21:31 +08:00

158 lines
4.9 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -Eeuo pipefail
set +x
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname -- "$SCRIPT_DIR")"
cd "$PROJECT_ROOT"
# Jenkins 页面只需要配置 ACR_REGISTRY 和 DEPLOY_TO_ACK。
# 其余默认值已与当前 ACK 资源对齐,必要时仍可通过同名环境变量覆盖。
ACR_REGISTRY="${ACR_REGISTRY:-}"
ACR_NAMESPACE="${ACR_NAMESPACE:-one-feel}"
API_REPOSITORY="${API_REPOSITORY:-wanderq-api}"
ADMIN_REPOSITORY="${ADMIN_REPOSITORY:-wanderq-admin}"
ACK_NAMESPACE="${ACK_NAMESPACE:-wanqu}"
API_DEPLOYMENT="${API_DEPLOYMENT:-wanderq-api}"
API_CONTAINER="${API_CONTAINER:-}"
ADMIN_DEPLOYMENT="${ADMIN_DEPLOYMENT:-wanderq-admin}"
ADMIN_CONTAINER="${ADMIN_CONTAINER:-}"
ADMIN_API_BASE_URL="${ADMIN_API_BASE_URL:-}"
DEPLOY_TO_ACK="${DEPLOY_TO_ACK:-false}"
BUILD_NUMBER="${BUILD_NUMBER:-local}"
DOCKER_BUILDKIT="${DOCKER_BUILDKIT:-1}"
export DOCKER_BUILDKIT
log() {
printf '\n[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
}
fail() {
printf '错误:%s\n' "$*" >&2
exit 1
}
require_command() {
command -v "$1" >/dev/null 2>&1 || fail "Jenkins Agent 缺少命令:$1"
}
[[ -n "$ACR_REGISTRY" ]] || fail "ACR_REGISTRY 不能为空"
[[ "$ACR_REGISTRY" != *://* ]] || fail "ACR_REGISTRY 只填写域名,不要包含协议"
[[ -n "$ACR_NAMESPACE" ]] || fail "ACR_NAMESPACE 不能为空"
case "$DEPLOY_TO_ACK" in
true|false) ;;
*) fail "DEPLOY_TO_ACK 只能是 true 或 false" ;;
esac
require_command git
require_command docker
docker version >/dev/null
if [[ "$DEPLOY_TO_ACK" == "true" ]]; then
require_command kubectl
[[ -n "${ACK_KUBECONFIG:-}" ]] || fail "未绑定 Jenkins kubeconfig 文件变量 ACK_KUBECONFIG"
[[ -f "$ACK_KUBECONFIG" ]] || fail "ACK_KUBECONFIG 指向的文件不存在"
fi
GIT_COMMIT="$(git rev-parse --short=12 HEAD)"
IMAGE_TAG="${IMAGE_TAG:-${GIT_COMMIT}-${BUILD_NUMBER}}"
API_IMAGE="${ACR_REGISTRY}/${ACR_NAMESPACE}/${API_REPOSITORY}"
ADMIN_IMAGE="${ACR_REGISTRY}/${ACR_NAMESPACE}/${ADMIN_REPOSITORY}"
test_container=""
cleanup() {
if [[ -n "$test_container" ]]; then
docker rm --force "$test_container" >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT
log "构建 API 镜像:$API_IMAGE:$IMAGE_TAG"
docker build \
--tag "$API_IMAGE:$IMAGE_TAG" \
WonderQ-Admin
log "运行 API 测试"
test_container="$(docker create \
--entrypoint python \
"$API_IMAGE:$IMAGE_TAG" \
-m pytest)"
docker cp WonderQ-Admin/tests/. "$test_container:/app/tests"
docker cp WonderQ-Admin/docker-compose.yml "$test_container:/app/docker-compose.yml"
docker start --attach "$test_container"
docker rm "$test_container" >/dev/null
test_container=""
log "构建 Admin UI 镜像:$ADMIN_IMAGE:$IMAGE_TAG"
docker build \
--build-arg "VITE_API_BASE_URL=$ADMIN_API_BASE_URL" \
--tag "$ADMIN_IMAGE:$IMAGE_TAG" \
WonderQ-Admin-UI-Vue
log "检查 Admin UI Nginx 配置"
docker run --rm \
--entrypoint nginx \
"$ADMIN_IMAGE:$IMAGE_TAG" \
-t
log "推送镜像"
docker push "$API_IMAGE:$IMAGE_TAG"
docker push "$ADMIN_IMAGE:$IMAGE_TAG"
if [[ "$DEPLOY_TO_ACK" != "true" ]]; then
log "镜像已推送DEPLOY_TO_ACK=false本次不更新 ACK"
exit 0
fi
KUBECTL=(
kubectl
--kubeconfig "$ACK_KUBECONFIG"
--namespace "$ACK_NAMESPACE"
)
log "检查 ACK Deployment"
"${KUBECTL[@]}" get deployment "$API_DEPLOYMENT" >/dev/null
"${KUBECTL[@]}" get deployment "$ADMIN_DEPLOYMENT" >/dev/null
# 当前两个 Deployment 均为单容器;自动读取容器名,避免把 Pod 名称或历史拼写写进 Jenkins 参数。
if [[ -z "$API_CONTAINER" ]]; then
API_CONTAINER="$("${KUBECTL[@]}" get deployment "$API_DEPLOYMENT" \
-o jsonpath='{.spec.template.spec.containers[0].name}')"
fi
if [[ -z "$ADMIN_CONTAINER" ]]; then
ADMIN_CONTAINER="$("${KUBECTL[@]}" get deployment "$ADMIN_DEPLOYMENT" \
-o jsonpath='{.spec.template.spec.containers[0].name}')"
fi
[[ -n "$API_CONTAINER" ]] || fail "无法读取 API Deployment 的容器名称"
[[ -n "$ADMIN_CONTAINER" ]] || fail "无法读取 Admin UI Deployment 的容器名称"
log "更新 API Deployment$API_DEPLOYMENT/$API_CONTAINER"
"${KUBECTL[@]}" set image \
"deployment/$API_DEPLOYMENT" \
"$API_CONTAINER=$API_IMAGE:$IMAGE_TAG"
if ! "${KUBECTL[@]}" rollout status \
"deployment/$API_DEPLOYMENT" \
--timeout=300s; then
"${KUBECTL[@]}" rollout undo "deployment/$API_DEPLOYMENT" || true
fail "API 发布失败,已尝试回滚 Deployment数据库迁移不会自动回滚"
fi
log "更新 Admin UI Deployment$ADMIN_DEPLOYMENT/$ADMIN_CONTAINER"
"${KUBECTL[@]}" set image \
"deployment/$ADMIN_DEPLOYMENT" \
"$ADMIN_CONTAINER=$ADMIN_IMAGE:$IMAGE_TAG"
if ! "${KUBECTL[@]}" rollout status \
"deployment/$ADMIN_DEPLOYMENT" \
--timeout=300s; then
"${KUBECTL[@]}" rollout undo "deployment/$ADMIN_DEPLOYMENT" || true
"${KUBECTL[@]}" rollout undo "deployment/$API_DEPLOYMENT" || true
fail "Admin UI 发布失败,已尝试回滚两个 Deployment"
fi
log "ACK 发布完成,镜像标签:$IMAGE_TAG"