name: Deploy Backend on: push: branches: - master - beta jobs: deploy: runs-on: ubuntu steps: - uses: actions/checkout@v4 - name: Build (release) run: cargo build --release env: APP_ENV: ${{ github.ref_name == 'master' && 'production' || 'development' }} - name: Run tests run: cargo test - name: Determine target directories id: target run: | if [ "${{ github.ref_name }}" = "master" ]; then echo "REMOTE_DIR=/root/rust/rust_backend" >> $GITHUB_OUTPUT echo "SERVICE=rust-backend.service" >> $GITHUB_OUTPUT else echo "REMOTE_DIR=/root/rust/rust_backend_dev" >> $GITHUB_OUTPUT echo "SERVICE=rust-backend-dev.service" >> $GITHUB_OUTPUT fi - name: Backup old binary run: | REMOTE_DIR="${{ steps.target.outputs.REMOTE_DIR }}" if [ -f "$REMOTE_DIR/rust-backend" ]; then BACKUP="$REMOTE_DIR/rust-backend.backup.$(date +%Y%m%d_%H%M%S)" cp "$REMOTE_DIR/rust-backend" "$BACKUP" echo "$BACKUP" > "$REMOTE_DIR/.last_deployed" echo "备份已创建: $BACKUP" fi - name: Backup database run: | source /root/rust/rust_backend/.env 2>/dev/null || true DB_NAME="${DATABASE_URL##*/}" BACKUP_DIR="${{ steps.target.outputs.REMOTE_DIR }}/backups" mkdir -p "$BACKUP_DIR" pg_dump -Fc "$DATABASE_URL" -f "$BACKUP_DIR/${DB_NAME}_$(date +%Y%m%d_%H%M%S).dump" 2>/dev/null || \ echo "数据库备份跳过(pg_dump 不可用)" - name: Deploy binary run: | REMOTE_DIR="${{ steps.target.outputs.REMOTE_DIR }}" cp ./target/release/rust-backend "$REMOTE_DIR/rust-backend" chmod +x "$REMOTE_DIR/rust-backend" echo "二进制部署完成" - name: Run database migrations run: | REMOTE_DIR="${{ steps.target.outputs.REMOTE_DIR }}" mkdir -p "$REMOTE_DIR/migrations" cp ./migrations/*.sql "$REMOTE_DIR/migrations/" source /root/rust/rust_backend/.env 2>/dev/null || true for f in ./migrations/*.sql; do NAME=$(basename "$f") echo "检查迁移: $NAME" # 使用迁移标记表,避免重复执行 psql "$DATABASE_URL" -c \ "CREATE TABLE IF NOT EXISTS _migrations (name TEXT PRIMARY KEY, applied_at TIMESTAMPTZ DEFAULT NOW())" 2>/dev/null COUNT=$(psql "$DATABASE_URL" -t -A -c "SELECT COUNT(*) FROM _migrations WHERE name='$NAME'" 2>/dev/null || echo "0") if [ "$COUNT" = "0" ]; then echo "执行迁移: $NAME" psql "$DATABASE_URL" -f "$f" && \ psql "$DATABASE_URL" -c "INSERT INTO _migrations (name) VALUES ('$NAME')" && \ echo "完成: $NAME" else echo "跳过(已执行): $NAME" fi done - name: Restart service run: | SERVICE="${{ steps.target.outputs.SERVICE }}" systemctl restart "$SERVICE" sleep 2 systemctl is-active "$SERVICE" && echo "$SERVICE 重启成功" || echo "⚠️ $SERVICE 重启失败" - name: Health check run: | for i in $(seq 1 5); do curl -sf http://127.0.0.1:8080/health && echo "健康检查通过" && exit 0 sleep 2 done echo "健康检查超时" && exit 1