Jenkinsfile 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * 整体 / 单服务 / 多选:仅晋升 Harbor 镜像 + 可选 ACK。
  3. * Script Path:docs/jenkins/produ/whole/Jenkinsfile
  4. *
  5. * 注意:load / checkout 必须在 agent 的 stage 内执行,禁止在 pipeline 外顶层 load。
  6. */
  7. def sparseCheckoutProduShared() {
  8. checkout scm: [
  9. $class: 'GitSCM',
  10. branches: scm.branches,
  11. extensions: [
  12. [$class: 'CloneOption', depth: 1, shallow: true, noTags: true],
  13. [$class: 'SparseCheckoutPaths', sparseCheckoutPaths: [
  14. [path: 'docs/jenkins/produ/_shared/'],
  15. ]],
  16. ],
  17. userRemoteConfigs: scm.userRemoteConfigs,
  18. ]
  19. }
  20. /** 在 node 内稀疏检出并加载共享库(每个 stage 可重复调用) */
  21. def getProduLibs() {
  22. sparseCheckoutProduShared()
  23. def k8s = load 'docs/jenkins/produ/_shared/k8s-produ-lib.groovy'
  24. def reg = load 'docs/jenkins/produ/_shared/service-registry.groovy'
  25. return [k8s, reg]
  26. }
  27. pipeline {
  28. agent any
  29. options {
  30. buildDiscarder(logRotator(numToKeepStr: '15'))
  31. disableConcurrentBuilds()
  32. timestamps()
  33. timeout(time: 120, unit: 'MINUTES')
  34. }
  35. parameters {
  36. choice(name: 'DEPLOY_MODE', choices: ['whole', 'single', 'multi'],
  37. description: 'whole=7个服务;single=选一个;multi=勾选 MULTI_*')
  38. choice(name: 'SINGLE_SERVICE', choices: [
  39. 'gateway', 'store', 'second', 'store-platform', 'lawyer', 'job', 'dining',
  40. ], description: '仅 DEPLOY_MODE=single 时生效')
  41. booleanParam(name: 'MULTI_gateway', defaultValue: false)
  42. booleanParam(name: 'MULTI_store', defaultValue: false)
  43. booleanParam(name: 'MULTI_second', defaultValue: false)
  44. booleanParam(name: 'MULTI_store_platform', defaultValue: false)
  45. booleanParam(name: 'MULTI_lawyer', defaultValue: false)
  46. booleanParam(name: 'MULTI_job', defaultValue: false)
  47. booleanParam(name: 'MULTI_dining', defaultValue: false)
  48. string(name: 'SOURCE_TAG', defaultValue: 'uat-latest', trim: true,
  49. description: 'Harbor UAT tag,默认 uat-latest;回滚填 uat-build-<N>')
  50. string(name: 'TARGET_TAG', defaultValue: '', trim: true,
  51. description: '留空则 produ-${BUILD_NUMBER}')
  52. string(name: 'HARBOR_REGISTRY', defaultValue: '39.105.153.68', trim: true)
  53. string(name: 'HARBOR_PROJECT', defaultValue: 'alien_cloud', trim: true)
  54. choice(name: 'DEPLOY_STRATEGY', choices: ['rolling', 'canary', 'skip'],
  55. description: 'skip=只晋升 Harbor,不 kubectl')
  56. string(name: 'CANARY_WEIGHT', defaultValue: '10', trim: true)
  57. string(name: 'K8S_NAMESPACE', defaultValue: 'alien-produ', trim: true)
  58. booleanParam(name: 'DRY_RUN', defaultValue: false)
  59. }
  60. environment {
  61. HARBOR_CREDENTIALS = 'harbor-robot-alien'
  62. KUBECONFIG_CREDENTIALS = 'ack-kubeconfig-alien'
  63. }
  64. stages {
  65. stage('Plan') {
  66. steps {
  67. script {
  68. def (k8s, reg) = getProduLibs()
  69. def services = reg.filterServices(reg.getServiceRegistry(), params)
  70. def srcTag = k8s.requireSourceTag(this, params.SOURCE_TAG)
  71. env.PROMOTE_LIST = services*.prodDir.join(',')
  72. env.TARGET_TAG_RESOLVED = k8s.resolveTargetTag(this, params.TARGET_TAG)
  73. echo ">>> DEPLOY_MODE=${params.DEPLOY_MODE} 服务=${env.PROMOTE_LIST}"
  74. echo ">>> ${srcTag} → ${env.TARGET_TAG_RESOLVED}"
  75. }
  76. }
  77. }
  78. stage('Promote images') {
  79. steps {
  80. script {
  81. def (k8s, reg) = getProduLibs()
  82. def services = reg.filterServices(reg.getServiceRegistry(), params)
  83. k8s.promoteHarborImages(this, services, [
  84. harborRegistry: params.HARBOR_REGISTRY,
  85. harborProject: params.HARBOR_PROJECT,
  86. sourceTag: params.SOURCE_TAG,
  87. targetTag: env.TARGET_TAG_RESOLVED,
  88. harborCredentialsId: env.HARBOR_CREDENTIALS,
  89. dryRun: params.DRY_RUN == true,
  90. ])
  91. }
  92. }
  93. }
  94. stage('Deploy to ACK') {
  95. when { expression { return params.DEPLOY_STRATEGY != 'skip' && !params.DRY_RUN } }
  96. steps {
  97. script {
  98. def (k8s, reg) = getProduLibs()
  99. def services = reg.filterServices(reg.getServiceRegistry(), params)
  100. def regHost = params.HARBOR_REGISTRY.trim()
  101. def proj = params.HARBOR_PROJECT.trim()
  102. def tgtTag = env.TARGET_TAG_RESOLVED
  103. def strategy = params.DEPLOY_STRATEGY
  104. services.each { s ->
  105. def imageRef = "${regHost}/${proj}/${s.prodDir}:${tgtTag}"
  106. k8s.deployToAck(this, [
  107. k8sNamespace: params.K8S_NAMESPACE,
  108. imageRef: imageRef,
  109. deployStrategy: strategy == 'canary' ? 'canary' : 'rolling',
  110. deploymentStable: s.deployName,
  111. deploymentCanary: "${s.deployName}-canary",
  112. ingressCanary: "${s.deployName}-canary",
  113. canaryWeight: (params.CANARY_WEIGHT ?: '10').trim(),
  114. kubeCredentialsId: env.KUBECONFIG_CREDENTIALS,
  115. ])
  116. }
  117. }
  118. }
  119. }
  120. }
  121. post {
  122. success { echo ">>> 完成: ${env.PROMOTE_LIST} tag=${env.TARGET_TAG_RESOLVED}" }
  123. }
  124. }