stages.nodejs.groovy 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. sharedLibsPath = "${env.WORKSPACE}/sharedLibs"
  2. backup_destination = '/var/jenkins_home/backups'
  3. backup_targetFile = 'dockerImage.tar'
  4. // 获取镜像URL
  5. generateFullImageUri = {Map DOCKER, String base_branch, String BUILD_NUMBER ->
  6. return "${DOCKER.registry}/${DOCKER.image}:${base_branch}-${BUILD_NUMBER}"
  7. }
  8. // 获取镜像名
  9. generateImageName = {Map DOCKER, String base_branch, String BUILD_NUMBER ->
  10. return "${DOCKER.image}:${base_branch}-${BUILD_NUMBER}"
  11. }
  12. def generateImageName(String imageName, String base_branch, String BUILD_NUMBER) {
  13. return "${imageName}:${base_branch}-${BUILD_NUMBER}"
  14. }
  15. def generateDockerfile(Object SERVICE, String pathOfDockerfile='projdir') {
  16. def module = SERVICE.module == null ? '' : (SERVICE.module[-1] == '/' ? SERVICE.module : SERVICE.module + '/')
  17. echo "-----> Generating Dockerfile: ${pathOfDockerfile}/Dockerfile ..."
  18. sh """cat > ${pathOfDockerfile}/Dockerfile<<EOF
  19. FROM node:14-slim as BUILD
  20. LABEL stage=STATICRES-BUILD
  21. COPY ./admin /admin
  22. WORKDIR /admin
  23. RUN npm config set registry https://registry.npm.taobao.org && npm install && npm run build
  24. FROM nginx:1.23-alpine as FINAL
  25. # configs for default
  26. COPY ./default.conf /etc/nginx/conf.d
  27. COPY ./html /usr/share/nginx/html
  28. # configs for partner.hobbystocks.cn
  29. COPY ./partner.hobbystocks.cn.conf /etc/nginx/conf.d
  30. COPY --from=BUILD /admin/dist /usr/share/nginx/partner/admin
  31. EOF
  32. """
  33. return pathOfDockerfile
  34. }
  35. def buildDockerImage(Object SERVICE, Object DOCKER, String base_branch, projDir='projdir', String filter2Remove=null) {
  36. def imageUri = generateFullImageUri(DOCKER, base_branch, BUILD_NUMBER)
  37. echo "-----> Building docker image: ${imageUri} ..."
  38. dir(projDir) {
  39. docker.withRegistry("http://${DOCKER.registry}", "${DOCKER.push_credentialId}") {
  40. def imageName = generateImageName(DOCKER, base_branch, BUILD_NUMBER)
  41. def image = docker.build(imageName)
  42. image.push()
  43. sh "docker rmi ${imageName}"
  44. if(filter2Remove != null)
  45. sh "docker image prune --filter label=${filter2Remove} -f"
  46. }
  47. }
  48. return imageUri
  49. }
  50. def restoreDockerImage(Object DOCKER, String workspace, String base_branch, String rollbackBuildNumber) {
  51. dir(workspace) {
  52. imageUri = generateFullImageUri(DOCKER, base_branch, rollbackBuildNumber)
  53. sh "docker load -i ${backup_targetFile}"
  54. // in case, docker image doesn't exist in remote registry
  55. docker.withRegistry("http://${DOCKER.registry}", "${DOCKER.push_credentialId}") {
  56. def image = docker.image(imageUri)
  57. image.push()
  58. }
  59. }
  60. return imageUri
  61. }
  62. def cleanDockerImage(String dockerImgName) {
  63. sh "docker rmi ${dockerImgName}"
  64. }
  65. def backupDockerImage(String dockerImgName) {
  66. echo "-----> Backup artifact(docker image : ${dockerImgName}) ..."
  67. path = "${backup_destination}/${JOB_NAME}/${BUILD_NUMBER}"
  68. sh """
  69. docker save ${dockerImgName} -o ${backup_targetFile}
  70. if [ -d ${path} ];
  71. then
  72. echo \"${path} already exists\"
  73. else
  74. mkdir -p ${path}
  75. mv ${backup_targetFile} ${path}
  76. fi
  77. """
  78. }
  79. def backupK8sConfigs(String[] files2backup) {
  80. path = "${backup_destination}/${JOB_NAME}/${BUILD_NUMBER}/k8s"
  81. sh """if [ -d ${path} ];
  82. then
  83. echo \"${path} already exists!\"
  84. else
  85. mkdir -p ${path}
  86. fi
  87. """
  88. for(file in files2backup) {
  89. sh "cp ${file} ${path}"
  90. }
  91. }
  92. def applyDeployment(SERVICE, K3S, String base_branch) {
  93. print "loading ${sharedLibsPath}/k3sUtil.groovy..."
  94. def k3sUtils = load "${sharedLibsPath}/k3sUtil.groovy"
  95. kvs = [:]
  96. kvs.put('<service_name>', SERVICE.name)
  97. kvs.put('<service_version>', SERVICE.version)
  98. kvs.put('<release>', base_branch)
  99. kvs.put('<COMMIT_SHA>', COMMIT_SHA)
  100. kvs.put('<imagePullSecret>', K3S.pull_secretId)
  101. kvs.put('<docker_image>', imageUri)
  102. k3sUtils.generateDeployment(kvs, 'deployment.yaml')
  103. k3sUtils.applyDeployment(K3S)
  104. k3sUtils.generateService(kvs, 'service.yaml')
  105. k3sUtils.applyService(K3S)
  106. }
  107. // Jenkins pipeline stages
  108. def execute(CONFIG, base_branch, closures=[:]) {
  109. stage('source code check out') {
  110. println "loading ${sharedLibsPath}/gitUtil.groovy..."
  111. def gitUtils = load "${sharedLibsPath}/gitUtil.groovy"
  112. COMMIT_SHA = closures.GITCLONE == null ? gitUtils.clone(CONFIG.git, base_branch) : closures.GITCLONE()
  113. }
  114. stage("docker image build") {
  115. def projDir = 'projdir'
  116. if (closures.GENERATEDOCKERFILE != null)
  117. projDir = closures.GENERATEDOCKERFILE()
  118. else
  119. projDir = generateDockerfile(CONFIG.service) //default
  120. if (closures.BUILDIMAGE != null)
  121. imageUri = closures.BUILDIMAGE()
  122. else
  123. imageUri = buildDockerImage(CONFIG.service, CONFIG.docker, base_branch, projDir, 'stage=STATICRES-BUILD')
  124. }
  125. stage("apply K8S Deployment") {
  126. if (closures.K3SDEPLOY != null) {
  127. closures.K3SDEPLOY()
  128. return
  129. }
  130. applyDeployment(CONFIG.service, CONFIG.k3s, base_branch)
  131. }
  132. }
  133. def upgrade(Object CONFIG, String base_branch, String[] k8sBackupFiles, closures=[:]) {
  134. stage('source code check out') {
  135. println "loading ${sharedLibsPath}/gitUtil.groovy..."
  136. def gitUtils = load "${sharedLibsPath}/gitUtil.groovy"
  137. COMMIT_SHA = closures.GITCLONE == null ? gitUtils.clone(CONFIG.git, base_branch) : closures.GITCLONE()
  138. }
  139. stage("docker image build") {
  140. def projDir = 'projdir'
  141. if (closures.GENERATEDOCKERFILE != null)
  142. projDir = closures.GENERATEDOCKERFILE()
  143. else
  144. projDir = generateDockerfile(CONFIG.service) //default
  145. if (closures.BUILDIMAGE != null)
  146. imageUri = closures.BUILDIMAGE()
  147. else
  148. imageUri = buildDockerImage(CONFIG.service, CONFIG.docker, base_branch, projDir, 'stage=STATICRES-BUILD')
  149. // stage("Docker Image backup") {
  150. backupDockerImage(imageUri)
  151. envFile = new File("${backup_destination}/${JOB_NAME}/${BUILD_NUMBER}/env")
  152. envFile << "${COMMIT_SHA}\n"
  153. envFile << "${base_branch}\n"
  154. // }
  155. // stage("K8s configs backup") {
  156. backupK8sConfigs(k8sBackupFiles)
  157. // }
  158. cleanDockerImage(imageUri)
  159. }
  160. stage("apply K8S Deployment") {
  161. if (closures.K3SDEPLOY != null) {
  162. closures.K3SDEPLOY()
  163. return
  164. }
  165. applyDeployment(CONFIG.service, CONFIG.k3s, base_branch)
  166. }
  167. stage("Clear older backup version") {
  168. // 清理旧的备份
  169. dir("${backup_destination}/${JOB_NAME}") {
  170. echo "-----> Clear older backup version ..."
  171. sh """
  172. save_file=`ls -ltr | tail -5 | awk '{print \$NF}'`
  173. ls | grep -v "\$save_file" | xargs rm -rf
  174. """
  175. }
  176. }
  177. }
  178. def rollback(Object CONFIG, String rollbackBuildNumber, closures=[:]) {
  179. path = "${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}"
  180. if (fileExists(path)) {
  181. envFile = new File("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/env")
  182. def lines = envFile.readLines()
  183. COMMIT_SHA = lines[0]
  184. BASE_BRANCH = lines[1]
  185. stage('source code check out') {
  186. print("souce code check out. Skipped!")
  187. }
  188. stage("docker image build") {
  189. print("restore docker image from rollbackNo. #${rollbackBuildNumber}")
  190. imageUri = restoreDockerImage(CONFIG.docker, path, BASE_BRANCH, rollbackBuildNumber)
  191. cleanDockerImage(imageUri)
  192. }
  193. stage("apply K8S Deployment") {
  194. if (closures.K3SDEPLOY != null) {
  195. closures.K3SDEPLOY()
  196. return
  197. }
  198. dir("${backup_destination}/${JOB_NAME}/${rollbackBuildNumber}/k8s") {
  199. applyDeployment(CONFIG.service, CONFIG.k3s, BASE_BRANCH)
  200. }
  201. }
  202. stage("Clear rollback workspace") {
  203. // 清理rollback工作目录
  204. dir("${backup_destination}/${JOB_NAME}") {
  205. echo "-----> Clear rollback workspace ..."
  206. sh "rm -rf *@tmp"
  207. }
  208. }
  209. }
  210. }
  211. return this