支持开发环境远程部署
This commit is contained in:
Vendored
+4
-4
@@ -52,7 +52,7 @@ pipeline {
|
|||||||
booleanParam(name: 'SERVICE_INTEGRATION', defaultValue: false, description: '第三方集成服务(integration-service)')
|
booleanParam(name: 'SERVICE_INTEGRATION', defaultValue: false, description: '第三方集成服务(integration-service)')
|
||||||
booleanParam(name: 'SERVICE_EVENT_BRIDGE', defaultValue: false, description: '跨区域事件桥(event-bridge-service)')
|
booleanParam(name: 'SERVICE_EVENT_BRIDGE', defaultValue: false, description: '跨区域事件桥(event-bridge-service)')
|
||||||
booleanParam(name: 'SERVICE_AUDIT', defaultValue: false, description: '审计服务(audit-service)')
|
booleanParam(name: 'SERVICE_AUDIT', defaultValue: false, description: '审计服务(audit-service)')
|
||||||
choice(name: 'ENVIRONMENT', choices: ['test', 'staging', 'production'], description: '部署环境')
|
choice(name: 'ENVIRONMENT', choices: ['test', 'development', 'staging', 'production'], description: '部署环境')
|
||||||
booleanParam(name: 'DEPLOY', defaultValue: false, description: '各服务构建成功后是否独立部署')
|
booleanParam(name: 'DEPLOY', defaultValue: false, description: '各服务构建成功后是否独立部署')
|
||||||
booleanParam(name: 'INITIALIZE_TEST_DATABASE', defaultValue: false, description: '仅 test:调度服务前幂等初始化测试数据库')
|
booleanParam(name: 'INITIALIZE_TEST_DATABASE', defaultValue: false, description: '仅 test:调度服务前幂等初始化测试数据库')
|
||||||
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '是否跳过测试;生产构建不建议勾选')
|
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '是否跳过测试;生产构建不建议勾选')
|
||||||
@@ -66,9 +66,9 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
String requestedRepository
|
String requestedRepository
|
||||||
if (params.ENVIRONMENT == 'test') {
|
if (['development', 'test'].contains(params.ENVIRONMENT)) {
|
||||||
requestedRepository = 'baiyue-firstleg-test'
|
requestedRepository = "baiyue-firstleg-${params.ENVIRONMENT}"
|
||||||
echo '测试环境使用 Jenkins 节点本机镜像,不登录、不推送远程 Registry'
|
echo "${params.ENVIRONMENT} 环境使用本地构建镜像,不登录、不推送远程 Registry"
|
||||||
} else {
|
} else {
|
||||||
requestedRepository = params.IMAGE_REPOSITORY?.trim()
|
requestedRepository = params.IMAGE_REPOSITORY?.trim()
|
||||||
if (!requestedRepository || requestedRepository == 'registry.example.com/your-group/baiyue-firstleg') {
|
if (!requestedRepository || requestedRepository == 'registry.example.com/your-group/baiyue-firstleg') {
|
||||||
|
|||||||
+7
-4
@@ -36,7 +36,7 @@ pipeline {
|
|||||||
parameters {
|
parameters {
|
||||||
string(name: 'SOURCE_COMMIT', defaultValue: '', description: '必须构建的 Git commit;通常由总控 Job 传入')
|
string(name: 'SOURCE_COMMIT', defaultValue: '', description: '必须构建的 Git commit;通常由总控 Job 传入')
|
||||||
string(name: 'IMAGE_TAG', defaultValue: '', description: '不可变镜像标签;通常使用 Git commit 前 12 位')
|
string(name: 'IMAGE_TAG', defaultValue: '', description: '不可变镜像标签;通常使用 Git commit 前 12 位')
|
||||||
choice(name: 'ENVIRONMENT', choices: ['test', 'staging', 'production'], description: '部署环境')
|
choice(name: 'ENVIRONMENT', choices: ['test', 'development', 'staging', 'production'], description: '部署环境')
|
||||||
booleanParam(name: 'DEPLOY', defaultValue: false, description: '构建成功后是否部署本服务')
|
booleanParam(name: 'DEPLOY', defaultValue: false, description: '构建成功后是否部署本服务')
|
||||||
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '是否跳过测试')
|
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '是否跳过测试')
|
||||||
string(name: 'IMAGE_REPOSITORY', defaultValue: 'baiyue-firstleg-test', description: '镜像仓库基础路径,不包含服务名和标签')
|
string(name: 'IMAGE_REPOSITORY', defaultValue: 'baiyue-firstleg-test', description: '镜像仓库基础路径,不包含服务名和标签')
|
||||||
@@ -47,6 +47,9 @@ pipeline {
|
|||||||
REGISTRY_CREDENTIALS = 'gitea-test-token'
|
REGISTRY_CREDENTIALS = 'gitea-test-token'
|
||||||
MAVEN_SETTINGS = 'deploy/maven/settings-cn.xml'
|
MAVEN_SETTINGS = 'deploy/maven/settings-cn.xml'
|
||||||
MAVEN_OPTS = '-Dfile.encoding=UTF-8 -Dmaven.wagon.http.retryHandler.count=3'
|
MAVEN_OPTS = '-Dfile.encoding=UTF-8 -Dmaven.wagon.http.retryHandler.count=3'
|
||||||
|
DEVELOPMENT_SSH_TARGET = 'deploy@172.31.198.8'
|
||||||
|
DEVELOPMENT_SSH_KEY = '/var/jenkins_home/.ssh/dev_deploy'
|
||||||
|
DEVELOPMENT_DEPLOY_DIR = '/opt/firstleg/application'
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
@@ -81,7 +84,7 @@ pipeline {
|
|||||||
if (!imageRepository || imageRepository.contains('://')) {
|
if (!imageRepository || imageRepository.contains('://')) {
|
||||||
error('IMAGE_REPOSITORY 不能为空且不能包含 http:// 或 https://')
|
error('IMAGE_REPOSITORY 不能为空且不能包含 http:// 或 https://')
|
||||||
}
|
}
|
||||||
if (params.ENVIRONMENT != 'test' && !imageRepository.contains('/')) {
|
if (!['development', 'test'].contains(params.ENVIRONMENT) && !imageRepository.contains('/')) {
|
||||||
error('预发布/生产环境 IMAGE_REPOSITORY 必须使用 host[:port]/owner/image 格式')
|
error('预发布/生产环境 IMAGE_REPOSITORY 必须使用 host[:port]/owner/image 格式')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,8 +140,8 @@ pipeline {
|
|||||||
sh "mkdir -p '${contextDir}' && cp -f '${jar}' '${contextDir}/app.jar'"
|
sh "mkdir -p '${contextDir}' && cp -f '${jar}' '${contextDir}/app.jar'"
|
||||||
sh "docker build -f deploy/docker/Dockerfile --build-arg BASE_IMAGE=${params.DOCKER_BASE_IMAGE} --build-arg JAR_FILE=app.jar -t ${image} '${contextDir}'"
|
sh "docker build -f deploy/docker/Dockerfile --build-arg BASE_IMAGE=${params.DOCKER_BASE_IMAGE} --build-arg JAR_FILE=app.jar -t ${image} '${contextDir}'"
|
||||||
|
|
||||||
if (params.ENVIRONMENT == 'test') {
|
if (['development', 'test'].contains(params.ENVIRONMENT)) {
|
||||||
echo "测试镜像已保存在当前 Docker 节点:${image}"
|
echo "${params.ENVIRONMENT} 镜像已保存在当前 Docker 节点:${image}"
|
||||||
} else {
|
} else {
|
||||||
String registryHost = env.RESOLVED_IMAGE_REPOSITORY.tokenize('/')[0]
|
String registryHost = env.RESOLVED_IMAGE_REPOSITORY.tokenize('/')[0]
|
||||||
withCredentials([usernamePassword(credentialsId: env.REGISTRY_CREDENTIALS, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASSWORD')]) {
|
withCredentials([usernamePassword(credentialsId: env.REGISTRY_CREDENTIALS, usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASSWORD')]) {
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if [ "$#" -ne 4 ]; then
|
||||||
|
echo "用法: $0 <镜像仓库> <镜像标签> <逗号分隔服务> <环境文件>" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
IMAGE_REPOSITORY="$1"
|
||||||
|
IMAGE_TAG="$2"
|
||||||
|
SERVICE_CSV="$3"
|
||||||
|
ENV_FILE="$4"
|
||||||
|
|
||||||
|
SSH_TARGET="${DEVELOPMENT_SSH_TARGET:-deploy@172.31.198.8}"
|
||||||
|
SSH_KEY="${DEVELOPMENT_SSH_KEY:-/var/jenkins_home/.ssh/dev_deploy}"
|
||||||
|
REMOTE_DIR="${DEVELOPMENT_DEPLOY_DIR:-/opt/firstleg/application}"
|
||||||
|
COMPOSE_FILE="deploy/docker-compose.yml"
|
||||||
|
|
||||||
|
if [ ! -f "$SSH_KEY" ]; then
|
||||||
|
echo "开发环境 SSH 私钥不存在: $SSH_KEY" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "开发环境变量文件不存在: $ENV_FILE" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||||
|
echo "Compose 文件不存在: $COMPOSE_FILE" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
SERVICES=$(printf '%s' "$SERVICE_CSV" | tr ',' ' ')
|
||||||
|
for service in $SERVICES; do
|
||||||
|
case "$service" in
|
||||||
|
*[!A-Za-z0-9_-]*|'')
|
||||||
|
echo "非法服务名: $service" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
run_ssh() {
|
||||||
|
ssh -i "$SSH_KEY" \
|
||||||
|
-o BatchMode=yes \
|
||||||
|
-o StrictHostKeyChecking=yes \
|
||||||
|
-o ConnectTimeout=10 \
|
||||||
|
"$SSH_TARGET" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_scp() {
|
||||||
|
scp -i "$SSH_KEY" \
|
||||||
|
-o BatchMode=yes \
|
||||||
|
-o StrictHostKeyChecking=yes \
|
||||||
|
-o ConnectTimeout=10 \
|
||||||
|
"$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_ssh install -d -m 750 "$REMOTE_DIR"
|
||||||
|
|
||||||
|
SUFFIX="${IMAGE_TAG}.$$.${SERVICE_CSV}"
|
||||||
|
REMOTE_ENV_TMP="$REMOTE_DIR/.env.$SUFFIX.tmp"
|
||||||
|
REMOTE_COMPOSE_TMP="$REMOTE_DIR/docker-compose.yml.$SUFFIX.tmp"
|
||||||
|
|
||||||
|
run_scp "$ENV_FILE" "$SSH_TARGET:$REMOTE_ENV_TMP"
|
||||||
|
run_scp "$COMPOSE_FILE" "$SSH_TARGET:$REMOTE_COMPOSE_TMP"
|
||||||
|
|
||||||
|
run_ssh sh -s -- "$REMOTE_DIR" "$REMOTE_ENV_TMP" "$REMOTE_COMPOSE_TMP" <<'REMOTE_PREPARE'
|
||||||
|
set -eu
|
||||||
|
remote_dir="$1"
|
||||||
|
env_tmp="$2"
|
||||||
|
compose_tmp="$3"
|
||||||
|
chmod 600 "$env_tmp"
|
||||||
|
chmod 644 "$compose_tmp"
|
||||||
|
mv -f "$env_tmp" "$remote_dir/.env"
|
||||||
|
mv -f "$compose_tmp" "$remote_dir/docker-compose.yml"
|
||||||
|
REMOTE_PREPARE
|
||||||
|
|
||||||
|
for service in $SERVICES; do
|
||||||
|
image="$IMAGE_REPOSITORY/$service:$IMAGE_TAG"
|
||||||
|
docker image inspect "$image" >/dev/null
|
||||||
|
echo "传输开发镜像: $image"
|
||||||
|
docker save "$image" | gzip -1 | run_ssh 'gzip -dc | docker load'
|
||||||
|
done
|
||||||
|
|
||||||
|
run_ssh sh -s -- "$REMOTE_DIR" "$IMAGE_REPOSITORY" "$IMAGE_TAG" "$SERVICE_CSV" <<'REMOTE_DEPLOY'
|
||||||
|
set -eu
|
||||||
|
remote_dir="$1"
|
||||||
|
image_repository="$2"
|
||||||
|
image_tag="$3"
|
||||||
|
service_csv="$4"
|
||||||
|
services=$(printf '%s' "$service_csv" | tr ',' ' ')
|
||||||
|
|
||||||
|
cd "$remote_dir"
|
||||||
|
export DEPLOY_ENV=development
|
||||||
|
export IMAGE_REPOSITORY="$image_repository"
|
||||||
|
export IMAGE_TAG="$image_tag"
|
||||||
|
|
||||||
|
docker compose \
|
||||||
|
--project-name firstleg-development \
|
||||||
|
--env-file .env \
|
||||||
|
-f docker-compose.yml \
|
||||||
|
up -d --remove-orphans --pull never $services
|
||||||
|
|
||||||
|
docker compose \
|
||||||
|
--project-name firstleg-development \
|
||||||
|
--env-file .env \
|
||||||
|
-f docker-compose.yml \
|
||||||
|
ps $services
|
||||||
|
REMOTE_DEPLOY
|
||||||
@@ -74,6 +74,11 @@ esac
|
|||||||
|
|
||||||
export DEPLOY_ENV IMAGE_REPOSITORY IMAGE_TAG
|
export DEPLOY_ENV IMAGE_REPOSITORY IMAGE_TAG
|
||||||
|
|
||||||
|
if [ "$DEPLOY_ENV" = "development" ]; then
|
||||||
|
exec sh deploy/scripts/deploy-development-service.sh \
|
||||||
|
"$IMAGE_REPOSITORY" "$IMAGE_TAG" "$SERVICE_CSV" "$ENV_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
PULL_POLICY_ARGS=""
|
PULL_POLICY_ARGS=""
|
||||||
if [ "$DEPLOY_ENV" = "test" ]; then
|
if [ "$DEPLOY_ENV" = "test" ]; then
|
||||||
PULL_POLICY_ARGS="--pull never"
|
PULL_POLICY_ARGS="--pull never"
|
||||||
|
|||||||
Reference in New Issue
Block a user