diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..8ca17e9 --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,95 @@ +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