pipeline { agent any environment { CODE_BRANCH = "dev" LOCKHOST_IP = "192.168.70.15" LOCKHOST_PROJECT_PATH = "/root/cdx/scalelink-frontend" WEB_HOST_IP = "43.153.21.64" WEB_HOST_PROJECT_PATH = "/data/webapps/lessie_official_web" } stages { stage('拉取代码') { steps { git branch: "${CODE_BRANCH}", credentialsId: 'fly_gitlab_auth', url: 'http://172.24.16.20/web/scalelink-frontend.git' } } stage('同步到本地机器') { steps { sh """ ssh ${LOCKHOST_IP} 'rm -rf ${LOCKHOST_PROJECT_PATH}/"*"' && rsync -az ${WORKSPACE}/ ${LOCKHOST_IP}:${LOCKHOST_PROJECT_PATH}/ """ } } stage('依赖和构建') { steps { sh """ ssh ${LOCKHOST_IP} "bash -lc \\" cd ${LOCKHOST_PROJECT_PATH}/projects/lessie && pnpm install --force && pnpm build && tar -czf output.tar.gz .output \\"" """ } } stage('上传产物') { steps { sh """ ssh ${LOCKHOST_IP} "bash -lc \\" scp -r ${LOCKHOST_PROJECT_PATH}/projects/lessie/output.tar.gz 43.153.21.64:${WEB_HOST_PROJECT_PATH}/ \\"" """ } } stage('启动') { steps { sh """ ssh ${WEB_HOST_IP} ' cd ${WEB_HOST_PROJECT_PATH} && pm2 list && pm2 delete lessie-official-web && tar -zxf output.tar.gz && pm2 start .output/server/index.mjs --name lessie-official-web --output ./nuxt-out.log --error ./nuxt-error.log ' """ } } } } pipeline { agent any environment { CODE_BRANCH = "dev" WEB_HOST_IP = "49.51.46.148" WEB_HOST_PROJECT_PATH = "/data/webapps/lessie_official_web" } stages { stage('checkout 代码') { steps { git branch: 'sit', credentialsId: 'fly_gitlab_auth', url: 'http://172.24.16.20/root/fly_moon.git' } } stage('Maven 编译') { steps { sh "cd ${WORKSPACE}/ && mvn clean install -P sit -Dmaven.sit.skip=true -pl flymoon-seo -am" } } stage('jar A下线') { steps { sh "ssh 192.168.70.18 'sh /data/sh/kill_fly_moon_seo.sh'" } } stage('jar A同步') { steps { sh """ scp ${WORKSPACE}/flymoon-seo/target/flymoon-seo.jar 192.168.70.18:/data/webapps/flymoon_seo/ scp ${WORKSPACE}/flymoon-common/target/flymoon-common.jar 192.168.70.18:/data/webapps/flymoon_seo/ scp ${WORKSPACE}/flymoon-framework/target/flymoon-framework.jar 192.168.70.18:/data/webapps/flymoon_seo/ scp ${WORKSPACE}/flymoon-system/target/flymoon-system.jar 192.168.70.18:/data/webapps/flymoon_seo/ """ } } stage('jar A启动') { steps { sh "ssh 192.168.70.18 'nohup /data/jdk1.8.0_181/bin/java -jar /data/webapps/flymoon_seo/flymoon-seo.jar --spring.profiles.active=sit >/data/webapps/flymoon_seo/nohup.out 2>&1 &' " } } } } # ------------------------7-22备份--------------- pipeline { agent any environment { REMOTE_HOST = "43.130.56.138" // 远程服务器 {params.REMOTE_HOST} REMOTE_PROJECT_PATH = "/data/webapps/lessie_sourcing_agents" // 远程 Python 项目路径 VENV_DIR = "/data/webapps/lessie_sourcing_agents/venv" // 远程虚拟环境目录 CONDA_PATH = "/root/miniconda3/bin/conda" // 修改为实际 Conda 安装路径 } stages { stage('Checkout 代码') { steps { git branch: "${params.Code_branch}", credentialsId: 'fly_gitlab_auth', url: 'http://172.24.16.20/python/lessie-sourcing-agents.git' } } stage('进程下线') { steps { echo("下线") sh "ssh ${REMOTE_HOST} 'sh /data/sh/kill_lessie_sourcing_agents.sh'" } } stage('工程同步') { steps { sh """ ssh ${REMOTE_HOST} 'mkdir -p ${REMOTE_PROJECT_PATH}' rsync -avz --exclude 'venv' ${WORKSPACE}/ ${REMOTE_HOST}:${REMOTE_PROJECT_PATH}/ """ } } stage('安装依赖') { steps { sh """ ssh ${REMOTE_HOST} ' cd ${REMOTE_PROJECT_PATH} && source ~/.bashrc && conda activate search && source ${VENV_DIR}/bin/activate && pip install --upgrade pip && pip install -r requirements.txt ' """ } } stage('工程启动') { steps { echo("启动") sh """ ssh ${REMOTE_HOST} ' conda activate search source ${VENV_DIR}/bin/activate TIMESTAMP=\$(date +"%Y%m%d_%H%M%S") nohup env APP_ENV=sit python /data/webapps/lessie_sourcing_agents/server.py > /data/webapps/lessie_sourcing_agents/logs/lessie_sourcing_agents_\${TIMESTAMP}.log 2>&1 & ' """ } } } post { success { echo '✅ 部署成功!' } failure { echo '❌ 部署失败,请检查日志!' } } } # ------------------------7-22备份--------------- # ------------------------7-22 滚动发布实验--------------- pipeline { agent any environment { REMOTE_HOST = "43.130.56.138" // 远程服务器 {params.REMOTE_HOST} REMOTE_PROJECT_PATH = "/data/webapps/lessie_sourcing_agents" // 远程 Python 项目路径 VENV_DIR = "/data/webapps/lessie_sourcing_agents/venv" // 远程虚拟环境目录 REMOTE_PROJECT_PATH_02 = "/data/webapps/lessie_sourcing_agents_02" VENV_DIR_02 = "/data/webapps/lessie_sourcing_agents_02/venv" CONDA_PATH = "/root/miniconda3/bin/conda" // 修改为实际 Conda 安装路径 } stages { stage('Checkout 代码') { steps { git branch: "${params.Code_branch}", credentialsId: 'fly_gitlab_auth', url: 'http://172.24.16.20/python/lessie-sourcing-agents.git' } } stage('进程A下线') { steps { echo("下线A") sh "ssh ${REMOTE_HOST} 'sh /data/sh/kill_lessie_sourcing_agents.sh'" } } stage('工程A同步') { steps { sh """ ssh ${REMOTE_HOST} 'mkdir -p ${REMOTE_PROJECT_PATH}' rsync -avz --exclude 'venv' ${WORKSPACE}/ ${REMOTE_HOST}:${REMOTE_PROJECT_PATH}/ """ } } stage('安装A依赖') { steps { sh """ ssh ${REMOTE_HOST} ' cd ${REMOTE_PROJECT_PATH} && source ~/.bashrc && conda activate search && source ${VENV_DIR}/bin/activate && pip install --upgrade pip && pip install -r requirements.txt ' """ } } stage('工程A启动') { steps { echo("启动A") sh """ ssh ${REMOTE_HOST} ' conda activate search source ${VENV_DIR}/bin/activate TIMESTAMP=\$(date +"%Y%m%d_%H%M%S") nohup env APP_ENV=sit python ${REMOTE_PROJECT_PATH}/server.py > ${REMOTE_PROJECT_PATH}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log 2>&1 & ' """ } } stage('探测A服务 ') { steps { echo("探测A服务") sh "ssh ${REMOTE_HOST} 'sh /data/sh/check_lessie_agents_8000.sh' " } } stage('进程B下线') { steps { echo("下线B") sh "ssh ${REMOTE_HOST} 'sh /data/sh/kill_lessie_sourcing_agents_8002.sh'" } } stage('工程B同步') { steps { sh """ ssh ${REMOTE_HOST} 'mkdir -p ${REMOTE_PROJECT_PATH_02}' rsync -avz --exclude 'venv' ${WORKSPACE}/ ${REMOTE_HOST}:${REMOTE_PROJECT_PATH_02}/ """ } } stage('安装B依赖') { steps { sh """ ssh ${REMOTE_HOST} ' cd ${REMOTE_PROJECT_PATH_02} && source ~/.bashrc && conda activate search && source ${VENV_DIR_02}/bin/activate && pip install --upgrade pip && pip install -r requirements.txt ' """ } } stage('工程B启动') { steps { echo("启动B") sh """ ssh ${REMOTE_HOST} ' conda activate search mv ${REMOTE_PROJECT_PATH_02}/server.py ${REMOTE_PROJECT_PATH_02}/server8002.py source ${VENV_DIR_02}/bin/activate TIMESTAMP_02=\$(date +"%Y%m%d_%H%M%S") nohup env APP_ENV=sit python ${REMOTE_PROJECT_PATH_02}/server8002.py --port 8002 > ${REMOTE_PROJECT_PATH_02}/logs/lessie_sourcing_agents_\${TIMESTAMP_02}.log 2>&1 & ' """ } } } post { success { echo '✅ 部署成功!' } failure { echo '❌ 部署失败,请检查日志!' } } } # ------------------------7-22 滚动发布实验--------------- # ------------------------7-28 滚动发布 等待连接数为0 再kill --------------- # 目标服务器脚本 set_s1_backend_weight.sh wait_s1_for_connections.sh # ------------------------7-28 滚动发布 等待连接数为0再kill 实验--------------- # ==============9-9双台python============== pipeline { agent any environment { REMOTE_HOST_A = "43.130.53.202" // 远程服务器A REMOTE_PROJECT_PATH_A = "/data/webapps/lessie_sourcing_agents" // 远程 Python 项目路径 VENV_DIR_A = "/data/webapps/lessie_sourcing_agents/venv" // 远程虚拟环境目录 CONDA_PATH = "/root/miniconda3/bin/conda" // 修改为实际 Conda 安装路径 } stages { stage('Checkout 代码') { steps { git branch: "${params.Code_branch}", credentialsId: 'fly_gitlab_auth', url: 'http://172.24.16.20/python/lessie-sourcing-agents.git' } } stage('进程A下线') { steps { echo("下线A") sh "ssh ${REMOTE_HOST_A} 'sh /data/sh/kill_lessie_sourcing_agents_8002.sh'" } } stage('工程A同步') { steps { echo("同步A") sh """ ssh ${REMOTE_HOST_A} 'mkdir -p ${REMOTE_PROJECT_PATH_A}' rsync -avz --exclude 'venv' ${WORKSPACE}/ ${REMOTE_HOST_A}:${REMOTE_PROJECT_PATH_A}/ """ } } stage('安装A依赖') { steps { echo("依赖A") sh """ ssh ${REMOTE_HOST_A} ' cd ${REMOTE_PROJECT_PATH_A} && source ~/.bashrc && conda activate search && source ${VENV_DIR_A}/bin/activate && pip install --upgrade pip && pip install -r requirements.txt ' """ } } stage('工程A启动') { steps { echo("启动A") sh """ ssh ${REMOTE_HOST_A} ' conda activate search source ${VENV_DIR_A}/bin/activate TIMESTAMP=\$(date +"%Y%m%d_%H%M%S") LOGFILE="${REMOTE_PROJECT_PATH_A}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log" nohup env APP_ENV=s1 python ${REMOTE_PROJECT_PATH_A}/server.py --port 8002 > ${REMOTE_PROJECT_PATH_A}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log 2>&1 & ln -sf "\$LOGFILE" ${REMOTE_PROJECT_PATH_A}/logs/lessie_sourcing_agents_latest.log ' """ } } stage('探测A服务 ') { steps { echo("探测A服务") sh "ssh ${REMOTE_HOST_A} 'sh /data/sh/check_lessie_agents_8002.sh' " } } } post { success { echo '✅ 部署成功!' } failure { echo '❌ 部署失败,请检查日志!' } } } # ========================9-9双台python============================== pipeline { agent any environment { REMOTE_HOST_A = "43.130.56.138" NGINX_HOST_B = "43.130.53.202" NGINX_HOST = "49.51.46.148" REMOTE_PROJECT_PATH_A = "/data/webapps/lessie_sourcing_agents" VENV_DIR_A = "/data/webapps/lessie_sourcing_agents/venv" REMOTE_PROJECT_PATH_B = "/data/webapps/lessie_sourcing_agents" VENV_DIR_B = "/data/webapps/lessie_sourcing_agents/venv" CONDA_PATH = "/root/miniconda3/bin/conda" NGINX_PY_backend_A = "10.0.0.5" NGINX_PY_backend_B = "10.0.0.13" PORT_A = "8000" PORT_B = "8002" CONNECTION_TIMEOUT = "600" // 等待连接关闭的超时时间(秒) NGINX_RELOAD_SCRIPT = "/data/sh/set_s1_backend_weight_new.sh" // 设置nginx后端组up/down WAIT_CONNECTIONS_SCRIPT = "/data/sh/wait_s1_for_connections.sh" // 等待连接数变为0 CHECK_STATUS_SCRIPT = "/data/sh/check_s1_backend_status.sh" // 检查后端组状态 } stages { stage('Checkout 代码') { steps { git branch: "${params.Code_branch}", credentialsId: 'fly_gitlab_auth', url: 'http://172.24.16.20/python/lessie-sourcing-agents.git' } } stage('A脱离后端组') { steps { echo "将实例A的权重设置为down,停止接收新连接" sh "ssh ${NGINX_HOST} 'sh ${NGINX_RELOAD_SCRIPT} ${NGINX_PY_backend_A} ${PORT_A} down'" echo "等待实例A的现有连接关闭" sh "ssh ${REMOTE_HOST_A} 'sh ${WAIT_CONNECTIONS_SCRIPT} ${PORT_A} ${CONNECTION_TIMEOUT}'" } } stage('A下线&同步') { steps { echo("下线A后同步A") sh "ssh ${REMOTE_HOST_A} 'sh /data/sh/kill_lessie_sourcing_agents.sh'" sh """ ssh ${REMOTE_HOST_A} 'mkdir -p ${REMOTE_PROJECT_PATH_A}' rsync -avz --exclude 'venv' --exclude '.git' ${WORKSPACE}/ ${REMOTE_HOST_A}:${REMOTE_PROJECT_PATH_A}/ """ } } stage('A依赖&启动') { steps { echo("A依赖&启动") sh """ ssh ${REMOTE_HOST_A} ' cd ${REMOTE_PROJECT_PATH_A} source ~/.bashrc conda activate search source ${VENV_DIR_A}/bin/activate pip install --upgrade pip pip install -r requirements.txt TIMESTAMP=\$(date +"%Y%m%d_%H%M%S") LOGFILE="${REMOTE_PROJECT_PATH_A}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log" nohup env APP_ENV=s1 python ${REMOTE_PROJECT_PATH_A}/server.py --port 8002 > ${REMOTE_PROJECT_PATH_A}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log 2>&1 & ln -sf "\$LOGFILE" ${REMOTE_PROJECT_PATH_A}/logs/lessie_sourcing_agents_latest.log ' """ } } stage('探测A服务 ') { steps { echo("探测A服务") sh "sleep 5" sh """ ssh ${REMOTE_HOST_A} "head -n 300 ${REMOTE_PROJECT_PATH_A}/logs/lessie_sourcing_agents_latest.log | grep -i 'error' || true" ssh ${REMOTE_HOST_A} "sh /data/sh/check_lessie_agents_8000.sh" """ } } stage('恢复A流量') { steps { echo "恢复实例A的流量" sh "sleep 5" sh "ssh ${NGINX_HOST} 'sh ${NGINX_RELOAD_SCRIPT} ${NGINX_PY_backend_A} ${PORT_A} up'" echo "实例 A 部署完成" } } stage('截B流量') { steps { echo "将实例B的权重设置为down,停止接收新连接" sh "ssh ${NGINX_HOST} 'sh ${NGINX_RELOAD_SCRIPT} ${NGINX_PY_backend_B} ${PORT_B} down'" echo "等待实例B的现有连接关闭" sh "ssh ${REMOTE_HOST} '${WAIT_CONNECTIONS_SCRIPT} ${PORT_B} ${CONNECTION_TIMEOUT}'" } } stage('B下线&同步') { steps { echo("B下线&同步") sh "ssh ${REMOTE_HOST_B} 'sh /data/sh/kill_lessie_sourcing_agents.sh'" sh """ ssh ${REMOTE_HOST_B} 'mkdir -p ${REMOTE_PROJECT_PATH_B}' rsync -avz --exclude 'venv' --exclude '.git' ${WORKSPACE}/ ${REMOTE_HOST_B}:${REMOTE_PROJECT_PATH_B}/ """ } } stage('B依赖&启动') { steps { echo("B依赖&启动") sh """ ssh ${REMOTE_HOST_B} ' cd ${REMOTE_PROJECT_PATH_B} && source ~/.bashrc && conda activate search && source ${VENV_DIR_B}/bin/activate && pip install --upgrade pip && pip install -r requirements.txt TIMESTAMP=\$(date +"%Y%m%d_%H%M%S") LOGFILE="${REMOTE_PROJECT_PATH_B}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log" nohup env APP_ENV=s1 python ${REMOTE_PROJECT_PATH_B}/server.py --port 8002 > ${REMOTE_PROJECT_PATH_B}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log 2>&1 & ln -sf "\$LOGFILE" ${REMOTE_PROJECT_PATH_B}/logs/lessie_sourcing_agents_latest.log ' """ } } stage('探测B服务 ') { steps { echo("探测B服务") sh "sleep 5" sh """ ssh ${REMOTE_HOST_B} "head -n 300 ${REMOTE_PROJECT_PATH_B}/logs/lessie_sourcing_agents_latest.log | grep -i 'error' || true" ssh ${REMOTE_HOST_B} "sh /data/sh/check_lessie_agents_8002.sh" """ } } stage('恢复B流量') { steps { echo "恢复实例B的流量" sh "sleep 5" sh "ssh ${NGINX_HOST} '${NGINX_RELOAD_SCRIPT_B} ${PORT_B} up'" echo "实例 B 部署完成" } } } post { success { echo '✅ 部署成功!' } failure { echo '❌ 部署失败,请检查日志!' } } } #========================================11-19未更改=============================================================================== node { properties([ parameters([ // 分支选择参数 gitParameter( branchFilter: 'origin/(.*)', defaultValue: 'master', description: 's1环境,默认master分支', name: 'Code_branch', quickFilterEnabled: true, selectedValue: 'DEFAULT', sortMode: 'NONE', type: 'PT_BRANCH', size: 1 ), // 部署实例选择 choice( name: 'DEPLOY_TARGETS', choices: ['A'], description: '选择需要部署的实例(多选格式为"A,B")' ), // 部署顺序 string( name: 'DEPLOY_ORDER', defaultValue: 'A', description: '指定部署顺序(如AB、BA,必须是已选实例的组合)' ) ]) ]) // 环境配置(集中管理实例参数) def config = [ A: [ remoteHost: "43.130.56.138", projectPath: "/data/webapps/lessie_sourcing_agents", venvDir: "/data/webapps/lessie_sourcing_agents/.venv", nginxBackend: "10.0.0.5", port: "8000", killScript: "/data/sh/kill_lessie_sourcing_agents.sh", checkScript: "/data/sh/check_lessie_agents_8000.sh", gunicornWorkers: 4 ], B: [ remoteHost: "43.130.53.202", projectPath: "/data/webapps/lessie_sourcing_agents", venvDir: "/data/webapps/lessie_sourcing_agents/.venv", nginxBackend: "10.0.0.13", port: "8002", killScript: "/data/sh/kill_lessie_sourcing_agents.sh", checkScript: "/data/sh/check_lessie_agents_8002.sh", gunicornWorkers: 4 ] ] def commonConfig = [ nginxHost: "49.51.46.148", connectionTimeout: "600", nginxReloadScript: "/data/sh/set_s1_backend_weight_new.sh", waitConnectionsScript: "/data/sh/wait_s1_for_connections.sh" ] stage('拉代码') { checkout scm: [ $class: 'GitSCM', branches: [[name: params.Code_branch]], userRemoteConfigs: [[ url: 'http://172.24.16.20/python/lessie-sourcing-agents.git', credentialsId: 'fly_gitlab_auth' ]] ] } stage('验证参数') { def selectedTargets = params.DEPLOY_TARGETS.split(',').toList() def orderChars = params.DEPLOY_ORDER.split('').toList() if (orderChars.isEmpty()) { error("部署顺序不能为空,请输入如AB、BA的顺序") } orderChars.each { instance -> if (!selectedTargets.contains(instance)) { error("部署顺序包含未选择的实例: ${instance},已选实例:${params.DEPLOY_TARGETS}") } } def uniqueOrder = orderChars.unique() if (uniqueOrder.size() != orderChars.size()) { error("部署顺序包含重复实例: ${params.DEPLOY_ORDER}") } echo "✅ 参数验证通过:已选实例=${selectedTargets},部署顺序=${orderChars}" env.VALID_ORDER = params.DEPLOY_ORDER } stage('动态部署') { def orderChars = env.VALID_ORDER.split('').toList() orderChars.each { instance -> echo "===== 开始部署实例 ${instance} =====" // 实例部署的5个步骤(直接在循环中定义stage,无嵌套) stage("${instance}:脱离后端组") { def cfg = config[instance] sh "ssh ${commonConfig.nginxHost} 'sh ${commonConfig.nginxReloadScript} ${cfg.nginxBackend} ${cfg.port} down'" sh "ssh ${cfg.remoteHost} 'sh ${commonConfig.waitConnectionsScript} ${cfg.port} ${commonConfig.connectionTimeout}'" } stage("${instance}下线&同步") { def cfg = config[instance] sh "ssh ${cfg.remoteHost} 'sh ${cfg.killScript} ${cfg.port}'" sh """ ssh ${cfg.remoteHost} 'mkdir -p ${cfg.projectPath}' rsync -avz --exclude '.venv' --exclude '.git' ${WORKSPACE}/ ${cfg.remoteHost}:${cfg.projectPath}/ """ } stage("${instance}依赖&启动") { def cfg = config[instance] sh """ ssh ${cfg.remoteHost} ' cd ${cfg.projectPath} uv sync source ${cfg.venvDir}/bin/activate TIMESTAMP=\$(date +"%Y%m%d_%H%M%S") LOGFILE="${cfg.projectPath}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log" nohup env APP_ENV=s1 gunicorn -w ${cfg.gunicornWorkers} -k uvicorn.workers.UvicornWorker \ -b 0.0.0.0:${cfg.port} --timeout 300 dialogue.app:app \ --max-requests 200 --max-requests-jitter 50 \ > "\$LOGFILE" 2>&1 & ln -sf "\$LOGFILE" ${cfg.projectPath}/logs/lessie_sourcing_agents_latest.log ' """ } stage("探测${instance}探测服务") { def cfg = config[instance] sh "sleep 5" sh "ssh ${cfg.remoteHost} 'head -n 300 ${cfg.projectPath}/logs/lessie_sourcing_agents_latest.log | grep -i error || echo 未发现错误日志'" sh "ssh ${cfg.remoteHost} 'sh ${cfg.checkScript}'" } stage("恢复${instance}流量") { def cfg = config[instance] sh "ssh ${commonConfig.nginxHost} 'sh ${commonConfig.nginxReloadScript} ${cfg.nginxBackend} ${cfg.port} up'" } echo "===== 实例 ${instance} 部署完成 =====" } } echo '✅ 所有选中的实例部署成功!' } #==================================================11-19未更改==================================================================== #========================================11-19更改=============================================================================== node { properties([ parameters([ // 分支选择参数 gitParameter( branchFilter: 'origin/(.*)', defaultValue: 'master', description: 's1环境,默认master分支', name: 'Code_branch', quickFilterEnabled: true, selectedValue: 'DEFAULT', sortMode: 'NONE', type: 'PT_BRANCH', size: 1 ), // 部署实例选择 choice( name: 'DEPLOY_TARGETS', choices: ['A'], description: '选择需要部署的实例(多选格式为"A,B")' ), // 部署顺序 string( name: 'DEPLOY_ORDER', defaultValue: 'A', description: '指定部署顺序(如AB、BA,必须是已选实例的组合)' ) ]) ]) // 环境配置(集中管理实例参数) def config = [ A: [ remoteHost: "43.130.56.138", projectPath: "/data/webapps/lessie_sourcing_agents", venvDir: "/data/webapps/lessie_sourcing_agents/.venv", nginxBackend: "10.0.0.5", port: "8000", killScript: "/data/sh/kill_lessie_sourcing_agents.sh", checkScript: "/data/sh/check_lessie_agents_8000.sh", gunicornWorkers: 4 ] ] def commonConfig = [ nginxHost: "49.51.46.148", connectionTimeout: "600", nginxReloadScript: "/data/sh/set_s1_backend_weight_new.sh", waitConnectionsScript: "/data/sh/wait_s1_for_connections.sh" ] stage('拉代码') { checkout scm: [ $class: 'GitSCM', branches: [[name: params.Code_branch]], userRemoteConfigs: [[ url: 'http://172.24.16.20/python/lessie-sourcing-agents.git', credentialsId: 'fly_gitlab_auth' ]] ] } stage('验证参数') { def selectedTargets = params.DEPLOY_TARGETS.split(',').toList() def orderChars = params.DEPLOY_ORDER.split('').toList() if (orderChars.isEmpty()) { error("部署顺序不能为空,请输入如AB、BA的顺序") } orderChars.each { instance -> if (!selectedTargets.contains(instance)) { error("部署顺序包含未选择的实例: ${instance},已选实例:${params.DEPLOY_TARGETS}") } } def uniqueOrder = orderChars.unique() if (uniqueOrder.size() != orderChars.size()) { error("部署顺序包含重复实例: ${params.DEPLOY_ORDER}") } echo "✅ 参数验证通过:已选实例=${selectedTargets},部署顺序=${orderChars}" env.VALID_ORDER = params.DEPLOY_ORDER } stage('动态部署') { def orderChars = env.VALID_ORDER.split('').toList() orderChars.each { instance -> echo "===== 开始部署实例 ${instance} =====" // 实例部署的5个步骤(直接在循环中定义stage,无嵌套) stage("${instance}:脱离后端组") { def cfg = config[instance] sh "ssh ${commonConfig.nginxHost} 'sh ${commonConfig.nginxReloadScript} ${cfg.nginxBackend} ${cfg.port} down'" sh "ssh ${cfg.remoteHost} 'sh ${commonConfig.waitConnectionsScript} ${cfg.port} ${commonConfig.connectionTimeout}'" } stage("${instance}下线&同步") { def cfg = config[instance] sh "ssh ${cfg.remoteHost} 'sh ${cfg.killScript} ${cfg.port}'" sh """ ssh ${cfg.remoteHost} 'mkdir -p ${cfg.projectPath}' rsync -avz --exclude '.venv' --exclude '.git' ${WORKSPACE}/ ${cfg.remoteHost}:${cfg.projectPath}/ """ } stage("${instance}依赖&启动") { def cfg = config[instance] sh """ ssh ${cfg.remoteHost} ' cd ${cfg.projectPath} uv sync source ${cfg.venvDir}/bin/activate TIMESTAMP=\$(date +"%Y%m%d_%H%M%S") LOGFILE="${cfg.projectPath}/logs/lessie_sourcing_agents_\${TIMESTAMP}.log" nohup env APP_ENV=s1 gunicorn -w ${cfg.gunicornWorkers} -k uvicorn.workers.UvicornWorker \ -b 0.0.0.0:${cfg.port} --timeout 300 dialogue.app:app \ --max-requests 200 --max-requests-jitter 50 \ > "\$LOGFILE" 2>&1 & ln -sf "\$LOGFILE" ${cfg.projectPath}/logs/lessie_sourcing_agents_latest.log ' """ } stage("探测${instance}探测服务") { def cfg = config[instance] sh "sleep 5" sh "ssh ${cfg.remoteHost} 'head -n 300 ${cfg.projectPath}/logs/lessie_sourcing_agents_latest.log | grep -i error || echo 未发现错误日志'" sh "ssh ${cfg.remoteHost} 'sh ${cfg.checkScript}'" } stage("恢复${instance}流量") { def cfg = config[instance] sh "ssh ${commonConfig.nginxHost} 'sh ${commonConfig.nginxReloadScript} ${cfg.nginxBackend} ${cfg.port} up'" } echo "===== 实例 ${instance} 部署完成 =====" } } echo '✅ 所有选中的实例部署成功!' stage("POST") { // python 环境 env.PY_environment = 's1' // git 提交短哈希 env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() // git 作者 env.GIT_AUTHOR = sh(script: 'git log -1 --pretty=format:%an', returnStdout: true).trim() // git 提交信息 env.GIT_COMMIT_MSG = sh(script: 'git log -1 --pretty=format:%B', returnStdout: true).trim() // 拼接荷载信息 def payload = [ env: env.PY_environment, usage_desc: [ code_branch : params.Code_branch, git_commit_short : env.GIT_COMMIT_SHORT, git_author : env.GIT_AUTHOR, git_commit_msg : env.GIT_COMMIT_MSG ] ] // JSON —— 转义所有字符 def jsonStr = groovy.json.JsonOutput.toJson(payload) // 请求 apex URL def URL = "http://43.159.145.241:8200/api/public/env-usage/env-usage" echo "正在发送请求到 ${URL}" echo "JSON Payload: ${jsonStr}" sh """ curl -X POST "${URL}" \ -H "Content-Type: application/json" \ -d '${jsonStr}' """ echo "请求完成" } } #==================================================11-19更改====================================================================