增加打包脚本

This commit is contained in:
andy
2026-08-25 10:53:19 +08:00
parent ed5cfe08b8
commit c608e186d6

169
scripts/jenkins-freestyle.sh Executable file
View File

@@ -0,0 +1,169 @@
#!/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 不能为空"
[[ -n "${ACR_USERNAME:-}" ]] || fail "未绑定 Jenkins ACR 用户名变量 ACR_USERNAME"
[[ -n "${ACR_PASSWORD:-}" ]] || fail "未绑定 Jenkins ACR 密码变量 ACR_PASSWORD"
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=""
docker_config=""
cleanup() {
if [[ -n "$test_container" ]]; then
docker rm --force "$test_container" >/dev/null 2>&1 || true
fi
if [[ -n "$docker_config" && -d "$docker_config" ]]; then
docker logout "$ACR_REGISTRY" >/dev/null 2>&1 || true
rm -rf -- "$docker_config"
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 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
log "检查 Admin UI Nginx 配置"
docker run --rm \
--entrypoint nginx \
"$ADMIN_IMAGE:$IMAGE_TAG" \
-t
log "登录 ACR 并推送镜像"
docker_config="$(mktemp -d)"
export DOCKER_CONFIG="$docker_config"
printf '%s' "$ACR_PASSWORD" | docker login \
--username "$ACR_USERNAME" \
--password-stdin \
"$ACR_REGISTRY"
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"