优化
This commit is contained in:
Vendored
+16
-187
@@ -1,11 +1,10 @@
|
||||
def serviceModules = [
|
||||
'gateway', 'gateway-overseas', 'auth', 'iam', 'firstleg', 'finance', 'order', 'warehouse', 'file', 'print',
|
||||
'integration-service', 'lastleg-service', 'warehouse-overseas-service', 'event-bridge-service', 'audit-service'
|
||||
'gateway', 'auth', 'iam', 'firstleg', 'finance', 'order', 'warehouse', 'file', 'print',
|
||||
'integration-service', 'lastleg-service', 'warehouse-overseas-service', 'audit-service'
|
||||
]
|
||||
|
||||
def serviceCheckboxes = [
|
||||
'gateway': 'SERVICE_GATEWAY',
|
||||
'gateway-overseas': 'SERVICE_GATEWAY_OVERSEAS',
|
||||
'auth': 'SERVICE_AUTH',
|
||||
'iam': 'SERVICE_IAM',
|
||||
'firstleg': 'SERVICE_FIRSTLEG',
|
||||
@@ -17,20 +16,19 @@ def serviceCheckboxes = [
|
||||
'integration-service': 'SERVICE_INTEGRATION',
|
||||
'lastleg-service': 'SERVICE_LASTLEG',
|
||||
'warehouse-overseas-service': 'SERVICE_WAREHOUSE_OVERSEAS',
|
||||
'event-bridge-service': 'SERVICE_EVENT_BRIDGE',
|
||||
'audit-service': 'SERVICE_AUDIT'
|
||||
]
|
||||
|
||||
def fullRebuildPaths = [
|
||||
'pom.xml', 'platform-bom/', 'common-core/', 'deploy/docker/',
|
||||
'deploy/docker-compose.yml', 'deploy/service-map.yml'
|
||||
'deploy/docker-compose.yml', 'deploy/service-map.yml', 'config/nacos/test/', 'deploy/scripts/', 'Jenkinsfile'
|
||||
]
|
||||
|
||||
def commonPathServices = [
|
||||
'common-web/': [
|
||||
'auth', 'iam', 'firstleg', 'finance', 'order', 'warehouse', 'file', 'print',
|
||||
'integration-service', 'lastleg-service', 'warehouse-overseas-service',
|
||||
'event-bridge-service', 'audit-service'
|
||||
'audit-service'
|
||||
],
|
||||
'common-security/': [
|
||||
'auth', 'iam', 'firstleg', 'finance', 'order', 'warehouse', 'file',
|
||||
@@ -39,20 +37,16 @@ def commonPathServices = [
|
||||
'common-openapi/': [
|
||||
'auth', 'iam', 'firstleg', 'finance', 'order', 'warehouse', 'file', 'print',
|
||||
'integration-service', 'lastleg-service', 'warehouse-overseas-service',
|
||||
'event-bridge-service', 'audit-service'
|
||||
'audit-service'
|
||||
],
|
||||
'common-audit/': [
|
||||
'auth', 'iam', 'firstleg', 'finance', 'order', 'warehouse', 'file',
|
||||
'warehouse-overseas-service', 'audit-service'
|
||||
],
|
||||
'common-event-contract/': [
|
||||
'firstleg', 'iam', 'lastleg-service', 'event-bridge-service'
|
||||
],
|
||||
'deploy/docker-compose.overseas.yml': [
|
||||
'gateway-overseas', 'lastleg-service', 'warehouse-overseas-service', 'event-bridge-service'
|
||||
'firstleg', 'finance', 'lastleg-service'
|
||||
],
|
||||
'deploy/docker-compose.audit.yml': ['audit-service'],
|
||||
'deploy/docker-compose.rocketmq.yml': ['event-bridge-service']
|
||||
]
|
||||
|
||||
def databaseMigrationPaths = ['deploy/sql/']
|
||||
@@ -63,45 +57,6 @@ def downstreamResults = [:]
|
||||
def downstreamBuildUrls = [:]
|
||||
def downstreamBuildNumbers = [:]
|
||||
|
||||
def sendProductionWeComNotification(String title, String status, String color, String detail) {
|
||||
node('java-builder') {
|
||||
withCredentials([string(credentialsId: 'wecom-prod-webhook', variable: 'WECOM_WEBHOOK')]) {
|
||||
String sourceVersion = env.IMAGE_TAG ?: env.SOURCE_COMMIT ?: env.GIT_COMMIT ?: '未解析'
|
||||
String duration = currentBuild.durationString?.replace(' and counting', '') ?: '—'
|
||||
String content = """## ${title}
|
||||
> 应用:后端服务
|
||||
> Job:${env.JOB_NAME}
|
||||
> 构建:[#${env.BUILD_NUMBER}](${env.BUILD_URL})
|
||||
> 提交:${sourceVersion}
|
||||
> 状态:<font color="${color}">${status}</font>
|
||||
${detail}
|
||||
> 耗时:${duration}
|
||||
> 时间:${new Date().format('yyyy-MM-dd HH:mm:ss', TimeZone.getTimeZone('Asia/Shanghai'))}
|
||||
"""
|
||||
String payloadFile = 'wecom-production-notification.json'
|
||||
writeFile(
|
||||
file: payloadFile,
|
||||
text: groovy.json.JsonOutput.toJson([
|
||||
msgtype: 'markdown',
|
||||
markdown: [content: content]
|
||||
]),
|
||||
encoding: 'UTF-8'
|
||||
)
|
||||
sh '''
|
||||
set -eu
|
||||
payload_file='wecom-production-notification.json'
|
||||
trap 'rm -f "$payload_file"' EXIT HUP INT TERM
|
||||
response="$(curl --fail --silent --show-error \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary @"$payload_file" \
|
||||
"$WECOM_WEBHOOK")"
|
||||
printf '%s\n' "$response"
|
||||
printf '%s' "$response" | grep -Eq '"errcode"[[:space:]]*:[[:space:]]*0([[:space:]]*[,}])'
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def parseAutoBuildState(String description, List<String> allowedServices) {
|
||||
if (!description?.startsWith('AUTO ')) return null
|
||||
int markerIndex = description.indexOf(' | ')
|
||||
@@ -154,12 +109,8 @@ def environmentChoicesForJob(String jobBaseName) {
|
||||
|
||||
def fixedEnvironmentForJob(String jobBaseName) {
|
||||
switch (jobBaseName) {
|
||||
case 'backend-java-dev':
|
||||
return 'development'
|
||||
case 'backend-java':
|
||||
return 'test'
|
||||
case 'backend-java-prod':
|
||||
return 'production'
|
||||
default:
|
||||
return null
|
||||
}
|
||||
@@ -167,12 +118,8 @@ def fixedEnvironmentForJob(String jobBaseName) {
|
||||
|
||||
def fixedDownstreamJobPrefixForJob(String jobBaseName) {
|
||||
switch (jobBaseName) {
|
||||
case 'backend-java-dev':
|
||||
return 'baiyue-firstleg-dev-'
|
||||
case 'backend-java':
|
||||
return 'baiyue-firstleg-'
|
||||
case 'backend-java-prod':
|
||||
return 'baiyue-firstleg-prod-'
|
||||
default:
|
||||
return null
|
||||
}
|
||||
@@ -195,9 +142,8 @@ pipeline {
|
||||
parameters {
|
||||
choice(name: 'BUILD_MODE', choices: ['AUTO', 'SELECT', 'ALL'], description: 'AUTO 按 Git 变更识别;SELECT 勾选服务;ALL 构建全部服务')
|
||||
booleanParam(name: 'SERVICE_GATEWAY', defaultValue: false, description: 'Gateway 网关服务(gateway)')
|
||||
booleanParam(name: 'SERVICE_GATEWAY_OVERSEAS', defaultValue: false, description: '海外 Gateway 网关服务(gateway-overseas)')
|
||||
booleanParam(name: 'SERVICE_AUTH', defaultValue: false, description: '统一认证服务(auth)')
|
||||
booleanParam(name: 'SERVICE_IAM', defaultValue: false, description: '租户与权限服务(iam)')
|
||||
booleanParam(name: 'SERVICE_IAM', defaultValue: false, description: '客户与权限服务(iam)')
|
||||
booleanParam(name: 'SERVICE_FIRSTLEG', defaultValue: false, description: '头程履约服务(firstleg)')
|
||||
booleanParam(name: 'SERVICE_FINANCE', defaultValue: false, description: '财务服务(finance)')
|
||||
booleanParam(name: 'SERVICE_ORDER', defaultValue: false, description: '订单服务(order)')
|
||||
@@ -207,14 +153,12 @@ pipeline {
|
||||
booleanParam(name: 'SERVICE_INTEGRATION', defaultValue: false, description: '第三方集成服务(integration-service)')
|
||||
booleanParam(name: 'SERVICE_LASTLEG', defaultValue: false, description: '海外尾程与入仓服务(lastleg-service)')
|
||||
booleanParam(name: 'SERVICE_WAREHOUSE_OVERSEAS', defaultValue: false, description: '海外仓资源服务(warehouse-overseas-service)')
|
||||
booleanParam(name: 'SERVICE_EVENT_BRIDGE', defaultValue: false, description: '跨区域事件桥(event-bridge-service;默认同时部署国内和海外实例)')
|
||||
choice(name: 'EVENT_BRIDGE_REGION', choices: ['BOTH', 'CN', 'OVERSEAS'], description: 'BOTH 同时部署国内和海外实例;CN/OVERSEAS 用于单区故障重跑')
|
||||
booleanParam(name: 'SERVICE_AUDIT', defaultValue: false, description: '审计服务(audit-service)')
|
||||
choice(name: 'ENVIRONMENT', choices: environmentChoicesForJob(env.JOB_BASE_NAME), description: '部署环境')
|
||||
booleanParam(name: 'DEPLOY', defaultValue: false, description: '各服务构建成功后是否独立部署')
|
||||
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '是否跳过测试;生产构建不建议勾选')
|
||||
string(name: 'IMAGE_REPOSITORY', defaultValue: 'git.buggoglobal.com/java-project/baiyue-firstleg', description: '共享镜像仓库地址')
|
||||
string(name: 'DOCKER_BASE_IMAGE', defaultValue: 'git.buggoglobal.com/java-project/eclipse-temurin:17-jre-alpine', description: 'Java 17 基础镜像')
|
||||
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: '是否跳过测试执行(仍编译测试源码)')
|
||||
string(name: 'IMAGE_REPOSITORY', defaultValue: 'registry.example.com/team/baiyue-firstleg', description: '共享镜像仓库地址')
|
||||
string(name: 'DOCKER_BASE_IMAGE', defaultValue: 'eclipse-temurin:17-jre-alpine', description: 'Java 17 基础镜像')
|
||||
choice(name: 'DOWNSTREAM_JOB_PREFIX', choices: downstreamJobPrefixChoicesForJob(env.JOB_BASE_NAME), description: '由当前总控 Job 固定的单服务 Job 前缀')
|
||||
}
|
||||
|
||||
@@ -230,7 +174,7 @@ pipeline {
|
||||
}
|
||||
if (params.ENVIRONMENT != resolvedEnvironment ||
|
||||
params.DOWNSTREAM_JOB_PREFIX?.trim() != resolvedJobPrefix) {
|
||||
echo "忽略外部传入的环境或 Job 前缀;${env.JOB_BASE_NAME} 固定使用 ${resolvedEnvironment} / ${resolvedJobPrefix}"
|
||||
error('当前流水线仅允许 TEST 与 baiyue-firstleg- 下游前缀')
|
||||
}
|
||||
env.RESOLVED_ENVIRONMENT = resolvedEnvironment
|
||||
echo "Job ${env.JOB_BASE_NAME} 使用部署环境: ${env.RESOLVED_ENVIRONMENT}"
|
||||
@@ -239,16 +183,7 @@ pipeline {
|
||||
env.SOURCE_COMMIT = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
|
||||
env.IMAGE_TAG = sh(script: 'git rev-parse --short=12 HEAD', returnStdout: true).trim()
|
||||
|
||||
if (env.RESOLVED_ENVIRONMENT == 'production') {
|
||||
sh '''
|
||||
set -eu
|
||||
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
|
||||
test "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" || {
|
||||
echo "生产构建只允许 origin/main 当前提交;请先通过 Pull Request 合并到 main 后再部署" >&2
|
||||
exit 1
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
|
||||
String requestedRepository = params.IMAGE_REPOSITORY?.trim()
|
||||
if (!requestedRepository || requestedRepository == 'registry.example.com/your-group/baiyue-firstleg') {
|
||||
@@ -262,9 +197,7 @@ pipeline {
|
||||
|
||||
env.RESOLVED_JOB_PREFIX = resolvedJobPrefix
|
||||
env.DATABASE_CHANGE_DETECTED = 'false'
|
||||
if (env.RESOLVED_ENVIRONMENT == 'production' && params.SKIP_TESTS) {
|
||||
error('生产环境禁止跳过测试')
|
||||
}
|
||||
|
||||
|
||||
List selected = []
|
||||
if (params.BUILD_MODE == 'ALL') {
|
||||
@@ -326,15 +259,7 @@ pipeline {
|
||||
}
|
||||
|
||||
selected = selected.unique()
|
||||
if (params.DEPLOY && selected.contains('event-bridge-service')) {
|
||||
String bridgeRegion = params.EVENT_BRIDGE_REGION?.trim()
|
||||
if (!['BOTH', 'SELECT', 'CN', 'OVERSEAS'].contains(bridgeRegion)) {
|
||||
error('EVENT_BRIDGE_REGION 只能为 BOTH、CN 或 OVERSEAS')
|
||||
}
|
||||
if (bridgeRegion == 'SELECT') {
|
||||
echo '兼容旧 Jenkins 参数 SELECT:本次按 BOTH 同时部署国内和海外事件桥'
|
||||
}
|
||||
}
|
||||
|
||||
env.SELECTED_SERVICES = selected.join(',')
|
||||
env.NO_SERVICE_CHANGE = selected ? 'false' : 'true'
|
||||
if (!selected) {
|
||||
@@ -426,14 +351,6 @@ pipeline {
|
||||
String service = selectedService
|
||||
branches[service] = {
|
||||
String jobName = "${env.RESOLVED_JOB_PREFIX}${service}"
|
||||
boolean deployBothBridges = service == 'event-bridge-service' &&
|
||||
['BOTH', 'SELECT'].contains(params.EVENT_BRIDGE_REGION)
|
||||
String downstreamImageTag = deployBothBridges
|
||||
? "${env.IMAGE_TAG}-both"
|
||||
: env.IMAGE_TAG
|
||||
String downstreamBridgeRegion = deployBothBridges
|
||||
? 'CN'
|
||||
: (service == 'event-bridge-service' ? params.EVENT_BRIDGE_REGION : 'CN')
|
||||
echo "触发单服务 Job: ${jobName}"
|
||||
def downstreamBuild = build(
|
||||
job: jobName,
|
||||
@@ -441,16 +358,13 @@ pipeline {
|
||||
propagate: false,
|
||||
parameters: [
|
||||
string(name: 'SOURCE_COMMIT', value: env.SOURCE_COMMIT),
|
||||
string(name: 'IMAGE_TAG', value: downstreamImageTag),
|
||||
string(name: 'IMAGE_TAG', value: env.IMAGE_TAG),
|
||||
string(name: 'ENVIRONMENT', value: env.RESOLVED_ENVIRONMENT),
|
||||
booleanParam(name: 'DEPLOY', value: params.DEPLOY),
|
||||
// 总控已完成统一测试,或用户已明确选择跳过;下游仅负责编译、打包和部署。
|
||||
booleanParam(name: 'SKIP_TESTS', value: true),
|
||||
string(name: 'IMAGE_REPOSITORY', value: env.RESOLVED_IMAGE_REPOSITORY),
|
||||
string(name: 'DOCKER_BASE_IMAGE', value: params.DOCKER_BASE_IMAGE),
|
||||
// Choice 参数始终传递所有新旧 Job 都接受的单区值;
|
||||
// 双区意图通过现有 IMAGE_TAG 参数携带,由下游还原真实镜像标签。
|
||||
string(name: 'EVENT_BRIDGE_REGION', value: downstreamBridgeRegion)
|
||||
string(name: 'DOCKER_BASE_IMAGE', value: params.DOCKER_BASE_IMAGE)
|
||||
]
|
||||
)
|
||||
downstreamResults[service] = downstreamBuild.result ?: 'UNKNOWN'
|
||||
@@ -483,89 +397,4 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
script {
|
||||
if (env.JOB_BASE_NAME == 'backend-java-prod' && params.DEPLOY && env.NO_SERVICE_CHANGE != 'true') {
|
||||
try {
|
||||
List deployedServices = env.SELECTED_SERVICES?.split(',')
|
||||
?.collect { it.trim() }
|
||||
?.findAll { it } ?: []
|
||||
String serviceSummary = deployedServices.size() <= 3
|
||||
? deployedServices.join('、')
|
||||
: "${deployedServices.size()} 个服务"
|
||||
sendProductionWeComNotification(
|
||||
'✅ 生产部署成功',
|
||||
'成功',
|
||||
'info',
|
||||
"> 结果:${deployedServices.size()} 个服务全部成功\n" +
|
||||
"> 部署服务:${serviceSummary ?: '—'}"
|
||||
)
|
||||
} catch (Exception error) {
|
||||
echo "企业微信通知失败,不影响原构建结果:${error.message}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unstable {
|
||||
script {
|
||||
if (env.JOB_BASE_NAME == 'backend-java-prod' && params.DEPLOY) {
|
||||
try {
|
||||
List failedServices = downstreamResults.findAll { service, result -> result != 'SUCCESS' }
|
||||
.collect { service, result -> service }
|
||||
int successCount = downstreamResults.findAll { service, result -> result == 'SUCCESS' }.size()
|
||||
String failedLinks = failedServices.collect { service ->
|
||||
String url = downstreamBuildUrls[service]
|
||||
String number = downstreamBuildNumbers[service]
|
||||
String label = number ? "${service} #${number}" : service
|
||||
url ? "[${label}](${url})" : label
|
||||
}.join('、')
|
||||
sendProductionWeComNotification(
|
||||
'⚠️ 生产部署部分失败',
|
||||
'部分失败',
|
||||
'warning',
|
||||
"> 结果:成功 ${successCount} / 失败 ${failedServices.size()}\n" +
|
||||
"> 失败服务:${failedLinks ?: '未解析'}\n" +
|
||||
'> 说明:点击失败服务可直接查看下游构建日志'
|
||||
)
|
||||
} catch (Exception error) {
|
||||
echo "企业微信通知失败,不影响原构建结果:${error.message}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
failure {
|
||||
script {
|
||||
if (env.JOB_BASE_NAME == 'backend-java-prod' && params.DEPLOY) {
|
||||
try {
|
||||
sendProductionWeComNotification(
|
||||
'❌ 生产发布失败',
|
||||
'失败',
|
||||
'warning',
|
||||
'> 说明:生产发布流程失败,请打开父构建日志查看失败阶段'
|
||||
)
|
||||
} catch (Exception error) {
|
||||
echo "企业微信通知失败,不影响原构建结果:${error.message}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aborted {
|
||||
script {
|
||||
if (env.JOB_BASE_NAME == 'backend-java-prod' && params.DEPLOY) {
|
||||
try {
|
||||
sendProductionWeComNotification(
|
||||
'⏹ 生产部署已取消',
|
||||
'已取消',
|
||||
'comment',
|
||||
'> 说明:生产部署流程被人工取消或中止'
|
||||
)
|
||||
} catch (Exception error) {
|
||||
echo "企业微信通知失败,不影响原构建结果:${error.message}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user