Git自动化部署教程:GitHub Actions + 香港VPS实现代码推送自动上线

手动部署代码既耗时又容易出错。通过GitHub Actions实现CI/CD(持续集成/持续部署),每次代码推送到main分支后自动测试、构建并部署到香港VPS,整个过程无需人工介入。本文给出完整的配置方案。

一、自动化部署流程架构

开发者本地 git push → GitHub仓库
                           ↓
                   GitHub Actions触发
                           ↓
                   运行测试(可选)
                           ↓
                   SSH连接香港VPS
                           ↓
                   拉取最新代码
                           ↓
                   安装依赖、构建
                           ↓
                   重启应用服务
                           ↓
                   部署完成通知

二、服务器准备:创建专用部署用户

# 在香港VPS上创建专用部署用户(非root,安全隔离)
useradd -m -s /bin/bash deploy
usermod -aG www-data deploy  # 加入web组

# 切换到deploy用户,生成SSH密钥对
su - deploy
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_actions -N ""

# 将公钥添加到authorized_keys
cat ~/.ssh/github_actions.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys

# 查看私钥(需要复制到GitHub Secrets)
cat ~/.ssh/github_actions

三、配置GitHub Secrets

在GitHub仓库页面 → Settings → Secrets and variables → Actions → New repository secret,添加以下密钥:

Secret名称
SERVER_HOST香港VPS的公网IP或域名
SERVER_USERdeploy(上一步创建的用户)
SERVER_SSH_KEY私钥内容(~/.ssh/github_actions的全部内容)
SERVER_PORTSSH端口(如2233)
APP_DIR/var/www/html(项目目录)

四、GitHub Actions Workflow 文件

Node.js项目部署(.github/workflows/deploy.yml)

name: Deploy to Hong Kong VPS

on:
  push:
    branches: [ main ]   # 推送到main分支时触发
  workflow_dispatch:      # 允许手动触发

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci --production

      - name: Run tests
        run: npm test
        continue-on-error: false  # 测试失败则停止部署

      - name: Deploy to server
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          port: ${{ secrets.SERVER_PORT }}
          script: |
            set -e  # 任何命令失败则退出
            
            cd ${{ secrets.APP_DIR }}
            
            # 拉取最新代码
            git fetch origin main
            git reset --hard origin/main
            
            # 安装/更新依赖
            npm ci --production
            
            # 零停机重启(PM2 reload不会中断现有连接)
            pm2 reload all --update-env
            
            echo "✅ 部署完成:$(date)"

      - name: Notify on success
        if: success()
        run: echo "部署成功!"

      - name: Notify on failure
        if: failure()
        run: echo "部署失败,请检查日志!"

PHP/WordPress项目部署

name: Deploy WordPress to VPS

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4

      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          port: ${{ secrets.SERVER_PORT }}
          script: |
            set -e
            cd ${{ secrets.APP_DIR }}
            
            # 拉取代码(排除敏感文件)
            git fetch origin main
            git reset --hard origin/main
            
            # 安装Composer依赖(如有)
            if [ -f composer.json ]; then
              composer install --no-dev --optimize-autoloader
            fi
            
            # 更新WordPress数据库(如有迁移)
            wp core update-db --allow-root 2>/dev/null || true
            
            # 刷新OPcache缓存
            php -r "opcache_reset();" 2>/dev/null || true
            
            # 清除WordPress缓存
            wp cache flush --allow-root 2>/dev/null || true
            
            # 重载PHP-FPM(不中断服务)
            systemctl reload php8.1-fpm
            
            echo "✅ WordPress部署完成"

五、零停机部署策略

蓝绿部署方案

#!/bin/bash
# /usr/local/bin/blue-green-deploy.sh

APP_DIR="/var/www"
CURRENT_LINK="$APP_DIR/current"
RELEASES_DIR="$APP_DIR/releases"
RELEASE_DIR="$RELEASES_DIR/$(date +%Y%m%d_%H%M%S)"

# 创建新版本目录
mkdir -p "$RELEASE_DIR"

# 拉取代码到新目录
git clone --depth 1 --branch main git@github.com:你的用户名/项目.git "$RELEASE_DIR"

# 安装依赖
cd "$RELEASE_DIR"
npm ci --production

# 创建共享文件软链接(如.env、uploads目录)
ln -sf "$APP_DIR/shared/.env" "$RELEASE_DIR/.env"
ln -sf "$APP_DIR/shared/uploads" "$RELEASE_DIR/public/uploads"

# 原子切换(软链接切换是原子操作,不会有中间状态)
ln -sfn "$RELEASE_DIR" "$CURRENT_LINK"

# 重启应用(指向新目录)
pm2 reload all

# 保留最近5个版本,删除旧版本
ls -dt "$RELEASES_DIR"/* | tail -n +6 | xargs rm -rf

echo "✅ 蓝绿部署完成:$RELEASE_DIR"

六、回滚机制

#!/bin/bash
# /usr/local/bin/rollback.sh
# 快速回滚到上一个版本

APP_DIR="/var/www"
CURRENT_LINK="$APP_DIR/current"
RELEASES_DIR="$APP_DIR/releases"

# 获取上一个版本
PREVIOUS=$(ls -dt "$RELEASES_DIR"/* | sed -n '2p')

if [ -z "$PREVIOUS" ]; then
    echo "❌ 没有可回滚的版本"
    exit 1
fi

echo "回滚到:$PREVIOUS"
ln -sfn "$PREVIOUS" "$CURRENT_LINK"
pm2 reload all

echo "✅ 回滚完成"
# 在GitHub Actions中添加手动回滚触发
# 或直接在服务器执行
/usr/local/bin/rollback.sh

七、部署通知配置

<code"># 在workflow中添加钉钉通知
      - name: 发送钉钉通知
        if: always()
        run: |
          STATUS="${{ job.status }}"
          if [ "$STATUS" = "success" ]; then
            EMOJI="✅"
            TEXT="部署成功"
          else
            EMOJI="❌"
            TEXT="部署失败"
          fi
          
          curl -X POST "${{ secrets.DINGTALK_WEBHOOK }}" \
            -H "Content-Type: application/json" \
            -d "{
              \"msgtype\": \"text\",
              \"text\": {
                \"content\": \"$EMOJI $TEXT\n项目:${{ github.repository }}\n分支:${{ github.ref_name }}\n提交:${{ github.sha }}\n时间:$(date '+%Y-%m-%d %H:%M:%S')\"
              }
            }"

八、总结

GitHub Actions + 香港VPS的自动化部署方案,整个配置过程约1小时,完成后每次 git push 自动触发部署,开发效率显著提升。配合蓝绿部署和回滚机制,线上事故恢复时间从分钟级压缩到秒级。IDC.Net的香港VPS网络稳定,SSH连接从GitHub Actions节点延迟低,是自动化部署的可靠目标服务器。

THE END