deployment
Implements CI/CD pipelines and DevOps practices for Power BI. Use for automated validation, testing, and deployment of PBIP projects.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Implements CI/CD pipelines and DevOps practices for Power BI. Use for automated validation, testing, and deployment of PBIP projects.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | deployment |
| description | Implements CI/CD pipelines and DevOps practices for Power BI. Use for automated validation, testing, and deployment of PBIP projects. |
This skill helps implement CI/CD pipelines and DevOps practices for Power BI Desktop Projects (PBIP).
┌─────────┐ ┌──────────┐ ┌─────────┐ ┌────────┐
│ Build │ → │ Validate │ → │ Test │ → │ Deploy │
└─────────┘ └──────────┘ └─────────┘ └────────┘
│ │ │ │
Compile BPA Rules RLS Test Publish to
TMDL/PBIR DAX Check Data Check Power BI
| Tool | Purpose |
|---|---|
| Tabular Editor CLI | TMDL validation, BPA checks |
| Power BI REST API | Publish, refresh, admin |
| pbi-tools | Alternative PBIX/PBIP tooling |
| Fabric Git Integration | Native Git support |
main (production)
↑
release/v1.0
↑
develop
↑
feature/add-sales-measures
# GitHub branch protection
main:
required_reviews: 2
require_status_checks: true
required_checks:
- bpa-validation
- tmdl-syntax
develop:
required_reviews: 1
require_status_checks: true
<type>(<scope>): <description>
Types:
- feat: New feature
- fix: Bug fix
- refactor: Code refactoring
- docs: Documentation
- test: Tests
- ci: CI/CD changes
Examples:
feat(dax): add YoY% time intelligence measures
fix(model): correct relationship cardinality
refactor(query): optimize Sales query for folding
# .github/workflows/validate.yml
name: Validate PBIP
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
validate:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Tabular Editor
run: |
choco install tabular-editor -y
- name: Validate TMDL Syntax
run: |
# Find semantic model folder
$modelPath = Get-ChildItem -Recurse -Filter "*.pbism" |
Select-Object -First 1 |
Split-Path -Parent
# Validate with Tabular Editor
TabularEditor.exe "$modelPath" -S
- name: Run BPA Rules
run: |
$modelPath = Get-ChildItem -Recurse -Filter "*.pbism" |
Select-Object -First 1 |
Split-Path -Parent
# Run BPA with rules file
TabularEditor.exe "$modelPath" `
-A "BPA-Rules.json" `
-V
continue-on-error: false
# .github/workflows/cicd.yml
name: Power BI CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
TENANT_ID: ${{ secrets.PBI_TENANT_ID }}
CLIENT_ID: ${{ secrets.PBI_CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.PBI_CLIENT_SECRET }}
WORKSPACE_ID: ${{ secrets.PBI_WORKSPACE_ID }}
jobs:
validate:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install Tabular Editor
run: choco install tabular-editor -y
- name: Validate TMDL
run: |
$model = (Get-ChildItem -Recurse -Filter "definition.pbism" |
Select-Object -First 1).DirectoryName
TabularEditor.exe $model -S
- name: Run BPA
run: |
$model = (Get-ChildItem -Recurse -Filter "definition.pbism" |
Select-Object -First 1).DirectoryName
TabularEditor.exe $model -A BPA-Rules.json -V
deploy:
needs: validate
if: github.ref == 'refs/heads/main'
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install Power BI Tools
run: |
Install-Module -Name MicrosoftPowerBIMgmt -Force -Scope CurrentUser
- name: Authenticate to Power BI
run: |
$password = ConvertTo-SecureString "$env:CLIENT_SECRET" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($env:CLIENT_ID, $password)
Connect-PowerBIServiceAccount -ServicePrincipal -Credential $credential -TenantId $env:TENANT_ID
- name: Deploy to Workspace
run: |
# Deploy using Power BI REST API
# Note: Direct PBIP deployment requires Fabric Git integration
# This example shows dataset refresh trigger
Invoke-PowerBIRestMethod -Method POST `
-Url "groups/$env:WORKSPACE_ID/datasets/{dataset-id}/refreshes"
# azure-pipelines.yml
trigger:
- main
- develop
pool:
vmImage: 'windows-latest'
stages:
- stage: Validate
displayName: 'Validate PBIP'
jobs:
- job: ValidateTMDL
displayName: 'Validate TMDL Syntax'
steps:
- task: PowerShell@2
displayName: 'Install Tabular Editor'
inputs:
targetType: 'inline'
script: |
choco install tabular-editor -y
- task: PowerShell@2
displayName: 'Validate Model'
inputs:
targetType: 'inline'
script: |
$modelPath = Get-ChildItem -Recurse -Filter "definition.pbism" |
Select-Object -First 1 |
Split-Path -Parent
TabularEditor.exe $modelPath -S
- task: PowerShell@2
displayName: 'Run BPA'
inputs:
targetType: 'inline'
script: |
$modelPath = Get-ChildItem -Recurse -Filter "definition.pbism" |
Select-Object -First 1 |
Split-Path -Parent
TabularEditor.exe $modelPath -A "$(Build.SourcesDirectory)/BPA-Rules.json" -V
- stage: Deploy
displayName: 'Deploy to Power BI'
dependsOn: Validate
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployToPowerBI
displayName: 'Deploy to Production'
environment: 'Production'
strategy:
runOnce:
deploy:
steps:
- task: PowerShell@2
displayName: 'Deploy to Service'
inputs:
targetType: 'inline'
script: |
# Deployment script here
env:
PBI_TENANT_ID: $(PBI_TENANT_ID)
PBI_CLIENT_ID: $(PBI_CLIENT_ID)
PBI_CLIENT_SECRET: $(PBI_CLIENT_SECRET)
{
"rules": [
{
"id": "NO_IMPLICIT_MEASURES",
"name": "No Implicit Measures",
"category": "Performance",
"severity": 3,
"scope": "Model",
"expression": "Model.DiscourageImplicitMeasures == true",
"fixExpression": "Model.DiscourageImplicitMeasures = true",
"description": "Implicit measures should be disabled"
},
{
"id": "MEASURE_DESCRIPTION",
"name": "Measures Should Have Descriptions",
"category": "Documentation",
"severity": 2,
"scope": "Measure",
"expression": "!string.IsNullOrWhiteSpace(Description)",
"description": "All measures should have a description"
},
{
"id": "NO_BIDIRECTIONAL",
"name": "Avoid Bidirectional Relationships",
"category": "Performance",
"severity": 2,
"scope": "Relationship",
"expression": "CrossFilteringBehavior != CrossFilteringBehavior.BothDirections",
"description": "Bidirectional relationships impact performance"
},
{
"id": "USE_DIVIDE",
"name": "Use DIVIDE Instead of /",
"category": "DAX",
"severity": 2,
"scope": "Measure",
"expression": "!Expression.Contains(\"/\")",
"description": "Use DIVIDE function for safe division"
},
{
"id": "HIDDEN_KEY_COLUMNS",
"name": "Key Columns Should Be Hidden",
"category": "Formatting",
"severity": 1,
"scope": "Column",
"expression": "!(Name.EndsWith(\"Key\") || Name.EndsWith(\"ID\")) || IsHidden",
"description": "Key and ID columns should be hidden from users"
},
{
"id": "NO_UNUSED_COLUMNS",
"name": "Remove Unused Columns",
"category": "Maintenance",
"severity": 1,
"scope": "Column",
"expression": "ReferencedBy.Count > 0 || IsHidden == false",
"description": "Unused hidden columns should be removed"
}
]
}
# Validate TMDL syntax
TabularEditor.exe "path/to/Model" -S
# Run BPA with rules file
TabularEditor.exe "path/to/Model" -A "BPA-Rules.json" -V
# Save model (useful for formatting)
TabularEditor.exe "path/to/Model" -S "path/to/Model"
# Deploy to XMLA endpoint
TabularEditor.exe "path/to/Model" -D "powerbi://api.powerbi.com/v1.0/myorg/WorkspaceName" "DatasetName"
# Generate documentation
TabularEditor.exe "path/to/Model" -SCRIPT "GenerateDocs.cs"
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Validation errors |
| 2 | BPA violations (warning) |
| 3 | BPA violations (error) |
# Service Principal Authentication
$body = @{
grant_type = "client_credentials"
client_id = $clientId
client_secret = $clientSecret
resource = "https://analysis.windows.net/powerbi/api"
}
$token = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantId/oauth2/token" -Method Post -Body $body
$headers = @{ Authorization = "Bearer $($token.access_token)" }
# Get Workspaces
Invoke-RestMethod -Uri "https://api.powerbi.com/v1.0/myorg/groups" -Headers $headers
# Get Datasets in Workspace
Invoke-RestMethod -Uri "https://api.powerbi.com/v1.0/myorg/groups/$workspaceId/datasets" -Headers $headers
# Trigger Refresh
Invoke-RestMethod -Uri "https://api.powerbi.com/v1.0/myorg/groups/$workspaceId/datasets/$datasetId/refreshes" -Method Post -Headers $headers
# Get Refresh History
Invoke-RestMethod -Uri "https://api.powerbi.com/v1.0/myorg/groups/$workspaceId/datasets/$datasetId/refreshes" -Headers $headers
# Update Parameters
$body = @{
updateDetails = @(
@{ name = "ServerName"; newValue = "prod-server.database.windows.net" }
)
} | ConvertTo-Json
Invoke-RestMethod -Uri "https://api.powerbi.com/v1.0/myorg/groups/$workspaceId/datasets/$datasetId/Default.UpdateParameters" -Method Post -Headers $headers -Body $body -ContentType "application/json"
Local Development
↓
git push
↓
GitHub/Azure DevOps
↓
CI Validation
↓
Merge to main
↓
Fabric Git Sync
↓
Power BI Service
# Fabric-specific
.pbi/
**/localSettings.json
**/cache.abf
# Don't commit
*.pbix
*.pbit
# IDE
.vs/
.vscode/
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Development │ → │ Staging │ → │ Production │
│ Workspace │ │ Workspace │ │ Workspace │
└─────────────┘ └─────────────┘ └─────────────┘
feature/* develop main
Use parameters for environment-specific values:
expression ServerName = "dev-server.database.windows.net" meta [IsParameterQuery=true, Type="Text"]
expression DatabaseName = "SalesDB_Dev" meta [IsParameterQuery=true, Type="Text"]
Update via API during deployment:
# Update parameters for production
$body = @{
updateDetails = @(
@{ name = "ServerName"; newValue = "prod-server.database.windows.net" },
@{ name = "DatabaseName"; newValue = "SalesDB_Prod" }
)
} | ConvertTo-Json
Invoke-RestMethod -Uri ".../datasets/$datasetId/Default.UpdateParameters" `
-Method Post -Headers $headers -Body $body -ContentType "application/json"
# In workflow
env:
TENANT_ID: ${{ secrets.PBI_TENANT_ID }}
CLIENT_ID: ${{ secrets.PBI_CLIENT_ID }}
CLIENT_SECRET: ${{ secrets.PBI_CLIENT_SECRET }}
# Azure DevOps with Key Vault
- task: AzureKeyVault@2
inputs:
azureSubscription: 'ServiceConnection'
KeyVaultName: 'pbi-secrets-vault'
SecretsFilter: 'PBI-ClientId,PBI-ClientSecret'
# Secrets - NEVER commit
.env
*.secret
credentials.json
appsettings.Production.json
After setting up deployment:
Applies Power BI best practices, BPA rules, and enterprise standards. Use for quality validation, naming conventions, and performance optimization.
Creates calculation groups for reusable DAX patterns like time intelligence and currency conversion. Use to replace repetitive measures with dynamic calculations.
Writes DAX measures, calculated columns, and calculations for Power BI. Use for business logic, time intelligence, and analytical calculations.
Creates and manages Power BI Desktop Project (PBIP) structure. Use when starting new Power BI projects, setting up folder structure, or configuring project files.
Writes Power Query (M language) for data transformation, connections, and ETL. Use for data sources, transformations, parameters, and query optimization.
Creates Power BI reports and visuals in PBIR format. Use for pages, charts, tables, slicers, and visual configuration.