// 商户端 PC Web — 参数化流水线(预生产 / 生产) // 仓库: http://8.152.195.41:3000/alien/group_web_merchant.git // NPM 构建在 Docker node:20-alpine 中执行,无需本机安装 Node // 部署方式(默认 local): // local — Jenkins 容器内已挂载 /web_deploy_* 时,直接 cp(无需 SSH 凭据) // scp — Jenkins 与目标机分离时,需配置 SSH Username with private key 凭据 // // Jenkins 需预先配置「SSH Username with private key」凭据,ID 见参数 SSH_CREDENTIALS_ID(仅 scp 模式)。 pipeline { agent any parameters { choice( name: 'DEPLOY_ENV', choices: ['uat', 'pro'], description: 'uat=预生产,pro=生产' ) choice( name: 'DEPLOY_MODE', choices: ['local', 'scp'], description: 'local=容器内 cp 到 /web_deploy_*(同机挂载,推荐);scp=SSH 传到远程 ECS' ) // 仅 DEPLOY_MODE=scp 时需要;Jenkins → 凭据 → SSH Username with private key string( name: 'SSH_CREDENTIALS_ID', defaultValue: 'ssh-deploy', description: 'SCP/SSH 部署凭据 ID(类型须为 SSH Username with private key)' ) } options { buildDiscarder(logRotator(numToKeepStr: '2', artifactNumToKeepStr: '2')) timestamps() } environment { PATH = "${env.PATH}" } stages { stage('确认构建环境') { steps { script { if (params.DEPLOY_ENV == 'uat') { env.BUILD_SCRIPT = 'build:uat' env.DEPLOY_DEST = '/web_deploy_uat/group_web_merchant' env.DEPLOY_HOST = '39.106.135.88' env.DEPLOY_ENV_LABEL = '预生产(UAT)' } else if (params.DEPLOY_ENV == 'pro') { env.BUILD_SCRIPT = 'build:pro' env.DEPLOY_DEST = '/web_deploy_produ/group_web_merchant' env.DEPLOY_HOST = '39.106.135.88' env.DEPLOY_ENV_LABEL = '生产(PRO)' } else { error("未知 DEPLOY_ENV: ${params.DEPLOY_ENV}") } echo '========================================' echo ">>> 【流水线开始】本次构建环境: ${env.DEPLOY_ENV_LABEL}" echo ">>> BUILD_SCRIPT=${env.BUILD_SCRIPT}" echo ">>> 部署方式: ${params.DEPLOY_MODE}" echo ">>> 目标: ${env.DEPLOY_DEST}" echo '========================================' } } } stage('Checkout') { steps { echo ">>> 正在拉取 group_web_merchant 代码..." git branch: 'uat', credentialsId: 'zhanghaomimapingzheng', url: 'http://8.152.195.41:3000/alien/group_web_merchant.git' } } stage('NPM Build') { agent { docker { image 'node:20-alpine' reuseNode true // 若 workspace 属主与容器内用户不一致导致写权限问题,可临时用 root(按你们安全策略决定) // args '-u root:root' } } options { timeout(time: 20, unit: 'MINUTES') } steps { echo ">>> 安装依赖并构建(BUILD_SCRIPT=${env.BUILD_SCRIPT})..." sh """ set -e node -v npm -v npm config set registry https://registry.npmmirror.com export CI=true export HUSKY=0 export NODE_OPTIONS="--max-old-space-size=2048" npm install --no-audit npm run ${env.BUILD_SCRIPT} test -d dist && test -f dist/index.html echo ">>> 构建产物: \${WORKSPACE}/dist" """ } } stage('Deploy') { steps { echo ">>> 部署到 ${env.DEPLOY_ENV_LABEL}(${params.DEPLOY_MODE}): ${env.DEPLOY_DEST}" script { def allowedDest = [ '/web_deploy_uat/group_web_merchant', '/web_deploy_produ/group_web_merchant' ] if (!allowedDest.contains(env.DEPLOY_DEST)) { error("拒绝部署:DEPLOY_DEST 不在白名单内: ${env.DEPLOY_DEST}") } if (params.DEPLOY_MODE == 'scp') { if (!env.DEPLOY_HOST?.trim()) { error('拒绝部署:scp 模式需要 DEPLOY_HOST') } def credId = params.SSH_CREDENTIALS_ID?.trim() if (!credId) { error('拒绝部署:scp 模式请在构建参数中填写 SSH_CREDENTIALS_ID') } echo ">>> scp 模式,凭据: ${credId},目标: ${env.DEPLOY_HOST}:${env.DEPLOY_DEST}" } else { echo '>>> local 模式:容器内 cp 到挂载目录(无需 SSH 凭据)' } } script { if (params.DEPLOY_MODE == 'local') { sh """ set -e DEST="${env.DEPLOY_DEST}" case "\${DEST}" in /web_deploy_uat/group_web_merchant|/web_deploy_produ/group_web_merchant) ;; *) echo "拒绝部署:非法 DEST=[\${DEST}]"; exit 1 ;; esac test -d dist && test -f dist/index.html mkdir -p "\${DEST}" rm -rf "\${DEST}"/* cp -r dist/* "\${DEST}/" test -f "\${DEST}/index.html" echo ">>> group_web_merchant 部署完成: \${DEST}" """ } else { withCredentials([ sshUserPrivateKey( credentialsId: "${params.SSH_CREDENTIALS_ID}", keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER' ) ]) { sh """ set -e DEST="${env.DEPLOY_DEST}" HOST="${env.DEPLOY_HOST}" case "\${DEST}" in /web_deploy_uat/group_web_merchant|/web_deploy_produ/group_web_merchant) ;; *) echo "拒绝部署:非法 DEST=[\${DEST}]"; exit 1 ;; esac SSH_OPTS="-i \${SSH_KEY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes" echo ">>> 远程清空目录: \${SSH_USER}@\${HOST}:\${DEST}" ssh \${SSH_OPTS} "\${SSH_USER}@\${HOST}" "mkdir -p \${DEST} && rm -rf \${DEST}/*" echo ">>> 上传 dist/* ..." scp \${SSH_OPTS} -r dist/* "\${SSH_USER}@\${HOST}:\${DEST}/" echo ">>> group_web_merchant 部署完成: \${SSH_USER}@\${HOST}:\${DEST}" """ } } } } } } post { always { echo '========================================' echo ">>> 【流水线结束】构建任务结束" echo ">>> 环境: ${env.DEPLOY_ENV_LABEL ?: '(未执行确认阶段或变量未设置)'}" echo ">>> BUILD_SCRIPT=${env.BUILD_SCRIPT ?: '(无)'}" echo ">>> 目标: ${env.DEPLOY_DEST ?: '(无)'}" echo '========================================' } } }