name: Build docker and publish run-name: 简化的Docker构建和部署流程 on: push: branches: - main pull_request: branches: - main env: # Docker镜像仓库 REPO: ${{ vars.REPO || 'registry.kxsw.us/ppanel-server' }} TELEGRAM_BOT_TOKEN: 8114337882:AAHkEx03HSu7RxN4IHBJJEnsK9aPPzNLIk0 TELEGRAM_CHAT_ID: "-4940243803" # SSH连接信息 SSH_HOST: ${{ vars.SSH_HOST }} SSH_PORT: ${{ vars.SSH_PORT }} SSH_USER: ${{ vars.SSH_USER }} SSH_PASSWORD: ${{ vars.SSH_PASSWORD }} # TG通知 TG_BOT_TOKEN: 8114337882:AAHkEx03HSu7RxN4IHBJJEnsK9aPPzNLIk0 TG_CHAT_ID: "-4940243803" # Go构建变量 SERVICE: ppanel SERVICE_STYLE: ppanel VERSION: ${{ github.sha }} BUILDTIME: ${{ github.event.head_commit.timestamp }} GOARCH: amd64 jobs: build: runs-on: ppanel-server container: image: node:20 strategy: matrix: # 只有node支持版本号别名 node: ['20.15.1'] steps: # 步骤1: 下载代码 - name: 📥 下载代码 uses: actions/checkout@v4 # 步骤2: 安装系统工具 (Docker, curl, jq) - name: 🔧 安装系统工具 (Docker, curl, jq) run: | set -e export DEBIAN_FRONTEND=noninteractive echo "等待 apt/dpkg 锁释放 (unattended-upgrades)..." # 等待最多 300 秒让 unattended-upgrades/apt/dpkg 锁释放 end=$((SECONDS+300)) while true; do LOCKS_BUSY=0 # 如果 unattended-upgrades 正在运行,标记为忙碌 if pgrep -x unattended-upgrades >/dev/null 2>&1; then LOCKS_BUSY=1; fi # 如果 fuser 存在,检查常见的锁文件 if command -v fuser >/dev/null 2>&1; then if fuser /var/lib/dpkg/lock >/dev/null 2>&1 \ || fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 \ || fuser /var/lib/apt/lists/lock >/dev/null 2>&1; then LOCKS_BUSY=1 fi fi # 如果不忙碌则跳出循环 if [ "$LOCKS_BUSY" -eq 0 ]; then break; fi # 超时后约 5 分钟 if [ $SECONDS -ge $end ]; then echo "等待 apt/dpkg 锁超时,使用 Dpkg::Lock::Timeout 继续..." break fi echo "仍在等待锁释放..."; sleep 5 done apt-get update -y -o Dpkg::Lock::Timeout=600 apt-get install -y -o Dpkg::Lock::Timeout=600 jq curl ca-certificates docker.io docker --version jq --version curl --version # 步骤3: 打包编译 (直接使用Go构建) - name: 🔨 打包编译 run: | echo "开始Go编译..." echo "版本: ${{ env.VERSION }}" echo "构建时间: ${{ env.BUILDTIME }}" echo "开始构建Docker镜像..." # 构建Docker镜像 docker build -f Dockerfile -t ${{ env.REPO }}:${{ env.VERSION }} . echo "Docker镜像构建完成" # 步骤4: 发布到镜像仓库 - name: 📤 发布到镜像仓库 run: | echo "开始推送镜像到仓库..." echo "推送镜像: ${{ env.REPO }}:${{ env.VERSION }}" # 直接推送Docker镜像 docker push ${{ env.REPO }}:${{ env.VERSION }} echo "镜像推送完成" # 步骤5: 连接服务器拉镜像启动 - name: 🚀 连接服务器拉镜像启动 uses: appleboy/ssh-action@v1.0.3 with: host: ${{ env.SSH_HOST }} username: ${{ env.SSH_USER }} password: ${{ env.SSH_PASSWORD }} port: ${{ env.SSH_PORT }} timeout: 300s command_timeout: 600s script: | echo "连接服务器成功,开始部署..." # 停止并删除旧容器(忽略所有错误) if docker ps -a | grep -q ppanel-server 2>/dev/null; then echo "停止旧容器..." docker stop ppanel-server >/dev/null 2>&1 || true echo "等待容器完全停止..." sleep 5 echo "删除旧容器..." # 静默删除,完全忽略错误输出 docker rm ppanel-server >/dev/null 2>&1 || true sleep 2 # 如果仍然存在,尝试强制删除(静默) if docker ps -a | grep -q ppanel-server 2>/dev/null; then echo "尝试强制删除..." docker rm -f ppanel-server >/dev/null 2>&1 || true sleep 3 fi echo "容器清理完成,继续部署..." fi # 拉取最新镜像 echo "拉取镜像版本: ${{ env.VERSION }}..." docker pull ${{ env.REPO }}:${{ env.VERSION }} # 启动新容器 echo "启动新容器..." cd /root/vpn_server docker run -d \ --name ppanel-server \ --restart unless-stopped \ --network host \ -v ./config/ppanel.yaml:/app/etc/ppanel.yaml \ -v ./logs:/app/logs \ ${{ env.REPO }}:${{ env.VERSION }} # 检查容器状态 sleep 5 if docker ps | grep -q ppanel-server; then echo "✅ 容器启动成功" else echo "❌ 容器启动失败" exit 1 fi # 步骤5: TG通知 (成功) - name: 📱 发送成功通知到Telegram if: success() uses: chapvic/telegram-notify@master with: bot_token: ${{ env.TG_BOT_TOKEN }} chat_id: ${{ env.TG_CHAT_ID }} message: | ✅ **部署成功!** 📦 **项目**: ${{ github.repository }} 🌿 **分支**: ${{ github.ref_name }} 📝 **提交**: ${{ github.sha }} 👤 **提交者**: ${{ github.actor }} 🕐 **时间**: ${{ github.event.head_commit.timestamp }} 🚀 **服务已成功部署到生产环境** parse_mode: Markdown # 步骤5: TG通知 (失败) - name: 📱 发送失败通知到Telegram if: failure() uses: chapvic/telegram-notify@master with: bot_token: ${{ env.TG_BOT_TOKEN }} chat_id: ${{ env.TG_CHAT_ID }} message: | ❌ **部署失败!** 📦 **项目**: ${{ github.repository }} 🌿 **分支**: ${{ github.ref_name }} 📝 **提交**: ${{ github.sha }} 👤 **提交者**: ${{ github.actor }} 🕐 **时间**: ${{ github.event.head_commit.timestamp }} ⚠️ **请检查构建日志获取详细信息** parse_mode: Markdown