diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b4741c7..b343d6d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,249 +1,57 @@ -name: 部署到生产环境 +name: Auto Deploy NeoBot (Full Env Secrets) +# 触发条件:推送到main分支 或 手动触发 on: push: branches: [ main ] - pull_request: - branches: [ main ] workflow_dispatch: - inputs: - reason: - description: '手动触发部署的原因' - required: false - default: '手动部署' jobs: - deploy: + deploy-to-server: + # 关联你的仓库环境(ENV) + environment: ENV runs-on: ubuntu-latest - environment: SSH-KEY - timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - name: 检查环境密钥配置 + run: | + echo "✅ 已关联环境: ${{ github.environment }}" + echo "✅ API_URL 密钥是否存在: ${{ secrets.API_URL != '' }}" + echo "✅ API_TOKEN 密钥是否存在: ${{ secrets.NEOBOT_DEPLOY_TOKEN != '' }}" - # ========== 新增:检出代码失败时的错误处理 ========== - - name: 处理代码检出失败 - if: failure() - run: | - echo "❌ 代码检出失败!请检查仓库权限或网络问题" - exit 1 - # ========== 原有步骤:安装系统依赖工具(强化错误处理) ========== - - name: 安装依赖工具 - id: install_sys_deps - run: | - 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 安装成功" + - name: 调用部署API + env: + # 从环境密钥中读取API地址和Token(均为密文) + API_URL: ${{ secrets.API_URL }} + API_TOKEN: ${{ secrets.NEOBOT_DEPLOY_TOKEN }} + run: | + # 安装jq用于解析JSON + sudo apt-get update && sudo apt-get install -y jq + + # 打印关键信息(脱敏,仅验证是否读取到值) + echo "📌 调用的API地址(脱敏): $(echo $API_URL | sed 's/http:\/\///; s/\/deploy//')" + + # 发送POST请求到部署API(所有配置均来自密钥) + RESPONSE=$(curl -s -X POST \ + $API_URL \ + -H "Content-Type: application/json" \ + -H "X-API-Token: $API_TOKEN" \ + -d '{"script_name":"deploy.sh"}') + + # 打印完整响应(便于调试) + echo "📝 API响应详情:" + echo $RESPONSE | jq . + + # 解析status字段判断部署结果 + STATUS=$(echo $RESPONSE | jq -r '.status') + if [ "$STATUS" = "success" ]; then + echo "✅ 部署成功!" + exit 0 else - echo "❌ $TOOL 安装失败" + echo "❌ 部署失败!错误信息:$(echo $RESPONSE | jq -r '.message')" 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: | - set -euo pipefail - echo "=== 开始配置SSH密钥 ===" - - # 创建SSH目录并严格控制权限 - mkdir -p ~/.ssh - chmod 700 ~/.ssh - - # 处理私钥换行符问题 - echo "${{ secrets.KEY }}" | tr -d '\r' > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - - # 启动ssh-agent并加载私钥 - eval $(ssh-agent -s) - export SSH_AGENT_PID SSH_AUTH_SOCK - - echo "🔑 加载SSH私钥..." - expect -c " - set timeout 15 - spawn ssh-add ~/.ssh/id_rsa - expect { - \"Enter passphrase for /home/runner/.ssh/id_rsa:\" { - send \"${{ secrets.PASSPHRASE }}\r\" - exp_continue - } - \"Identity added: /home/runner/.ssh/id_rsa\" { - puts \"✅ 私钥加载成功\" - exit 0 - } - \"Bad passphrase, try again\" { - puts \"❌ 私钥密码错误(PASSPHRASE)\" - exit 1 - } - timeout { - puts \"❌ 私钥加载超时\" - exit 1 - } - eof { - puts \"❌ 私钥加载失败\" - exit 1 - } - } - " || { echo "❌ 私钥加载失败,终止流程"; exit 1; } - - # 配置SSH免主机检查 - cat > ~/.ssh/config << EOF - StrictHostKeyChecking no - UserKnownHostsFile /dev/null - GlobalKnownHostsFile /dev/null - ConnectTimeout 30 - EOF - chmod 600 ~/.ssh/config - echo "✅ SSH密钥配置完成" - continue-on-error: false - - # ========== 原有步骤:执行部署(强化错误处理) ========== - - name: 执行部署 - id: run_deploy - run: | - set -euo pipefail - echo "=== 开始执行服务器部署 ===" - - # 定义部署命令(抽离便于维护) - DEPLOY_CMD=$(cat << 'EOF' - set -exuo pipefail - echo "=== 服务器部署开始($(date))===" - - # 服务器端也配置清华源(可选,如需在服务器安装pip依赖) - pip3.14 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 - - # 切换到项目目录 - cd /home/luoxiaolei/neobot/NeoBot || { echo "❌ 项目目录不存在"; exit 1; } - echo "📁 当前目录:$(pwd)" - - # 修复文件权限 - echo "🔧 修复文件权限..." - echo "${SERVER_PASSWORD}" | sudo -S -k -p '' chown -R "${SERVER_USER}":"${SERVER_USER}" /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.14依赖安装失败"; exit 1; } - echo "✅ pip3.14依赖安装完成" - 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 "❌ 部署失败!详细排查信息:" - 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 || '自动触发' }}" + - name: 部署失败通知(可选) + if: failure() + run: | + echo "⚠️ 部署失败,可在此添加通知逻辑"