在這個教學中,你會使用 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 內建的相依處理機制,確保項目以正確順序部署。 這使得在測試與生產環境中能夠持續且可重複地部署,無需人工介入。
步驟 1。 準備一個範例庫
- 下載壓縮檔 bulk-api-demo-zip 到你本機
- 範例壓縮檔包含:
- Azure DevOps 管線檔案(
deploy-using-bulk-api.yml) - 範例工作區,包含少量 Fabric 項目定義檔案 (
bulk-tutorial-dev)
- 將你的 Azure DevOps 儲存庫複製到本地機器,然後解壓縮到這個資料夾。
- 將新內容推送到 Azure DevOps 倉庫
步驟 2。 執行 Azure DevOps pipeline
2.1 變數群: bulkapi-group
這個變數群組儲存服務主體的詳細資訊,Azure 管線用它來驗證。
創建步驟
- 在你的 ADO 專案中,導覽至 Pipelines → Library 。
- 點擊 + 變數群組。
- 請命名:
bulkapi-group - 新增下列變數:
| 變數名稱 | 說明 |
|---|---|
AZURE_TENANT_ID |
服務負責人 - 租戶識別碼 |
AZURE_CLIENT_ID |
服務主體 - 客戶識別碼 |
AZURE_CLIENT_SECRET |
服務負責人 - 客戶秘密(標記為秘密) |
2.2 Azure DevOps Pipeline setup
在 Azure DevOps 中建立一個管線,參考您存放庫中的 deploy-using-bulk-api.yml - YAML 檔案。
Steps
導航至 管道 → 管道 → 新管道。
選擇 Azure Repos Git ,然後選擇你的儲存庫。
選擇 Existing Azure Pipelines YAML 檔案。
根據現有的代理池變更 代理池,例如,若要使用 Microsoft-Hosted 代理(基於 Linux),請使用:
vmImage: ubuntu-latest執行
管線完成後,
bulk-tutorial-testFabric 工作區包含已部署的項目。
⚠️ 權限提示: 管線第一次執行時,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 工作區。