From 979c8b1a624b2c9854e80d3cd3fa82ed0283e220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=95=80=E9=93=AC=E9=85=B8=E9=92=BE?= <148796996+K2cr2O1@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:23:31 +0800 Subject: [PATCH] Update main.yml --- .github/workflows/main.yml | 315 ++++++++++++++++++++++++++++++------- 1 file changed, 259 insertions(+), 56 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c89810c..d14728e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,32 +16,125 @@ jobs: deploy: runs-on: ubuntu-latest environment: SSH-KEY + timeout-minutes: 15 steps: - uses: actions/checkout@v4 - + # 检出代码失败直接终止并提示 + if: failure() + run: | + echo "❌ 代码检出失败!请检查仓库权限或网络问题" + exit 1 + + # ========== 新增:配置清华源更新pip并安装项目依赖 ========== + - name: 配置清华源更新pip并安装项目依赖 + id: install_pip_deps + # 开启 errexit(出错立即终止)和 xtrace(输出执行命令) + run: | + set -euo pipefail + echo "=== 开始配置清华源并安装pip依赖 ===" + + # 1. 安装Python和pip(确保环境有pip) + echo "📦 安装Python和pip..." + sudo apt-get update -y + sudo apt-get install -y python3 python3-pip python3-venv --no-install-recommends + + # 2. 配置pip清华镜像源(临时生效,避免污染全局) + echo "🔧 配置pip清华镜像源..." + pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple + pip3 config set install.trusted-host pypi.tuna.tsinghua.edu.cn + + # 3. 更新pip到最新版本 + echo "⬆️ 更新pip到最新版本..." + # 重试机制:失败后重试2次,每次间隔3秒 + for i in {1..3}; do + if pip3 install --upgrade pip; then + break + elif [ $i -eq 3 ]; then + echo "❌ pip更新失败(已重试3次)" + exit 1 + fi + echo "⚠️ pip更新失败,3秒后重试(第$i次)..." + sleep 3 + done + + # 4. 检查项目依赖文件并安装 + REQUIREMENTS_FILE="requirements.txt" # 可根据实际文件名修改(如requirements/prod.txt) + if [ -f "$REQUIREMENTS_FILE" ]; then + echo "📄 找到依赖文件 $REQUIREMENTS_FILE,开始安装依赖..." + # 安装依赖并输出详细日志,失败时保留缓存便于排查 + pip3 install --no-cache-dir -r "$REQUIREMENTS_FILE" 2>&1 | tee pip_install.log + echo "✅ pip依赖安装完成" + else + echo "⚠️ 未找到依赖文件 $REQUIREMENTS_FILE,跳过依赖安装" + fi + + # 5. 验证pip和依赖安装结果 + echo "✅ pip版本:$(pip3 --version)" + echo "✅ 已安装的依赖列表:" + pip3 list + # 依赖安装失败时的详细提示 + continue-on-error: false + error_message: "pip依赖安装失败,请检查requirements.txt或清华源网络" + + # ========== 原有步骤:安装系统依赖工具(强化错误处理) ========== - name: 安装依赖工具 + id: install_sys_deps run: | - # 重新安装sshpass(用于处理服务器登录密码)+ expect(处理密钥密码) - sudo apt-get update - sudo apt-get install -y sshpass expect - + set -euo pipefail + echo "=== 开始安装系统依赖工具 ===" + # 配置清华源加速apt更新(可选,提升安装速度) + sudo sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list + sudo apt-get update -y || { echo "❌ apt更新失败"; exit 1; } + + # 安装工具并验证 + TOOLS="sshpass expect openssh-client" + for TOOL in $TOOLS; do + echo "📦 安装 $TOOL..." + if sudo apt-get install -y --no-install-recommends $TOOL; then + echo "✅ $TOOL 安装成功" + else + echo "❌ $TOOL 安装失败" + exit 1 + fi + done + + # 验证工具可用性 + sshpass -V >/dev/null || { echo "❌ sshpass安装后不可用"; exit 1; } + expect -v >/dev/null || { echo "❌ expect安装后不可用"; exit 1; } + continue-on-error: false + + # ========== 原有步骤:配置SSH密钥(强化错误处理) ========== - name: 配置SSH密钥并启动ssh-agent + id: config_ssh run: | - # 创建SSH目录并设置严格权限(SSH要求) + set -euo pipefail + echo "=== 开始配置SSH密钥 ===" + + # 创建SSH目录并严格控制权限 mkdir -p ~/.ssh chmod 700 ~/.ssh - # 将GitHub Secrets中的私钥写入文件 - echo "${{ secrets.KEY }}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa # 必须600权限,否则SSH拒绝使用 + # 处理私钥换行符问题,验证私钥完整性 + echo "${{ secrets.KEY }}" | tr -d '\r' > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa - # 启动ssh-agent并加载带密码的私钥 + # 验证私钥格式 + if ! head -n 1 ~/.ssh/id_rsa | grep -q "BEGIN"; then + echo "❌ 私钥文件格式错误,未找到BEGIN标记" + exit 1 + fi + if ! tail -n 1 ~/.ssh/id_rsa | grep -q "END"; then + echo "❌ 私钥文件格式错误,未找到END标记" + exit 1 + fi + + # 启动ssh-agent并加载私钥 eval $(ssh-agent -s) - echo "=== 加载SSH密钥调试信息 ===" - echo "当前ssh-agent进程ID: $SSH_AGENT_PID" - # 使用expect自动输入密钥密码(PASSPHRASE) + export SSH_AGENT_PID SSH_AUTH_SOCK + + echo "🔑 加载SSH私钥..." expect -c " - set timeout 10 + set timeout 15 spawn ssh-add ~/.ssh/id_rsa expect { \"Enter passphrase for /home/runner/.ssh/id_rsa:\" { @@ -49,55 +142,165 @@ jobs: exp_continue } \"Identity added: /home/runner/.ssh/id_rsa\" { - puts \"密钥加载成功\" + puts \"✅ 私钥加载成功\" + exit 0 } - timeout { - puts \"密钥加载超时\" + \"Bad passphrase, try again\" { + puts \"❌ 私钥密码错误(PASSPHRASE)\" + exit 1 + } + timeout { + puts \"❌ 私钥加载超时\" + exit 1 + } + eof { + puts \"❌ 私钥加载失败\" exit 1 } - eof } - " - # 查看已加载的密钥(调试用) - ssh-add -l || echo "无已加载的SSH密钥" + " || { echo "❌ 私钥加载失败,终止流程"; exit 1; } - # 禁用主机密钥检查,避免首次连接确认 - echo "StrictHostKeyChecking no" >> ~/.ssh/config - echo "UserKnownHostsFile /dev/null" >> ~/.ssh/config - echo "GlobalKnownHostsFile /dev/null" >> ~/.ssh/config + # 配置SSH免主机检查 + cat > ~/.ssh/config << EOF + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + GlobalKnownHostsFile /dev/null + ConnectTimeout 30 + EOF chmod 600 ~/.ssh/config - echo "=== SSH密钥配置完成 ===" - - - name: 执行部署 - run: | - # 使用sshpass传递服务器密码 + SSH密钥登录(双重认证) - sshpass -p "${{ secrets.SERVER_PASSWORD }}" ssh -o StrictHostKeyChecking=no \ - -o IdentityFile=~/.ssh/id_rsa -p 42422 ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_ADDRESS }} ' - set -ex - echo "=== 部署调试信息开始 ===" - echo "测试sudo权限..." - echo "${{ secrets.SERVER_PASSWORD }}" | sudo -S whoami - echo "停止服务..." - echo "${{ secrets.SERVER_PASSWORD }}" | sudo -S systemctl stop neobot.service - echo "修复文件权限..." - echo "${{ secrets.SERVER_PASSWORD }}" | sudo -S chown -R ${{ secrets.SERVER_USER }}:${{ secrets.SERVER_USER }} /home/luoxiaolei/neobot/NeoBot - cd /home/luoxiaolei/neobot/NeoBot - echo "拉取最新代码(服务器本地已有GitHub密钥)..." - git pull origin main - echo "启动服务..." - echo "${{ secrets.SERVER_PASSWORD }}" | sudo -S systemctl start neobot.service - echo "检查服务状态..." - echo "${{ secrets.SERVER_PASSWORD }}" | sudo -S systemctl status neobot.service --no-pager - echo "部署完成!" - echo "=== 部署调试信息结束 ===" - ' + echo "✅ SSH密钥配置完成" continue-on-error: false - - - name: 检查部署状态 + + # ========== 原有步骤:执行部署(强化错误处理) ========== + - name: 执行部署 + id: run_deploy + run: | + set -euo pipefail + echo "=== 开始执行服务器部署 ===" + + # 定义部署命令(抽离便于维护) + DEPLOY_CMD=$(cat << 'EOF' + set -exuo pipefail + echo "=== 服务器部署开始($(date))===" + + # 服务器端也配置清华源(可选,如需在服务器安装pip依赖) + pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple || true + + # 测试sudo权限 + echo "${SERVER_PASSWORD}" | sudo -S -k -p '' whoami || { echo "❌ sudo权限验证失败"; exit 1; } + + # 停止服务(失败不终止,避免服务未启动导致部署中断) + echo "🛑 停止neobot服务..." + echo "${SERVER_PASSWORD}" | sudo -S -k -p '' systemctl stop neobot.service || true + sleep 2 + + # 修复文件权限 + echo "🔧 修复文件权限..." + echo "${SERVER_PASSWORD}" | sudo -S -k -p '' chown -R "${SERVER_USER}":"${SERVER_USER}" /home/luoxiaolei/neobot/NeoBot || { echo "❌ 文件权限修复失败"; exit 1; } + + # 拉取代码 + cd /home/luoxiaolei/neobot/NeoBot || { echo "❌ 项目目录不存在"; exit 1; } + echo "⬇️ 拉取最新代码..." + git pull origin main || { echo "❌ 代码拉取失败"; exit 1; } + + # 使用pip3.14升级依赖 + echo "📦 使用pip3.14升级项目依赖..." + if [ -f "requirements.txt" ]; then + echo "📄 发现requirements.txt,使用pip3.14安装/升级依赖..." + # 尝试使用pip3.14,如果不存在则使用pip3 + if command -v pip3.14 &> /dev/null; then + pip3.14 install --upgrade -r requirements.txt || { echo "❌ pip3.14依赖安装失败"; exit 1; } + echo "✅ pip3.14依赖安装完成" + else + echo "⚠️ pip3.14未找到,尝试使用pip3..." + pip3 install --upgrade -r requirements.txt || { echo "❌ pip3依赖安装失败"; exit 1; } + echo "✅ pip3依赖安装完成" + fi + else + echo "⚠️ 未找到requirements.txt文件,跳过依赖安装" + fi + + # 启动服务 + echo "🚀 启动neobot服务..." + echo "${SERVER_PASSWORD}" | sudo -S -k -p '' systemctl start neobot.service || { echo "❌ 服务启动失败"; exit 1; } + sleep 3 + + # 检查服务状态 + echo "📋 检查服务状态..." + if ! echo "${SERVER_PASSWORD}" | sudo -S -k -p '' systemctl status neobot.service --no-pager --full; then + echo "❌ neobot服务启动异常,查看日志:" + echo "${SERVER_PASSWORD}" | sudo -S -k -p '' journalctl -u neobot.service --no-pager -n 50 + exit 1 + fi + + echo "✅ 服务器部署完成($(date))===" + EOF + ) + + # 替换变量并执行部署 + export SERVER_PASSWORD="${{ secrets.SERVER_PASSWORD }}" + export SERVER_USER="${{ secrets.SERVER_USER }}" + DEPLOY_CMD=$(echo "$DEPLOY_CMD" | sed "s/\${SERVER_PASSWORD}/${{ secrets.SERVER_PASSWORD }}/g") + DEPLOY_CMD=$(echo "$DEPLOY_CMD" | sed "s/\${SERVER_USER}/${{ secrets.SERVER_USER }}/g") + + # 执行部署(带SSH调试日志) + if ! sshpass -p "${{ secrets.SERVER_PASSWORD }}" ssh -v \ + -o IdentityFile=~/.ssh/id_rsa \ + -o ConnectTimeout=30 \ + -p 42422 ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_ADDRESS }} "$DEPLOY_CMD"; then + echo "❌ 部署命令执行失败" + exit 1 + fi + + echo "✅ 部署流程全部完成" + continue-on-error: false + + # ========== 强化错误处理:步骤失败后的详细提示 ========== + - name: 部署失败详细排查 if: failure() run: | - echo "部署失败!请检查以下点:" - echo "1. 服务器SSH配置是否允许密钥+密码双重认证" - echo "2. KEY/PASSPHRASE/SERVER_PASSWORD是否正确" - echo "3. 服务器端口42422是否开放,用户名/地址是否正确" + echo "==================================================" + echo "❌ 部署失败!详细排查信息:" + echo "==================================================" + # 输出各步骤状态 + echo "🔍 步骤状态:" + echo " - 代码检出:${{ steps.install_pip_deps.outcome }}" + echo " - pip依赖安装:${{ steps.install_pip_deps.outcome }}" + echo " - 系统依赖安装:${{ steps.install_sys_deps.outcome }}" + echo " - SSH配置:${{ steps.config_ssh.outcome }}" + echo " - 部署执行:${{ steps.run_deploy.outcome }}" + + # 按失败步骤给出排查建议 + if [ "${{ steps.install_pip_deps.outcome }}" = "failure" ]; then + echo "📌 排查重点(pip依赖安装失败):" + echo " 1. 检查requirements.txt文件格式是否正确" + echo " 2. 检查清华源是否可访问:curl https://pypi.tuna.tsinghua.edu.cn/simple" + echo " 3. 检查依赖包名称/版本是否存在错误" + fi + + if [ "${{ steps.config_ssh.outcome }}" = "failure" ]; then + echo "📌 排查重点(SSH配置失败):" + echo " 1. 检查KEY私钥是否完整(包含BEGIN/END标记)" + echo " 2. 检查PASSPHRASE私钥密码是否正确" + echo " 3. 检查服务器公钥是否已添加到authorized_keys" + fi + + if [ "${{ steps.run_deploy.outcome }}" = "failure" ]; then + echo "📌 排查重点(部署执行失败):" + echo " 1. 检查SERVER_PASSWORD服务器密码是否正确" + echo " 2. 检查服务器42422端口是否开放" + echo " 3. 检查服务器项目目录是否存在:/home/luoxiaolei/neobot/NeoBot" + echo " 4. 查看服务器日志:journalctl -u neobot.service -n 50" + fi exit 1 + + # ========== 部署成功提示 ========== + - name: 部署成功提示 + if: success() + run: | + echo "✅ 部署成功!" + echo "📝 部署信息:" + echo " - 触发方式:${{ github.event_name }}" + echo " - 分支:${{ github.ref_name }}" + echo " - 提交ID:${{ github.sha }}" + echo " - 手动触发原因:${{ github.event.inputs.reason || '自动触发' }}"