diff --git a/Jenkinsfile b/Jenkinsfile index e1c9c2258..0660d219a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -229,6 +229,14 @@ 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' + : params.EVENT_BRIDGE_REGION echo "触发单服务 Job: ${jobName}" def downstreamBuild = build( job: jobName, @@ -236,17 +244,16 @@ pipeline { propagate: false, parameters: [ string(name: 'SOURCE_COMMIT', value: env.SOURCE_COMMIT), - string(name: 'IMAGE_TAG', value: env.IMAGE_TAG), + string(name: 'IMAGE_TAG', value: downstreamImageTag), 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), - // 旧下游 Job 的 ChoiceParameterDefinition 尚不接受 BOTH; - // 使用兼容值 SELECT 传递,下游新流水线会将其解释为双区域部署。 - string(name: 'EVENT_BRIDGE_REGION', value: - params.EVENT_BRIDGE_REGION == 'BOTH' ? 'SELECT' : params.EVENT_BRIDGE_REGION) + // Choice 参数始终传递所有新旧 Job 都接受的单区值; + // 双区意图通过现有 IMAGE_TAG 参数携带,由下游还原真实镜像标签。 + string(name: 'EVENT_BRIDGE_REGION', value: downstreamBridgeRegion) ] ) downstreamResults[service] = downstreamBuild.result ?: 'UNKNOWN' diff --git a/Jenkinsfile.service b/Jenkinsfile.service index fcdf1cbff..a1aed8754 100644 --- a/Jenkinsfile.service +++ b/Jenkinsfile.service @@ -76,6 +76,11 @@ pipeline { if (!serviceModules.contains(service)) { error("无法从 Job 名称 ${env.JOB_BASE_NAME} 识别服务;名称必须以以下服务之一结尾: ${serviceModules.join(', ')}") } + boolean deployBothBridges = service == 'event-bridge-service' + && imageTag?.endsWith('-both') + if (deployBothBridges) { + imageTag = imageTag.substring(0, imageTag.length() - '-both'.length()) + } if (!sourceCommit || !(sourceCommit ==~ /(?i)[0-9a-f]{7,40}/)) { error('SOURCE_COMMIT 必须是 7 到 40 位十六进制 Git commit') } @@ -93,13 +98,14 @@ pipeline { env.RESOLVED_SOURCE_COMMIT = sourceCommit env.RESOLVED_IMAGE_TAG = imageTag env.RESOLVED_IMAGE_REPOSITORY = imageRepository + env.DEPLOY_BOTH_EVENT_BRIDGES = deployBothBridges ? 'true' : 'false' if (service == 'event-bridge-service' && params.DEPLOY) { String bridgeRegion = params.EVENT_BRIDGE_REGION?.trim() if (!['BOTH', 'SELECT', 'CN', 'OVERSEAS'].contains(bridgeRegion)) { error('EVENT_BRIDGE_REGION 只能为 BOTH、CN 或 OVERSEAS') } - if (['BOTH', 'SELECT'].contains(bridgeRegion) + if ((deployBothBridges || ['BOTH', 'SELECT'].contains(bridgeRegion)) && !['development', 'test'].contains(params.ENVIRONMENT)) { error('事件桥 BOTH 仅支持开发或测试环境;预发布和生产必须明确选择 CN 或 OVERSEAS') } @@ -197,7 +203,8 @@ pipeline { unstash 'deployment-files' echo "在目标节点 ${env.NODE_NAME} 本机部署到 ${params.ENVIRONMENT}" List bridgeRegions = env.RESOLVED_SERVICE == 'event-bridge-service' - && ['BOTH', 'SELECT'].contains(params.EVENT_BRIDGE_REGION) + && (env.DEPLOY_BOTH_EVENT_BRIDGES == 'true' + || ['BOTH', 'SELECT'].contains(params.EVENT_BRIDGE_REGION)) ? ['CN', 'OVERSEAS'] : [params.EVENT_BRIDGE_REGION] withCredentials([ diff --git a/scripts/controller-pipeline-contract.test.mjs b/scripts/controller-pipeline-contract.test.mjs index 04d4a4303..65be87496 100644 --- a/scripts/controller-pipeline-contract.test.mjs +++ b/scripts/controller-pipeline-contract.test.mjs @@ -46,5 +46,7 @@ test('coordinator defaults event bridge deployments to both non-production regio assert.match(pipeline, /\['BOTH', 'SELECT', 'CN', 'OVERSEAS'\]\.contains\(bridgeRegion\)/) assert.match(pipeline, /兼容旧 Jenkins 参数 SELECT:本次按 BOTH/) assert.match(pipeline, /事件桥 BOTH 仅支持开发或测试环境/) - assert.match(pipeline, /params\.EVENT_BRIDGE_REGION == 'BOTH' \? 'SELECT' : params\.EVENT_BRIDGE_REGION/) + assert.match(pipeline, /String downstreamImageTag = deployBothBridges[\s\S]*?\? "\$\{env\.IMAGE_TAG\}-both"/) + assert.match(pipeline, /String downstreamBridgeRegion = deployBothBridges[\s\S]*?\? 'CN'/) + assert.match(pipeline, /string\(name: 'EVENT_BRIDGE_REGION', value: downstreamBridgeRegion\)/) }) diff --git a/scripts/test-environment-pipeline-contract.test.mjs b/scripts/test-environment-pipeline-contract.test.mjs index d7897f09b..9858d6992 100644 --- a/scripts/test-environment-pipeline-contract.test.mjs +++ b/scripts/test-environment-pipeline-contract.test.mjs @@ -163,4 +163,7 @@ test('one event bridge build deploys both regional instances in development and assert.match(pipeline, /bridgeRegions\.each \{ bridgeRegion ->/) assert.match(pipeline, /EVENT_BRIDGE_REGION_OVERRIDE=\$\{bridgeRegion\}/) assert.match(pipeline, /部署事件桥实例:/) + assert.match(pipeline, /imageTag\?\.endsWith\('-both'\)/) + assert.match(pipeline, /imageTag\.substring\(0, imageTag\.length\(\) - '-both'\.length\(\)\)/) + assert.match(pipeline, /env\.DEPLOY_BOTH_EVENT_BRIDGES = deployBothBridges \? 'true' : 'false'/) })