Jenkinsfile-uat-build-deploy.groovy 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /**
  2. * UAT: Checkout -> Maven -> (optional) push images to Harbor -> deploy jar + docker restart.
  3. *
  4. * Jenkins Job: Pipeline script from SCM
  5. * Script Path: docs/jenkins/Jenkinsfile-uat-build-deploy.groovy
  6. *
  7. * Harbor (153.68): when PUSH_TO_HARBOR=true, push e.g.
  8. * 39.105.153.68/alien_cloud/gateway:uat-build-<BUILD_NUMBER>
  9. * Production promote jobs use SOURCE_TAG=uat-build-<same number>.
  10. */
  11. /** HARBOR_PUSH_SCOPE: all-java-services | <repo>-only */
  12. def filterHarborPushScope(List allServices, String scope) {
  13. def s = (scope ?: 'all-java-services').trim()
  14. if (s == 'all-java-services') {
  15. return allServices
  16. }
  17. if (s.endsWith('-only')) {
  18. def repo = s.substring(0, s.length() - '-only'.length())
  19. def picked = allServices.findAll { it.repo == repo }
  20. if (picked.isEmpty()) {
  21. error("Unknown HARBOR_PUSH_SCOPE: ${scope}")
  22. }
  23. return picked
  24. }
  25. error("Unknown HARBOR_PUSH_SCOPE: ${scope}")
  26. }
  27. pipeline {
  28. agent any
  29. options {
  30. buildDiscarder(logRotator(numToKeepStr: '15'))
  31. timestamps()
  32. timeout(time: 90, unit: 'MINUTES')
  33. }
  34. parameters {
  35. string(
  36. name: 'GIT_BRANCH',
  37. defaultValue: 'uat-20260202',
  38. trim: true,
  39. description: 'Git branch, must match remote (e.g. uat-20260202)'
  40. )
  41. booleanParam(name: 'FORCE_UPDATE', defaultValue: true, description: 'mvn -U')
  42. booleanParam(name: 'ALLOW_SNAPSHOTS', defaultValue: true, description: 'allow SNAPSHOT deps')
  43. booleanParam(
  44. name: 'PUSH_TO_HARBOR',
  45. defaultValue: false,
  46. description: 'After Maven: docker build + push to 39.105.153.68/alien_cloud (tag uat-build-<BUILD_NUMBER>)'
  47. )
  48. choice(
  49. name: 'HARBOR_PUSH_SCOPE',
  50. choices: [
  51. 'all-java-services',
  52. 'gateway-only',
  53. 'store-only',
  54. 'second-only',
  55. 'store-platform-only',
  56. 'lawyer-only',
  57. 'job-only',
  58. 'dining-only',
  59. ],
  60. description: 'Only when PUSH_TO_HARBOR=true; default=all seven; *-only=one service'
  61. )
  62. string(name: 'HARBOR_REGISTRY', defaultValue: '39.105.153.68', trim: true)
  63. string(name: 'HARBOR_PROJECT', defaultValue: 'alien_cloud', trim: true)
  64. }
  65. environment {
  66. MAVEN_HOME = tool '3.6.3'
  67. PATH = "${MAVEN_HOME}/bin:${env.PATH}"
  68. GIT_URL = 'http://8.152.195.41:3000/alien/alien_cloud'
  69. GIT_CREDENTIALS = 'zhanghaomimapingzheng'
  70. HARBOR_CREDENTIALS = 'harbor-robot-alien'
  71. UAT_HARBOR_IMAGE_TAG = "uat-build-${env.BUILD_NUMBER}"
  72. DOCKERFILE_JAVA = 'docs/jenkins/produ/docker/Dockerfile.java-service'
  73. }
  74. stages {
  75. stage('Checkout') {
  76. steps {
  77. script {
  78. def branch = (params.GIT_BRANCH ?: 'uat-20260202').trim()
  79. if (!branch) {
  80. error('GIT_BRANCH is required')
  81. }
  82. env.GIT_BRANCH = branch
  83. echo ">>> Checkout branch: ${env.GIT_BRANCH}"
  84. git branch: "${env.GIT_BRANCH}",
  85. credentialsId: "${env.GIT_CREDENTIALS}",
  86. url: "${env.GIT_URL}"
  87. sh """
  88. set -e
  89. git fetch origin
  90. git reset --hard origin/${env.GIT_BRANCH}
  91. git log -1 --oneline
  92. """
  93. }
  94. }
  95. }
  96. stage('Prepare Maven Settings') {
  97. steps {
  98. script {
  99. writeFile file: 'settings.xml', text: """<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  100. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  101. xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
  102. <profiles>
  103. <profile>
  104. <id>repo-mix</id>
  105. <repositories>
  106. <repository>
  107. <id>central</id>
  108. <name>Maven Central</name>
  109. <url>https://repo.maven.apache.org/maven2</url>
  110. <releases><enabled>true</enabled><updatePolicy>always</updatePolicy></releases>
  111. <snapshots><enabled>false</enabled></snapshots>
  112. </repository>
  113. <repository>
  114. <id>spring-milestones</id>
  115. <name>Spring Milestones</name>
  116. <url>https://repo.spring.io/milestone</url>
  117. <releases><enabled>true</enabled><updatePolicy>always</updatePolicy></releases>
  118. <snapshots><enabled>false</enabled></snapshots>
  119. </repository>
  120. <repository>
  121. <id>spring-snapshots</id>
  122. <name>Spring Snapshots</name>
  123. <url>https://repo.spring.io/snapshot</url>
  124. <releases><enabled>false</enabled></releases>
  125. <snapshots><enabled>true</enabled><updatePolicy>always</updatePolicy></snapshots>
  126. </repository>
  127. </repositories>
  128. <pluginRepositories>
  129. <pluginRepository>
  130. <id>central</id>
  131. <url>https://repo.maven.apache.org/maven2</url>
  132. <releases><enabled>true</enabled></releases>
  133. <snapshots><enabled>false</enabled></snapshots>
  134. </pluginRepository>
  135. <pluginRepository>
  136. <id>spring-milestones</id>
  137. <url>https://repo.spring.io/milestone</url>
  138. <releases><enabled>true</enabled></releases>
  139. <snapshots><enabled>false</enabled></snapshots>
  140. </pluginRepository>
  141. </pluginRepositories>
  142. </profile>
  143. </profiles>
  144. <activeProfiles>
  145. <activeProfile>repo-mix</activeProfile>
  146. </activeProfiles>
  147. </settings>
  148. """
  149. }
  150. }
  151. }
  152. stage('Maven Build') {
  153. steps {
  154. script {
  155. def updateFlag = params.FORCE_UPDATE ? '-U' : ''
  156. retry(2) {
  157. sh """
  158. set -e
  159. mvn -version
  160. unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY all_proxy no_proxy NO_PROXY || true
  161. export MAVEN_OPTS="-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true"
  162. rm -rf /root/.m2/repository/org/springframework/cloud/spring-cloud-dependencies/Hoxton.SR1 || true
  163. rm -rf /root/.m2/repository/org/springframework/boot/spring-boot-dependencies/2.3.2.RELEASE || true
  164. rm -rf ${WORKSPACE}/.m2/repository/org/springframework/cloud/spring-cloud-dependencies/Hoxton.SR1 || true
  165. rm -rf ${WORKSPACE}/.m2/repository/org/springframework/boot/spring-boot-dependencies/2.3.2.RELEASE || true
  166. mvn clean package -DskipTests -s settings.xml ${updateFlag} -e -Dmaven.repo.local=${WORKSPACE}/.m2/repository
  167. """
  168. }
  169. }
  170. }
  171. }
  172. stage('Push images to Harbor') {
  173. when {
  174. expression { return params.PUSH_TO_HARBOR == true }
  175. }
  176. steps {
  177. script {
  178. def reg = params.HARBOR_REGISTRY.trim()
  179. def proj = params.HARBOR_PROJECT.trim()
  180. def tag = env.UAT_HARBOR_IMAGE_TAG
  181. def baseImage = "${reg}/${proj}/base/openjdk8-ffmpeg:v1"
  182. def dockerfile = env.DOCKERFILE_JAVA
  183. def allHarborServices = [
  184. [module: 'alien-gateway', repo: 'gateway', port: '8000', withLib: false],
  185. [module: 'alien-store', repo: 'store', port: '50014', withLib: true],
  186. [module: 'alien-second', repo: 'second', port: '50015', withLib: false],
  187. [module: 'alien-store-platform', repo: 'store-platform', port: '50016', withLib: false],
  188. [module: 'alien-lawyer', repo: 'lawyer', port: '50017', withLib: true],
  189. [module: 'alien-job', repo: 'job', port: '50108', withLib: false],
  190. [module: 'alien-dining', repo: 'dining', port: '50019', withLib: false],
  191. ]
  192. def harborServices = filterHarborPushScope(allHarborServices, params.HARBOR_PUSH_SCOPE)
  193. echo ">>> HARBOR_PUSH_SCOPE=${params.HARBOR_PUSH_SCOPE} repos=${harborServices*.repo.join(',')}"
  194. withCredentials([usernamePassword(
  195. credentialsId: env.HARBOR_CREDENTIALS,
  196. usernameVariable: 'HARBOR_USER',
  197. passwordVariable: 'HARBOR_PASS',
  198. )]) {
  199. sh """
  200. set -e
  201. echo "\${HARBOR_PASS}" | docker login ${reg} -u "\${HARBOR_USER}" --password-stdin
  202. """
  203. harborServices.each { svc ->
  204. def jarName = "${svc.module}-1.0.0.jar"
  205. def imageRef = "${reg}/${proj}/${svc.repo}:${tag}"
  206. sh """
  207. set -e
  208. test -f ${WORKSPACE}/${svc.module}/target/${jarName}
  209. cd ${WORKSPACE}/${svc.module}
  210. rm -rf .jenkins_docker_ctx && mkdir -p .jenkins_docker_ctx/lib
  211. cp -f target/${jarName} .jenkins_docker_ctx/${jarName}
  212. if [ -d target/lib ]; then
  213. cp -rf target/lib/. .jenkins_docker_ctx/lib/
  214. else
  215. touch .jenkins_docker_ctx/lib/.keep
  216. fi
  217. cd .jenkins_docker_ctx
  218. docker build -f ${WORKSPACE}/${dockerfile} \\
  219. --build-arg BASE_IMAGE=${baseImage} \\
  220. --build-arg JAR_FILE=${jarName} \\
  221. --build-arg SERVER_PORT=${svc.port} \\
  222. --build-arg WITH_LIB=${svc.withLib} \\
  223. -t ${imageRef} .
  224. docker push ${imageRef}
  225. echo ">>> pushed ${imageRef}"
  226. """
  227. }
  228. }
  229. echo ">>> Harbor tag for prod promote: SOURCE_TAG=${tag}"
  230. }
  231. }
  232. }
  233. stage('Deploy Services') {
  234. steps {
  235. script {
  236. def services = [
  237. 'alien-gateway:gateway-uat',
  238. 'alien-job:job-uat',
  239. 'alien-lawyer:lawyer-uat',
  240. 'alien-second:second-uat',
  241. 'alien-store:store-uat',
  242. 'alien-dining:dining-uat',
  243. 'alien-store-platform:store-platform-uat',
  244. ]
  245. for (item in services) {
  246. def parts = item.split(':')
  247. def moduleName = parts[0]
  248. def dirName = parts[1]
  249. def sourceJar = "${env.WORKSPACE}/${moduleName}/target/${moduleName}-1.0.0.jar"
  250. def sourceLib = "${env.WORKSPACE}/${moduleName}/target/lib"
  251. def targetDir = "/app_deploy_uat/${dirName}"
  252. sh """
  253. set -e
  254. echo ">>> Deploy module: ${moduleName}"
  255. if [ -f "${sourceJar}" ]; then
  256. mkdir -p "${targetDir}"
  257. if [ -d "${sourceLib}" ]; then
  258. rm -rf "${targetDir}/lib"
  259. cp -rf "${sourceLib}" "${targetDir}"
  260. fi
  261. cp -f "${sourceJar}" "${targetDir}/"
  262. if docker ps -a --format '{{.Names}}' | grep -wq "${dirName}"; then
  263. docker restart "${dirName}"
  264. echo ">>> [${dirName}] restarted"
  265. else
  266. echo ">>> [${dirName}] container missing, jar copied only"
  267. fi
  268. else
  269. echo ">>> [${dirName}] jar missing, skip"
  270. fi
  271. """
  272. }
  273. }
  274. }
  275. }
  276. }
  277. post {
  278. always {
  279. sh 'rm -f settings.xml || true'
  280. script {
  281. if (!params.PUSH_TO_HARBOR) {
  282. echo '>>> Harbor push SKIPPED: PUSH_TO_HARBOR is false. On "Build with Parameters" check PUSH_TO_HARBOR.'
  283. }
  284. }
  285. }
  286. success {
  287. script {
  288. if (params.PUSH_TO_HARBOR) {
  289. echo ">>> Harbor images tagged: ${env.UAT_HARBOR_IMAGE_TAG}"
  290. echo ">>> Prod promote: SOURCE_TAG=${env.UAT_HARBOR_IMAGE_TAG}"
  291. }
  292. }
  293. }
  294. }
  295. }