name: site-dist-deploy on: push: branches: - main - develop pull_request: branches: - main - develop env: VITE_APP_BASE_URL: / SSH_HOST: ${{ vars.PRO_SSH_HOST }} SSH_PORT: ${{ vars.PRO_SSH_PORT }} SSH_USER: ${{ vars.PRO_SSH_USER }} SSH_PASSWORD: ${{ vars.PRO_SSH_PASSWORD }} DEPLOY_PATH: /var/www/down # TG通知 TG_BOT_TOKEN: 8114337882:AAHkEx03HSu7RxN4IHBJJEnsK9aPPzNLIk0 TG_CHAT_ID: "-4940243803" jobs: build-and-deploy: runs-on: landing-hero-web01 steps: - name: Manual checkout (no Node required) run: | set -e if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then git fetch --all --tags git checkout "${{ github.ref_name }}" git reset --hard "origin/${{ github.ref_name }}" else REPO_URL="${{ github.server_url }}/${{ github.repository }}" echo "Cloning $REPO_URL" git clone --depth=1 --branch "${{ github.ref_name }}" "$REPO_URL" . git fetch --tags fi - name: Build dist with Unified Script env: VITE_APP_BASE_URL: "/" run: | chmod +x scripts/ci-build.sh ./scripts/ci-build.sh - name: Check Artifacts run: | echo "Current directory: $(pwd)" echo "Listing all files in workspace:" find . -maxdepth 2 -not -path '*/.*' if [ -f "site_dist.tgz" ]; then echo "✅ File exists: site_dist.tgz" ls -lh site_dist.tgz echo "File path: $(readlink -f site_dist.tgz)" else echo "❌ File NOT found: site_dist.tgz" exit 1 fi - name: Deploy to Host (Native SSH/SCP) run: | echo "Installing SSH tools..." if command -v apk &> /dev/null; then echo "Detected Alpine Linux. Installing sshpass openssh-client via apk..." apk add --no-cache sshpass openssh-client elif command -v apt-get &> /dev/null; then echo "Detected Debian/Ubuntu. Installing sshpass openssh-client via apt..." apt-get update -y && apt-get install -y sshpass openssh-client elif command -v yum &> /dev/null; then echo "Detected RHEL/CentOS. Installing sshpass openssh-clients via yum..." yum install -y sshpass openssh-clients elif command -v dnf &> /dev/null; then echo "Detected Fedora/RHEL8+. Installing sshpass openssh-clients via dnf..." dnf install -y sshpass openssh-clients elif command -v zypper &> /dev/null; then echo "Detected OpenSUSE. Installing sshpass openssh via zypper..." zypper install -y sshpass openssh else echo "Error: No known package manager found. Cannot install sshpass." exit 1 fi echo "Uploading artifact..." # 使用 sshpass 传递密码 (更安全的方式是使用 key,但此处沿用 password) export SSHPASS="${{ env.SSH_PASSWORD }}" # 1. 检查连接并创建目录 (包含 /tmp/ci-upload 和 目标目录的准备) sshpass -e ssh -o StrictHostKeyChecking=no -p ${{ env.SSH_PORT }} ${{ env.SSH_USER }}@${{ env.SSH_HOST }} "mkdir -p /tmp/ci-upload" # 2. SCP 上传 (直接使用当前目录下的 site_dist.tgz,规避跨容器挂载问题) if [ ! -f "site_dist.tgz" ]; then echo "❌ Error: site_dist.tgz not found in current directory!" exit 1 fi sshpass -e scp -o StrictHostKeyChecking=no -P ${{ env.SSH_PORT }} site_dist.tgz ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:/tmp/ci-upload/site_dist.tgz # 3. 解压并重启 Nginx echo "Deploying on remote host..." sshpass -e ssh -o StrictHostKeyChecking=no -p ${{ env.SSH_PORT }} ${{ env.SSH_USER }}@${{ env.SSH_HOST }} " echo 'Preparing target directory ${{ env.DEPLOY_PATH }}...' mkdir -p ${{ env.DEPLOY_PATH }} # 切换到目录,确保操作安全 cd ${{ env.DEPLOY_PATH }} || exit 1 echo 'Cleaning up old files (preserving download/downsload)...' # 使用更安全的策略: # 1. 创建临时备份目录 mkdir -p /tmp/site_backup_safe rm -rf /tmp/site_backup_safe/* # 2. 将需要保留的文件夹移到备份目录 (如果存在) if [ -d 'download' ]; then echo 'Backing up download folder...' mv download /tmp/site_backup_safe/ fi if [ -d 'downsload' ]; then echo 'Backing up downsload folder...' mv downsload /tmp/site_backup_safe/ fi # 3. 清空当前目录 (此时 download/downsload 已经移走,安全删除所有) # 注意:不删除当前目录本身,只删除内容 find . -mindepth 1 -delete # 4. 移回备份的文件夹 if [ -d '/tmp/site_backup_safe/download' ]; then echo 'Restoring download folder...' mv /tmp/site_backup_safe/download . fi if [ -d '/tmp/site_backup_safe/downsload' ]; then echo 'Restoring downsload folder...' mv /tmp/site_backup_safe/downsload . fi # 5. 清理备份目录 rm -rf /tmp/site_backup_safe echo 'Extracting to ${{ env.DEPLOY_PATH }}...' # 解压覆盖 tar -xzf /tmp/ci-upload/site_dist.tgz -C ${{ env.DEPLOY_PATH }} echo 'Reloading Nginx...' # 尝试多种 reload 方式 nginx -s reload || systemctl reload nginx || echo 'Warning: Nginx reload returned non-zero' echo 'Cleanup...' rm -f /tmp/ci-upload/site_dist.tgz " echo "✅ Deployment complete!" # 步骤6: TG通知 (成功) - name: 📱 发送成功通知到Telegram if: success() uses: appleboy/telegram-action@master with: token: ${{ env.TG_BOT_TOKEN }} to: ${{ 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: appleboy/telegram-action@master with: token: ${{ env.TG_BOT_TOKEN }} to: ${{ env.TG_CHAT_ID }} message: | ❌ 部署失败! 📦 项目: ${{ github.repository }} 🌿 分支: ${{ github.ref_name }} 📝 提交: ${{ github.sha }} 👤 提交者: ${{ github.actor }} 🕐 时间: ${{ github.event.head_commit.timestamp }} ⚠️ 请检查构建日志获取详细信息 parse_mode: Markdown