共用方式為


教學 - Fabric CI/CD 搭配批量匯入項目定義 API

在這個教學中,你會使用 Azure DevOps 管線,利用 Bulk import 項目定義 API 從 Git 資料夾部署項目。 Git 資料夾包含連接 Git 的 開發 工作區的項目定義,管線會將它們部署到未連接 Git 的 測試 工作區。

先決條件

  • Azure DevOps Azure Project 與 repository + 權限,用以配置 Azure DevOps 管線並建立變數群組。
  • Fabric 工作區 名稱: bulk-tutorial-test - 部署目標工作區
  • Service Principal(SPN) -一個帶有用戶端秘密的 Entra ID(Azure AD)應用程式註冊,需要有用戶端 ID、用戶端秘密和租戶 ID。
  • 服務主體在 Fabric 工作區擁有貢獻者權限bulk-tutorial-test
  • 服務主體的 Fabric 管理員設定 - Fabric 管理員必須在 Fabric 管理入口網站的租戶設定中啟用「服務主體可以使用 Fabric API」

💡 小提示:要在 Fabric 中啟用服務主體存取權,Fabric 管理員必須在 Fabric 管理入口網站的租戶設定中啟用「服務主體可以使用 Fabric API」。

背景

基於 Git 的建置環境部署中,跨 Microsoft Fabric 工作空間的部署由中央 Git 倉庫驅動,Fabric 項目定義被視為程式碼,並透過結構化的發佈流程推廣。 所有環境——開發、測試與生產環境——都對齊於同一個主分支,而每個階段則透過專用的建置與發佈管線獨立部署。

管線通常從開發工作區透過 Fabric Git 整合匯出 Fabric 元件定義開始。 這些定義可透過自動化檢查、拉取請求審查及政策執行在推廣前,在建置環境中進行驗證。 (本教學未涵蓋)

部署期間,管線會呼叫 Bulk Import API,將核准的項目定義推廣至目標工作區。 API 支援建立新項目及更新現有項目,並依賴 Fabric 內建的相依處理機制,確保項目以正確順序部署。 這使得在測試與生產環境中能夠持續且可重複地部署,無需人工介入。

建議使用批量匯入項目定義 API 的建置與發布流程。

