|
@@ -1,25 +1,35 @@
|
|
|
/**
|
|
/**
|
|
|
- * 整体 / 单服务 / 多选 发版(Harbor + ACK)。
|
|
|
|
|
- *
|
|
|
|
|
- * Jenkins Job 建议名:alien-cloud-k8s-whole
|
|
|
|
|
|
|
+ * 整体 / 单服务 / 多选:仅晋升 Harbor 镜像 + 可选 ACK。
|
|
|
* Script Path:docs/jenkins/produ/whole/Jenkinsfile
|
|
* Script Path:docs/jenkins/produ/whole/Jenkinsfile
|
|
|
- *
|
|
|
|
|
- * DEPLOY_MODE:whole=七个服务全发;single=选一个;multi=勾选 MULTI_*。
|
|
|
|
|
- * 与 prod-promote-from-uat 的 whole/single/multi 语义一致,制品改为镜像而非 jar 目录。
|
|
|
|
|
*/
|
|
*/
|
|
|
-def k8s = load 'docs/jenkins/produ/_shared/k8s-produ-lib.groovy'
|
|
|
|
|
-def reg = load 'docs/jenkins/produ/_shared/service-registry.groovy'
|
|
|
|
|
|
|
+def sparseCheckoutProduShared() {
|
|
|
|
|
+ checkout scm: [
|
|
|
|
|
+ $class: 'GitSCM',
|
|
|
|
|
+ branches: scm.branches,
|
|
|
|
|
+ extensions: [
|
|
|
|
|
+ [$class: 'CloneOption', depth: 1, shallow: true, noTags: true],
|
|
|
|
|
+ [$class: 'SparseCheckoutPaths', sparseCheckoutPaths: [
|
|
|
|
|
+ [path: 'docs/jenkins/produ/_shared/'],
|
|
|
|
|
+ ]],
|
|
|
|
|
+ ],
|
|
|
|
|
+ userRemoteConfigs: scm.userRemoteConfigs,
|
|
|
|
|
+ ]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+def k8s
|
|
|
|
|
+def reg
|
|
|
|
|
|
|
|
pipeline {
|
|
pipeline {
|
|
|
agent any
|
|
agent any
|
|
|
options {
|
|
options {
|
|
|
buildDiscarder(logRotator(numToKeepStr: '15'))
|
|
buildDiscarder(logRotator(numToKeepStr: '15'))
|
|
|
|
|
+ disableConcurrentBuilds()
|
|
|
timestamps()
|
|
timestamps()
|
|
|
- timeout(time: 180, unit: 'MINUTES')
|
|
|
|
|
|
|
+ timeout(time: 120, unit: 'MINUTES')
|
|
|
}
|
|
}
|
|
|
parameters {
|
|
parameters {
|
|
|
choice(name: 'DEPLOY_MODE', choices: ['whole', 'single', 'multi'],
|
|
choice(name: 'DEPLOY_MODE', choices: ['whole', 'single', 'multi'],
|
|
|
- description: 'whole=全部七个 Java 服务;single=一个;multi=勾选下方复选框')
|
|
|
|
|
|
|
+ description: 'whole=7个服务;single=选一个;multi=勾选 MULTI_*')
|
|
|
choice(name: 'SINGLE_SERVICE', choices: [
|
|
choice(name: 'SINGLE_SERVICE', choices: [
|
|
|
'gateway', 'store', 'second', 'store-platform', 'lawyer', 'job', 'dining',
|
|
'gateway', 'store', 'second', 'store-platform', 'lawyer', 'job', 'dining',
|
|
|
], description: '仅 DEPLOY_MODE=single 时生效')
|
|
], description: '仅 DEPLOY_MODE=single 时生效')
|
|
@@ -30,76 +40,79 @@ pipeline {
|
|
|
booleanParam(name: 'MULTI_lawyer', defaultValue: false)
|
|
booleanParam(name: 'MULTI_lawyer', defaultValue: false)
|
|
|
booleanParam(name: 'MULTI_job', defaultValue: false)
|
|
booleanParam(name: 'MULTI_job', defaultValue: false)
|
|
|
booleanParam(name: 'MULTI_dining', defaultValue: false)
|
|
booleanParam(name: 'MULTI_dining', defaultValue: false)
|
|
|
- string(name: 'GIT_BRANCH', defaultValue: 'uat-20260202', trim: true)
|
|
|
|
|
- string(name: 'IMAGE_TAG', defaultValue: '', trim: true,
|
|
|
|
|
- description: '留空则各服务 tag 均为 build-${BUILD_NUMBER}')
|
|
|
|
|
- choice(name: 'DEPLOY_STRATEGY', choices: ['rolling', 'canary'])
|
|
|
|
|
- string(name: 'CANARY_WEIGHT', defaultValue: '10', trim: true)
|
|
|
|
|
- string(name: 'HARBOR_REGISTRY', defaultValue: '39.106.135.88', trim: true)
|
|
|
|
|
|
|
+ string(name: 'SOURCE_TAG', defaultValue: 'uat-latest', trim: true,
|
|
|
|
|
+ description: '七个服务共用的预生产 Harbor tag')
|
|
|
|
|
+ string(name: 'TARGET_TAG', defaultValue: '', trim: true,
|
|
|
|
|
+ description: '留空则 produ-${BUILD_NUMBER}')
|
|
|
|
|
+ string(name: 'HARBOR_REGISTRY', defaultValue: '39.105.153.68', trim: true)
|
|
|
string(name: 'HARBOR_PROJECT', defaultValue: 'alien_cloud', trim: true)
|
|
string(name: 'HARBOR_PROJECT', defaultValue: 'alien_cloud', trim: true)
|
|
|
- string(name: 'BASE_IMAGE', defaultValue: '39.106.135.88/alien_cloud/base/openjdk8-ffmpeg:v1', trim: true)
|
|
|
|
|
|
|
+ choice(name: 'DEPLOY_STRATEGY', choices: ['rolling', 'canary', 'skip'],
|
|
|
|
|
+ description: 'skip=只晋升 Harbor,不 kubectl')
|
|
|
|
|
+ string(name: 'CANARY_WEIGHT', defaultValue: '10', trim: true)
|
|
|
string(name: 'K8S_NAMESPACE', defaultValue: 'alien-produ', trim: true)
|
|
string(name: 'K8S_NAMESPACE', defaultValue: 'alien-produ', trim: true)
|
|
|
- booleanParam(name: 'SKIP_MAVEN', defaultValue: false)
|
|
|
|
|
booleanParam(name: 'DRY_RUN', defaultValue: false)
|
|
booleanParam(name: 'DRY_RUN', defaultValue: false)
|
|
|
}
|
|
}
|
|
|
environment {
|
|
environment {
|
|
|
- MAVEN_HOME = tool '3.6.3'
|
|
|
|
|
- PATH = "${MAVEN_HOME}/bin:${env.PATH}"
|
|
|
|
|
- GIT_URL = 'http://8.152.195.41:3000/alien/alien_cloud'
|
|
|
|
|
- GIT_CREDENTIALS = 'zhanghaomimapingzheng'
|
|
|
|
|
HARBOR_CREDENTIALS = 'harbor-robot-alien'
|
|
HARBOR_CREDENTIALS = 'harbor-robot-alien'
|
|
|
KUBECONFIG_CREDENTIALS = 'ack-kubeconfig-alien'
|
|
KUBECONFIG_CREDENTIALS = 'ack-kubeconfig-alien'
|
|
|
}
|
|
}
|
|
|
stages {
|
|
stages {
|
|
|
- stage('Checkout') {
|
|
|
|
|
|
|
+ stage('Plan') {
|
|
|
steps {
|
|
steps {
|
|
|
script {
|
|
script {
|
|
|
- def branch = (params.GIT_BRANCH ?: 'uat-20260202').trim()
|
|
|
|
|
- k8s.checkoutBranch(this, branch, env.GIT_URL, env.GIT_CREDENTIALS)
|
|
|
|
|
- env.SELECTED_SERVICES = reg.filterServices(reg.getServiceRegistry(), params)*.prodDir.join(',')
|
|
|
|
|
- echo ">>> 本次发版服务: ${env.SELECTED_SERVICES}"
|
|
|
|
|
|
|
+ sparseCheckoutProduShared()
|
|
|
|
|
+ k8s = load 'docs/jenkins/produ/_shared/k8s-produ-lib.groovy'
|
|
|
|
|
+ reg = load 'docs/jenkins/produ/_shared/service-registry.groovy'
|
|
|
|
|
+ def services = reg.filterServices(reg.getServiceRegistry(), params)
|
|
|
|
|
+ env.PROMOTE_LIST = services*.prodDir.join(',')
|
|
|
|
|
+ env.TARGET_TAG_RESOLVED = k8s.resolveTargetTag(this, params.TARGET_TAG)
|
|
|
|
|
+ echo ">>> DEPLOY_MODE=${params.DEPLOY_MODE} 服务=${env.PROMOTE_LIST}"
|
|
|
|
|
+ echo ">>> ${params.SOURCE_TAG} → ${env.TARGET_TAG_RESOLVED}"
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- stage('Maven Package (all modules)') {
|
|
|
|
|
- when { expression { return !params.SKIP_MAVEN } }
|
|
|
|
|
- steps {
|
|
|
|
|
- script { k8s.mavenPackageAll(this) }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- stage('Build Push & Deploy') {
|
|
|
|
|
|
|
+ stage('Promote images') {
|
|
|
steps {
|
|
steps {
|
|
|
script {
|
|
script {
|
|
|
def services = reg.filterServices(reg.getServiceRegistry(), params)
|
|
def services = reg.filterServices(reg.getServiceRegistry(), params)
|
|
|
- def tag = (params.IMAGE_TAG ?: '').trim() ?: "build-${env.BUILD_NUMBER}"
|
|
|
|
|
- def common = [
|
|
|
|
|
|
|
+ k8s.promoteHarborImages(this, services, [
|
|
|
harborRegistry: params.HARBOR_REGISTRY,
|
|
harborRegistry: params.HARBOR_REGISTRY,
|
|
|
harborProject: params.HARBOR_PROJECT,
|
|
harborProject: params.HARBOR_PROJECT,
|
|
|
- baseImage: params.BASE_IMAGE,
|
|
|
|
|
|
|
+ sourceTag: params.SOURCE_TAG,
|
|
|
|
|
+ targetTag: env.TARGET_TAG_RESOLVED,
|
|
|
harborCredentialsId: env.HARBOR_CREDENTIALS,
|
|
harborCredentialsId: env.HARBOR_CREDENTIALS,
|
|
|
- k8sNamespace: params.K8S_NAMESPACE,
|
|
|
|
|
- deployStrategy: params.DEPLOY_STRATEGY,
|
|
|
|
|
- canaryWeight: (params.CANARY_WEIGHT ?: '10').trim(),
|
|
|
|
|
- kubeCredentialsId: env.KUBECONFIG_CREDENTIALS,
|
|
|
|
|
- ]
|
|
|
|
|
- services.each { svc ->
|
|
|
|
|
- def imageRef = "${params.HARBOR_REGISTRY}/${params.HARBOR_PROJECT}/${svc.prodDir}:${tag}"
|
|
|
|
|
- echo ">>> === ${svc.prodDir} === ${imageRef}"
|
|
|
|
|
- if (!params.DRY_RUN) {
|
|
|
|
|
- k8s.dockerBuildAndPush(this, svc + common + [imageRef: imageRef])
|
|
|
|
|
- k8s.deployToAck(this, svc + common + [
|
|
|
|
|
- imageRef: imageRef,
|
|
|
|
|
- deploymentStable: svc.deployName,
|
|
|
|
|
- deploymentCanary: "${svc.deployName}-canary",
|
|
|
|
|
- ingressCanary: "${svc.deployName}-canary",
|
|
|
|
|
- ])
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ dryRun: params.DRY_RUN == true,
|
|
|
|
|
+ ])
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ stage('Deploy to ACK') {
|
|
|
|
|
+ when { expression { return params.DEPLOY_STRATEGY != 'skip' && !params.DRY_RUN } }
|
|
|
|
|
+ steps {
|
|
|
|
|
+ script {
|
|
|
|
|
+ def services = reg.filterServices(reg.getServiceRegistry(), params)
|
|
|
|
|
+ def regHost = params.HARBOR_REGISTRY.trim()
|
|
|
|
|
+ def proj = params.HARBOR_PROJECT.trim()
|
|
|
|
|
+ def tgtTag = env.TARGET_TAG_RESOLVED
|
|
|
|
|
+ def strategy = params.DEPLOY_STRATEGY
|
|
|
|
|
+ services.each { s ->
|
|
|
|
|
+ def imageRef = "${regHost}/${proj}/${s.prodDir}:${tgtTag}"
|
|
|
|
|
+ k8s.deployToAck(this, [
|
|
|
|
|
+ k8sNamespace: params.K8S_NAMESPACE,
|
|
|
|
|
+ imageRef: imageRef,
|
|
|
|
|
+ deployStrategy: strategy == 'canary' ? 'canary' : 'rolling',
|
|
|
|
|
+ deploymentStable: s.deployName,
|
|
|
|
|
+ deploymentCanary: "${s.deployName}-canary",
|
|
|
|
|
+ ingressCanary: "${s.deployName}-canary",
|
|
|
|
|
+ canaryWeight: (params.CANARY_WEIGHT ?: '10').trim(),
|
|
|
|
|
+ kubeCredentialsId: env.KUBECONFIG_CREDENTIALS,
|
|
|
|
|
+ ])
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
post {
|
|
post {
|
|
|
- success { echo ">>> 整体流水线完成: ${env.SELECTED_SERVICES}" }
|
|
|
|
|
|
|
+ success { echo ">>> 完成: ${env.PROMOTE_LIST} tag=${env.TARGET_TAG_RESOLVED}" }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|