Jenkinsfile 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // 商户端 PC Web — 参数化流水线(预生产 / 生产)
  2. // 仓库: http://8.152.195.41:3000/alien/group_web_merchant.git
  3. // NPM 构建在 Docker node:20-alpine 中执行,无需本机安装 Node
  4. // 部署方式(默认 local):
  5. // local — Jenkins 容器内已挂载 /web_deploy_* 时,直接 cp(无需 SSH 凭据)
  6. // scp — Jenkins 与目标机分离时,需配置 SSH Username with private key 凭据
  7. //
  8. // Jenkins 需预先配置「SSH Username with private key」凭据,ID 见参数 SSH_CREDENTIALS_ID(仅 scp 模式)。
  9. pipeline {
  10. agent any
  11. parameters {
  12. choice(
  13. name: 'DEPLOY_ENV',
  14. choices: ['uat', 'pro'],
  15. description: 'uat=预生产,pro=生产'
  16. )
  17. choice(
  18. name: 'DEPLOY_MODE',
  19. choices: ['local', 'scp'],
  20. description: 'local=容器内 cp 到 /web_deploy_*(同机挂载,推荐);scp=SSH 传到远程 ECS'
  21. )
  22. // 仅 DEPLOY_MODE=scp 时需要;Jenkins → 凭据 → SSH Username with private key
  23. string(
  24. name: 'SSH_CREDENTIALS_ID',
  25. defaultValue: 'ssh-deploy',
  26. description: 'SCP/SSH 部署凭据 ID(类型须为 SSH Username with private key)'
  27. )
  28. }
  29. options {
  30. buildDiscarder(logRotator(numToKeepStr: '2', artifactNumToKeepStr: '2'))
  31. timestamps()
  32. }
  33. environment {
  34. PATH = "${env.PATH}"
  35. }
  36. stages {
  37. stage('确认构建环境') {
  38. steps {
  39. script {
  40. if (params.DEPLOY_ENV == 'uat') {
  41. env.BUILD_SCRIPT = 'build:uat'
  42. env.DEPLOY_DEST = '/web_deploy_uat/group_web_merchant'
  43. env.DEPLOY_HOST = '39.106.135.88'
  44. env.DEPLOY_ENV_LABEL = '预生产(UAT)'
  45. } else if (params.DEPLOY_ENV == 'pro') {
  46. env.BUILD_SCRIPT = 'build:pro'
  47. env.DEPLOY_DEST = '/web_deploy_produ/group_web_merchant'
  48. env.DEPLOY_HOST = '39.106.135.88'
  49. env.DEPLOY_ENV_LABEL = '生产(PRO)'
  50. } else {
  51. error("未知 DEPLOY_ENV: ${params.DEPLOY_ENV}")
  52. }
  53. echo '========================================'
  54. echo ">>> 【流水线开始】本次构建环境: ${env.DEPLOY_ENV_LABEL}"
  55. echo ">>> BUILD_SCRIPT=${env.BUILD_SCRIPT}"
  56. echo ">>> 部署方式: ${params.DEPLOY_MODE}"
  57. echo ">>> 目标: ${env.DEPLOY_DEST}"
  58. echo '========================================'
  59. }
  60. }
  61. }
  62. stage('Checkout') {
  63. steps {
  64. echo ">>> 正在拉取 group_web_merchant 代码..."
  65. git branch: 'uat',
  66. credentialsId: 'zhanghaomimapingzheng',
  67. url: 'http://8.152.195.41:3000/alien/group_web_merchant.git'
  68. }
  69. }
  70. stage('NPM Build') {
  71. agent {
  72. docker {
  73. image 'node:20-alpine'
  74. reuseNode true
  75. // 若 workspace 属主与容器内用户不一致导致写权限问题,可临时用 root(按你们安全策略决定)
  76. // args '-u root:root'
  77. }
  78. }
  79. options {
  80. timeout(time: 20, unit: 'MINUTES')
  81. }
  82. steps {
  83. echo ">>> 安装依赖并构建(BUILD_SCRIPT=${env.BUILD_SCRIPT})..."
  84. sh """
  85. set -e
  86. node -v
  87. npm -v
  88. npm config set registry https://registry.npmmirror.com
  89. export CI=true
  90. export HUSKY=0
  91. export NODE_OPTIONS="--max-old-space-size=2048"
  92. npm install --no-audit
  93. npm run ${env.BUILD_SCRIPT}
  94. test -d dist && test -f dist/index.html
  95. echo ">>> 构建产物: \${WORKSPACE}/dist"
  96. """
  97. }
  98. }
  99. stage('Deploy') {
  100. steps {
  101. echo ">>> 部署到 ${env.DEPLOY_ENV_LABEL}(${params.DEPLOY_MODE}): ${env.DEPLOY_DEST}"
  102. script {
  103. def allowedDest = [
  104. '/web_deploy_uat/group_web_merchant',
  105. '/web_deploy_produ/group_web_merchant'
  106. ]
  107. if (!allowedDest.contains(env.DEPLOY_DEST)) {
  108. error("拒绝部署:DEPLOY_DEST 不在白名单内: ${env.DEPLOY_DEST}")
  109. }
  110. if (params.DEPLOY_MODE == 'scp') {
  111. if (!env.DEPLOY_HOST?.trim()) {
  112. error('拒绝部署:scp 模式需要 DEPLOY_HOST')
  113. }
  114. def credId = params.SSH_CREDENTIALS_ID?.trim()
  115. if (!credId) {
  116. error('拒绝部署:scp 模式请在构建参数中填写 SSH_CREDENTIALS_ID')
  117. }
  118. echo ">>> scp 模式,凭据: ${credId},目标: ${env.DEPLOY_HOST}:${env.DEPLOY_DEST}"
  119. } else {
  120. echo '>>> local 模式:容器内 cp 到挂载目录(无需 SSH 凭据)'
  121. }
  122. }
  123. script {
  124. if (params.DEPLOY_MODE == 'local') {
  125. sh """
  126. set -e
  127. DEST="${env.DEPLOY_DEST}"
  128. case "\${DEST}" in
  129. /web_deploy_uat/group_web_merchant|/web_deploy_produ/group_web_merchant) ;;
  130. *) echo "拒绝部署:非法 DEST=[\${DEST}]"; exit 1 ;;
  131. esac
  132. test -d dist && test -f dist/index.html
  133. mkdir -p "\${DEST}"
  134. rm -rf "\${DEST}"/*
  135. cp -r dist/* "\${DEST}/"
  136. test -f "\${DEST}/index.html"
  137. echo ">>> group_web_merchant 部署完成: \${DEST}"
  138. """
  139. } else {
  140. withCredentials([
  141. sshUserPrivateKey(
  142. credentialsId: "${params.SSH_CREDENTIALS_ID}",
  143. keyFileVariable: 'SSH_KEY',
  144. usernameVariable: 'SSH_USER'
  145. )
  146. ]) {
  147. sh """
  148. set -e
  149. DEST="${env.DEPLOY_DEST}"
  150. HOST="${env.DEPLOY_HOST}"
  151. case "\${DEST}" in
  152. /web_deploy_uat/group_web_merchant|/web_deploy_produ/group_web_merchant) ;;
  153. *) echo "拒绝部署:非法 DEST=[\${DEST}]"; exit 1 ;;
  154. esac
  155. SSH_OPTS="-i \${SSH_KEY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes"
  156. echo ">>> 远程清空目录: \${SSH_USER}@\${HOST}:\${DEST}"
  157. ssh \${SSH_OPTS} "\${SSH_USER}@\${HOST}" "mkdir -p \${DEST} && rm -rf \${DEST}/*"
  158. echo ">>> 上传 dist/* ..."
  159. scp \${SSH_OPTS} -r dist/* "\${SSH_USER}@\${HOST}:\${DEST}/"
  160. echo ">>> group_web_merchant 部署完成: \${SSH_USER}@\${HOST}:\${DEST}"
  161. """
  162. }
  163. }
  164. }
  165. }
  166. }
  167. }
  168. post {
  169. always {
  170. echo '========================================'
  171. echo ">>> 【流水线结束】构建任务结束"
  172. echo ">>> 环境: ${env.DEPLOY_ENV_LABEL ?: '(未执行确认阶段或变量未设置)'}"
  173. echo ">>> BUILD_SCRIPT=${env.BUILD_SCRIPT ?: '(无)'}"
  174. echo ">>> 目标: ${env.DEPLOY_DEST ?: '(无)'}"
  175. echo '========================================'
  176. }
  177. }
  178. }