步驟 1。 準備一個範例庫

  1. 下載壓縮檔 bulk-api-demo-zip 到你本機
  2. 範例壓縮檔包含:
  • Azure DevOps 管線檔案(deploy-using-bulk-api.yml
  • 範例工作區,包含少量 Fabric 項目定義檔案 (bulk-tutorial-dev
  1. 將你的 Azure DevOps 儲存庫複製到本地機器,然後解壓縮到這個資料夾。
  2. 將新內容推送到 Azure DevOps 倉庫

步驟 2。 執行 Azure DevOps pipeline

2.1 變數群: bulkapi-group

這個變數群組儲存服務主體的詳細資訊,Azure 管線用它來驗證。

創建步驟

  1. 在你的 ADO 專案中,導覽至 Pipelines → Library
  2. 點擊 + 變數群組
  3. 請命名:bulkapi-group
  4. 新增下列變數:
變數名稱 說明
AZURE_TENANT_ID 服務負責人 - 租戶識別碼
AZURE_CLIENT_ID 服務主體 - 客戶識別碼
AZURE_CLIENT_SECRET 服務負責人 - 客戶秘密(標記為秘密)

2.2 Azure DevOps Pipeline setup

在 Azure DevOps 中建立一個管線,參考您存放庫中的 deploy-using-bulk-api.yml - YAML 檔案。

Steps

  1. 導航至 管道 → 管道新管道

  2. 選擇 Azure Repos Git ,然後選擇你的儲存庫。

  3. 選擇 Existing Azure Pipelines YAML 檔案

  4. 根據現有的代理池變更 代理池,例如,若要使用 Microsoft-Hosted 代理(基於 Linux),請使用:vmImage: ubuntu-latest

  5. 執行

  6. 管線完成後,bulk-tutorial-test Fabric 工作區包含已部署的項目。

⚠️ 權限提示: 管線第一次執行時,ADO 可能會提示你授權存取變數群組和環境。 ADO 管理員可以在管線→設定中預先授權這些資料。

⚠️ 製作提示: 此管道示範部署到測試環境。 生產部署也可以採用類似流程,並在測試環境中成功驗證後新增批准閘門。

3. 程式碼深度分析:ADO 管線 YAML

檔案:deploy-using-bulk-api.yml- 位於 Azure DevOps 倉庫中。

以下是完整的流程及逐行註解。

# ──────────────────────────────────────────────────────────────
# TRIGGER: pipeline start on every push to main branch
# ──────────────────────────────────────────────────────────────
trigger:
  branches:
    include:
    - main

# ─────────────────────────────────────────────────────────────────────────────────────────
# Define the Azure DevOps agent, use of the variable group, and parameters initialization
# ─────────────────────────────────────────────────────────────────────────────────────────
pool:
  vmImage: ubuntu-latest

variables:
  - group: bulkapi-group
  - name: test_workspace_to_deploy
    value: "bulk-tutorial-test"

# ────────────────────────────────────────────────────────────────
# Step 1: Checkout & Get Fabric API token using service principal
# ────────────────────────────────────────────────────────────────
stages:
  - stage: Deploy_Test
    jobs:
      - job: Deploy
        displayName: 'Deploy using Bulk-API'
        steps:
        - checkout: self
        - script: |
            TOKEN=$(curl -s -X POST "https://login.microsoftonline.com/$(AZURE_TENANT_ID)/oauth2/v2.0/token" \
              -H "Content-Type: application/x-www-form-urlencoded" \
              -d "client_id=$(AZURE_CLIENT_ID)&client_secret=$(AZURE_CLIENT_SECRET)&scope=https://api.fabric.microsoft.com/.default&grant_type=client_credentials" \
              | jq -r '.access_token')
            echo "##vso[task.setvariable variable=FABRIC_TOKEN;issecret=true]$TOKEN"
          displayName: 'Get Fabric API token using service principal'

# ────────────────────────────────────────────────────────────────────
# Step 2: Build REQUEST_BODY and call Bulk Import Item Definitions API 
# ────────────────────────────────────────────────────────────────────
        - script: |
            ## Get workspace ID from workspace name to deploy
            WORKSPACE_ID=$(curl -s -H "Authorization: Bearer $(FABRIC_TOKEN)" \
              "https://api.fabric.microsoft.com/v1/workspaces" \
              | jq -r '.value[] | select(.displayName=="'"$(test_workspace_to_deploy)"'") | .id')

            if [ -z "$WORKSPACE_ID" ] || [ "$WORKSPACE_ID" = "null" ]; then
              echo "##vso[task.logissue type=error]Workspace '$(test_workspace_to_deploy)' not found"
              exit 1
            fi
            echo "Workspace ID: $WORKSPACE_ID"

            ## Iterate through each file in the specified folder, read its contents, and encode them in Base64.
            BASE_DIR="$(Build.SourcesDirectory)/bulk-tutorial-dev"

            PARTS_JSON="[]"
            while IFS= read -r -d '' FILE; do
              REL_PATH="/${FILE#$BASE_DIR/}"
              PAYLOAD=$(base64 -w 0 "$FILE" 2>/dev/null || base64 "$FILE")
              PARTS_JSON=$(echo "$PARTS_JSON" | jq \
                --arg path "$REL_PATH" \
                --arg payload "$PAYLOAD" \
                '. + [{path: $path, payload: $payload, payloadType: "InlineBase64"}]')
            done < <(find "$BASE_DIR" -type f -print0)

            ## Prepare the request body with base64 encoded items
            REQUEST_BODY=$(jq -n \
              --argjson parts "$PARTS_JSON" \
              '{
                definitionParts: $parts,
                options: {
                  allowPairingByName: false
                }
              }')

            echo "Request body built with $(echo "$PARTS_JSON" | jq length) parts"

            API_URL="https://api.fabric.microsoft.com/v1/workspaces/$WORKSPACE_ID/importItemDefinitions?beta=true"
            echo "Calling Bulk Import Item definition API: $API_URL"

            # Call the Bulk Import API and capture response headers
            HEADER_FILE=$(mktemp)
            RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
              "$API_URL" \
              -H "Authorization: Bearer $(FABRIC_TOKEN)" \
              -H "Content-Type: application/json" \
              -D "$HEADER_FILE" \
              -d "$REQUEST_BODY")

            HTTP_CODE=$(echo "$RESPONSE" | tail -1)
            BODY=$(echo "$RESPONSE" | sed '$d')

            echo "HTTP Status: $HTTP_CODE"
            echo "$BODY" | jq . 2>/dev/null || echo "$BODY"

            # Extract operation ID from response headers
            OPERATION_ID=$(grep -i '^x-ms-operation-id:' "$HEADER_FILE" | awk '{print $2}' | tr -d '\r\n ')
            echo "Operation ID: $OPERATION_ID"
            rm -f "$HEADER_FILE"

            # Set as variable for the next step
            echo "##vso[task.setvariable variable=OPERATION_ID]$OPERATION_ID"

            if [ "$HTTP_CODE" -ge 400 ]; then
              echo "##vso[task.logissue type=error]Bulk import failed with HTTP $HTTP_CODE"
              exit 1
            fi
          displayName: 'Deploy to $(test_workspace_to_deploy)'

# ────────────────────────────────────────
# Step 3: Wait for Deployment to complete 
# ────────────────────────────────────────
        - script: |
            echo "Polling operation: $(OPERATION_ID)"

            while true; do
              RESULT=$(curl -s -H "Authorization: Bearer $(FABRIC_TOKEN)" \
                "https://api.fabric.microsoft.com/v1/operations/$(OPERATION_ID)/result")

              # Check if importItemDefinitionsDetails exists and is not null
              HAS_DETAILS=$(echo "$RESULT" | jq 'has("importItemDefinitionsDetails") and (.importItemDefinitionsDetails != null)')

              if [ "$HAS_DETAILS" = "true" ]; then
                echo "Operation complete. Result:"
                echo "$RESULT" | jq .
                break
              fi

              echo "Operation not yet completed. Waiting 10 seconds..."
              sleep 10
            done
          displayName: 'Poll LRO until complete'

4. 摘要

本教學示範如何使用 Bulk Import 項目定義 API 作為部署機制。 它展示了如何從連接到 Git 倉庫的開發工作區部署項目,方法是擷取倉庫內容,轉換成所需的 API 輸入,然後部署到一個不連接 Git 的測試 Fabric 工作區。