Jenkinsfile 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. properties([
  2. parameters([
  3. [$class: 'ChoiceParameter',
  4. choiceType: 'PT_SINGLE_SELECT',
  5. description: '选择要部署 API or UI',
  6. name: 'modulePrefix',
  7. randomName: 'choice-parameter-5631314439613978',
  8. script: [
  9. $class: 'GroovyScript',
  10. fallbackScript: [
  11. classpath: [],
  12. sandbox: true,
  13. script:
  14. 'return[\'Could not get Env\']'
  15. ],
  16. script: [
  17. classpath: [],
  18. sandbox: true,
  19. script:
  20. 'return["java"]'
  21. ]
  22. ]
  23. ],
  24. [$class: 'CascadeChoiceParameter',
  25. choiceType: 'PT_SINGLE_SELECT',
  26. description: '选择要部署的项目',
  27. name: 'module',
  28. randomName: 'choice-parameter-5631314456178619',
  29. referencedParameters: 'modulePrefix',
  30. script: [
  31. $class: 'GroovyScript',
  32. fallbackScript: [
  33. classpath: [],
  34. sandbox: true,
  35. script:
  36. 'return[\'Could not get Environment from Env Param\']'
  37. ],
  38. script: [
  39. classpath: [],
  40. sandbox: true,
  41. script:
  42. 'return["storlead-api"]'
  43. ]
  44. ]
  45. ]
  46. ])
  47. ])
  48. pipeline {
  49. options {
  50. timestamps()
  51. }
  52. environment {
  53. GROUPID = readMavenPom().getGroupId()//com.storlead
  54. ARTIFACTID = readMavenPom().getArtifactId()//sp-project
  55. VERSION = readMavenPom().getVersion()//1.0
  56. }
  57. // 参数
  58. parameters {
  59. choice(
  60. name: 'profile',
  61. choices: ['test', 'prod','uat'],
  62. description: '选择要部署的配置文件'
  63. )
  64. }
  65. agent any
  66. stages {
  67. stage('处理参数') {
  68. steps {
  69. script {
  70. echo "处理参数"
  71. script {
  72. //服务器配置
  73. MODULE_PREFIX = "${params.modulePrefix}"
  74. SERVER_SSH_PORT = 53023
  75. SERVER_HOST = "node1.storlead.com"
  76. SWARM_INIT_REPLICAS_NUM = 1
  77. //服务配置
  78. API_PORT = 9200
  79. API_REMOTE_DEBUG_PORT = 9201
  80. API_NAMESPACE_RESTFUL = "${params.module}"
  81. //DOCKER配置
  82. DOCKER_REGISTRY = "reg-aliyun"
  83. DOCKER_HOST = "registry.cn-shenzhen.aliyuncs.com"
  84. //Docker私服登陆url https://registry-vpc.cn-shenzhen.aliyuncs.com
  85. DOCKER_LOGIN_REGISTRY = "https://${DOCKER_HOST}"
  86. BUILD_PREFIX = "storlead-huawei"
  87. //镜像完整名称 registry-vpc.cn-shenzhen.aliyuncs.com/storlead/sp-project-management-prod:1.0
  88. DOCKER_IMG_NAME = "${DOCKER_HOST}/${BUILD_PREFIX}/${params.module}-${params.profile}:${VERSION}"
  89. //镜像名 storlead/sp-project-management-prod:1.0
  90. IMG_NAME = "${BUILD_PREFIX}/${params.module}-${params.profile}:${VERSION}"
  91. PUSH_DOCK_IMG = true
  92. SERVER_HOST_NAME = "test1"
  93. echo "为指定 module 设定对应 服务器及端口"
  94. echo "处理 ${params.module} 项目"
  95. if (params.modulePrefix == "java") {
  96. echo "---- storelad-centre-api"
  97. script {
  98. if (params.profile == "test") {
  99. SWARM_INIT_REPLICAS_NUM = 1
  100. SERVER_HOST = "test1.storlead.com"
  101. API_PORT = 18060
  102. API_REMOTE_DEBUG_PORT = 18061
  103. SERVER_HOST_NAME = "test1"
  104. } else if (params.profile == "prod") {
  105. SERVER_HOST = "110.41.82.21"
  106. API_PORT = 18060
  107. API_REMOTE_DEBUG_PORT = 18061
  108. SERVER_HOST_NAME = "node1"
  109. }
  110. }
  111. } else if (params.modulePrefix == "ui") {
  112. script {
  113. if (params.profile == "test") {
  114. SERVER_HOST = "test1.storlead.com"
  115. } else if (params.profile == "prod") {
  116. SERVER_HOST = "110.41.82.21"
  117. }
  118. }
  119. }
  120. echo "处理MODULE_NAMESPACE_RESTFUL"
  121. // //把 module 名 从 sp-xxx 变成 xxx 也就是 项目 的 namespace
  122. //if (API_NAMESPACE_RESTFUL == "storlead-mail-api") {
  123. API_NAMESPACE_RESTFUL = "api"
  124. //}
  125. echo "处理镜像推送"
  126. }
  127. }
  128. }
  129. }
  130. // stage('Node 编译') {
  131. //
  132. // when {
  133. // environment name: 'modulePrefix', value: 'ui'
  134. // }
  135. // agent {
  136. // docker {
  137. // // image "registry-vpc.cn-shenzhen.aliyuncs.com/storlead/node:19-alpine"
  138. // image "node:20-alpine"
  139. // args '-v /app:/app/:z -v /etc/localtime:/etc/localtime:ro -u root'
  140. // reuseNode true
  141. // }
  142. // }
  143. // steps {
  144. // withCredentials([
  145. // usernamePassword(credentialsId: 'storleadHW', usernameVariable: 'usernameHW', passwordVariable: 'passwordHW'),
  146. // usernamePassword(credentialsId: 'storlead', usernameVariable: 'username', passwordVariable: 'password')
  147. // ]) {
  148. // script {
  149. // echo "发布 UI 代码"
  150. //
  151. // def remote = [:]
  152. // remote.allowAnyHosts = true
  153. // remote.name = "${SERVER_HOST}"
  154. // remote.host = "${SERVER_HOST}"
  155. // remote.port = 53023
  156. // remote.user = username
  157. // remote.password = password
  158. //
  159. // if (params.profile == "prod") {
  160. // remote.port = 22
  161. // remote.user = "root"
  162. // remote.user = usernameHW
  163. // remote.password = passwordHW
  164. // }
  165. // if(params.module == 'sp-user-mobile-center') {
  166. // sh """cd ${params.modulePrefix}/${params.module} && npm install && npm run build:${params.profile}"""
  167. // } else {
  168. // sh """cd ${params.modulePrefix}/${params.module} && npm install && npm run ${params.profile}"""
  169. // }
  170. //
  171. // // sh """cd ${params.modulePrefix}/${params.module} && npm run ${params.profile}"""
  172. //
  173. // sshCommand remote: remote, command: "mkdir -p /app/sp/ui/app-centre/${params.profile}/${params.module}"
  174. //
  175. // sshCommand remote: remote, command: "rm -rf /app/sp/ui/app-centre/${params.profile}/${params.module}/dist/*"
  176. //
  177. //
  178. // echo "/app/sp/ui/sales/${params.profile}/${params.module}/*"
  179. //
  180. // sshPut remote: remote, from: "${params.modulePrefix}/${params.module}/dist/", into: "/app/sp/ui/app-centre/${params.profile}/${params.module}/"
  181. //
  182. // echo "${params.modulePrefix}/${params.module}/dist/,/app/sp/ui/app-centre/${params.profile}/${params.module}/"
  183. //
  184. // sshCommand remote: remote, command: "cp -rf /app/sp/ui/app-centre/${params.profile}/${params.module}/dist/* /app/sp/ui/app-centre/${params.profile}/${params.module}/"
  185. // }
  186. // }
  187. // }
  188. // }
  189. stage('Maven 编译') {
  190. when {
  191. environment name: 'modulePrefix', value: 'java'
  192. }
  193. agent {
  194. docker {
  195. image 'maven:3-amazoncorretto-11'
  196. //让docker 使用 host 宿主机的 m2仓库 使用root用户来运行 以让指定的~/.m2/config/setting.xml 阿里加速下载maven 依赖生效
  197. args '-v /app:/app:z -v $HOME/.m2:/root/.m2:z -u root'
  198. reuseNode true
  199. }
  200. }
  201. steps {
  202. echo "编译 API 代码"
  203. sh "mvn clean package -U -am -pl ${params.module} -P${params.profile} -Dmaven.test.skip=true"
  204. }
  205. }
  206. // 项目打包到镜像并推送到镜像仓库
  207. stage('构建Docker镜像') {
  208. when {
  209. environment name: 'modulePrefix', value: 'java'
  210. }
  211. steps {
  212. echo "构建Dcoker镜像-------------------"
  213. script {
  214. docker.withRegistry(DOCKER_LOGIN_REGISTRY, DOCKER_REGISTRY) {
  215. BASE_IMAGE = 'registry.cn-shenzhen.aliyuncs.com/storlead/openjdk:11'
  216. sh "docker pull ${BASE_IMAGE}"
  217. sh """
  218. echo '
  219. FROM ${BASE_IMAGE}
  220. COPY ${params.module}/target/${params.module}.jar app.jar
  221. EXPOSE ${API_PORT}
  222. EXPOSE ${API_REMOTE_DEBUG_PORT}
  223. HEALTHCHECK --interval=1m --timeout=10s CMD curl -f http://localhost:${API_PORT}/${API_NAMESPACE_RESTFUL}/actuator
  224. ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-Djava.awt.headless=true","-Dspring.profiles.active=${params.profile}", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:${API_REMOTE_DEBUG_PORT}","-jar","/app.jar"]' > Dockerfile
  225. docker build -t ${DOCKER_IMG_NAME} .
  226. """
  227. sh "docker push ${DOCKER_IMG_NAME}"
  228. }
  229. }
  230. }
  231. }
  232. stage('启动服务') {
  233. when {
  234. environment name: 'modulePrefix', value: 'java'
  235. }
  236. steps {
  237. withCredentials([
  238. usernamePassword(credentialsId: 'storleadHW', usernameVariable: 'usernameHW', passwordVariable: 'passwordHW'),
  239. usernamePassword(credentialsId: 'storlead', usernameVariable: 'username', passwordVariable: 'password'),
  240. usernamePassword(credentialsId: 'reg-aliyun', usernameVariable: 'aliUsername', passwordVariable: 'aliPassword')
  241. ]) {
  242. script {
  243. echo "启动服务"
  244. echo "${aliPassword}"
  245. echo "docker login -u ${aliUsername} -p ${aliPassword} ${DOCKER_LOGIN_REGISTRY}"
  246. def remote = [:]
  247. remote.name = "${SERVER_HOST}"
  248. remote.host = "${SERVER_HOST}"
  249. remote.port = 53023
  250. remote.user = username
  251. remote.password = password
  252. remote.allowAnyHosts = true
  253. //因为使用 docker swarm 发布 只能在 manage node 执行部署
  254. if (params.profile == "prod") {
  255. remote.port = 22
  256. remote.user = "root"
  257. remote.user = usernameHW
  258. remote.password = passwordHW
  259. }
  260. if (PUSH_DOCK_IMG) {
  261. //docker 认证
  262. sshCommand remote: remote, command: "docker login -u ${aliUsername} -p ${aliPassword} ${DOCKER_LOGIN_REGISTRY}"
  263. //如果选择推送才使用远程的版本 如果不选择推送到远程则直接运行本机刚打包的镜像版本即可
  264. sshCommand remote: remote, command: "docker pull ${DOCKER_IMG_NAME}"
  265. }
  266. sh """
  267. echo '
  268. version: "3.7"
  269. services:
  270. ${params.module}-${params.profile}:
  271. image: ${DOCKER_IMG_NAME}
  272. deploy:
  273. replicas: ${SWARM_INIT_REPLICAS_NUM}
  274. placement:
  275. constraints:
  276. - 'node.hostname == ${SERVER_HOST_NAME}'
  277. resources:
  278. limits:
  279. memory: 2G
  280. reservations:
  281. memory: 512M
  282. update_config:
  283. parallelism: 1
  284. delay: 1m
  285. restart_policy:
  286. condition: on-failure
  287. # 最多连续重试3次如果仍然失败则放弃重试
  288. max_attempts: 3
  289. healthcheck:
  290. test: ["CMD", "curl", "-f", "http://localhost:${API_PORT}/${API_NAMESPACE_RESTFUL}/actuator"]
  291. interval: 1m
  292. timeout: 5s
  293. retries: 3
  294. start_period: 30s
  295. environment:
  296. - "TZ=Asia/Shanghai"
  297. - "SPRING_PROFILES_ACTIVE=${params.profile}"
  298. - "JAVA_OPTS=-Xms512m -Xmx1024m"
  299. volumes:
  300. - /app:/app
  301. - /mnt/vdb/storlead:/mnt/vdb/storlead
  302. ports:
  303. - "${API_PORT}:${API_PORT}"
  304. - "${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT}"
  305. networks:
  306. - ${ARTIFACTID}
  307. extra_hosts:
  308. - "www.storlead.com:172.18.194.161"
  309. - "node1:110.41.82.21"
  310. - "node2:110.41.174.46"
  311. - "node3:121.37.226.174"
  312. - "test1.storlead.com:172.18.194.168"
  313. - "test2.storlead.com:172.18.194.163"
  314. networks:
  315. ${ARTIFACTID}:
  316. driver: overlay
  317. external: true
  318. ' > ${params.module}-${params.profile}-stack.yml
  319. """
  320. // if (params.profile =="dev") {
  321. // sh "docker stack deploy -c ${ARTIFACTID}-${params.profile}-stack.yml ${ARTIFACTID}-${params.profile}"
  322. // sh "docker ps -f name=${ARTIFACTID} -q | xargs --no-run-if-empty docker container stop"
  323. // sh "docker container ls -a -fname=${ARTIFACTID} -q | xargs -r docker container rm"
  324. // sh "docker run -d --restart=always -p ${API_PORT}:${API_PORT} -p ${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT} -v /app:/app --name ${ARTIFACTID} ${DOCKER_IMG_NAME}"
  325. // } else {
  326. // 全部都以swarm 模式启动
  327. sshPut remote: remote, from: "${params.module}-${params.profile}-stack.yml", into: "/docker/sp/${params.module}-${params.profile}-stack.yml"
  328. sshCommand remote: remote, command: "docker stack deploy --resolve-image=always --with-registry-auth -c /docker/sp/${params.module}-${params.profile}-stack.yml ${params.module}-${params.profile}"
  329. // }
  330. }
  331. }
  332. }
  333. }
  334. }
  335. }