Skip to content
CSA Loom — the Microsoft Fabric experience for Azure tenants where Fabric isn't yet available: lakehouses, warehouses, notebooks, semantic models, Activator rules, Data Agents, across Commercial, GCC, GCC-High, and DoD IL5

Deploy CSA Loom from Azure DevOps Pipelines

Multi-stage YAML pipeline (Dev → Stage → Prod) using ADO workload-identity federation for OIDC-style auth, with per-stage approvals.

For customers standardized on Azure DevOps (federal customers frequently are — Azure DevOps Server / GCC-H Azure DevOps Services).

Prerequisites

Item Notes
Azure DevOps project Self-hosted or hosted
Service connection (Azure Resource Manager) with workload-identity federation Avoid long-lived secrets
Variable group Per environment: LOOM_BOUNDARY, LOOM_LOCATION, LOOM_ADMIN_GROUP_OBJECT_ID
Environments configured in ADO dev, stage, prod — each with approval gates
Bicep task installed (Azure DevOps task pack — already in ADO Cloud)

Pipeline

Save as azure-pipelines/loom-deploy.yml:

trigger: none  # manual dispatch only

parameters:
  - name: boundary
    type: string
    default: commercial
    values: [commercial, gcc, gcc-high]
  - name: runMode
    type: string
    default: deploy
    values: [validate, deploy, teardown]

variables:
  - name: BicepFile
    value: platform/fiab/bicep/main.bicep
  - name: ParamFile
    value: platform/fiab/bicep/params/${{ parameters.boundary }}.bicepparam
  - name: DeploymentName
    value: loom-$(Build.BuildId)

stages:
  - stage: Validate
    jobs:
      - job: validate
        pool:
          vmImage: ubuntu-latest
        steps:
          - task: AzureCLI@2
            displayName: Validate Bicep
            inputs:
              azureSubscription: loom-deploy-dev
              scriptType: bash
              scriptLocation: inlineScript
              inlineScript: |
                az bicep build --file $(BicepFile)
                az deployment sub validate \
                  --location $(LOOM_LOCATION) \
                  --template-file $(BicepFile) \
                  --parameters $(ParamFile)

  - stage: DeployDev
    dependsOn: Validate
    condition: and(succeeded(), eq('${{ parameters.runMode }}', 'deploy'))
    jobs:
      - deployment: dev
        environment: loom-dev
        pool:
          vmImage: ubuntu-latest
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: AzureCLI@2
                  inputs:
                    azureSubscription: loom-deploy-dev
                    scriptType: bash
                    scriptLocation: inlineScript
                    inlineScript: |
                      az deployment sub create \
                        --name $(DeploymentName) \
                        --location $(LOOM_LOCATION) \
                        --template-file $(BicepFile) \
                        --parameters $(ParamFile) \
                        --parameters loomAdminGroupObjectId=$(LOOM_ADMIN_GROUP_OBJECT_ID)
                      bash scripts/csa-loom/bootstrap-all.sh \
                        --boundary ${{ parameters.boundary }} --environment dev

  - stage: DeployStage
    dependsOn: DeployDev
    condition: and(succeeded(), eq('${{ parameters.runMode }}', 'deploy'))
    jobs:
      - deployment: stage
        environment: loom-stage  # approval gate configured here
        pool:
          vmImage: ubuntu-latest
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: AzureCLI@2
                  inputs:
                    azureSubscription: loom-deploy-stage
                    scriptType: bash
                    scriptLocation: inlineScript
                    inlineScript: |
                      az deployment sub create \
                        --name $(DeploymentName) \
                        --location $(LOOM_LOCATION) \
                        --template-file $(BicepFile) \
                        --parameters $(ParamFile) \
                        --parameters loomAdminGroupObjectId=$(LOOM_ADMIN_GROUP_OBJECT_ID)

  - stage: DeployProd
    dependsOn: DeployStage
    condition: and(succeeded(), eq('${{ parameters.runMode }}', 'deploy'))
    jobs:
      - deployment: prod
        environment: loom-prod  # production approval gate
        pool:
          vmImage: ubuntu-latest
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: AzureCLI@2
                  inputs:
                    azureSubscription: loom-deploy-prod
                    scriptType: bash
                    scriptLocation: inlineScript
                    inlineScript: |
                      az deployment sub create \
                        --name $(DeploymentName) \
                        --location $(LOOM_LOCATION) \
                        --template-file $(BicepFile) \
                        --parameters $(ParamFile) \
                        --parameters loomAdminGroupObjectId=$(LOOM_ADMIN_GROUP_OBJECT_ID)
                      bash scripts/csa-loom/bootstrap-all.sh \
                        --boundary ${{ parameters.boundary }} --environment prod

Approvals + post-deploy

Each environment: reference enforces ADO approval gates. Configure under Pipelines → Environments → loom-stage / loom-prod → Approvals + checks.

Post-deploy bootstrap (Power BI tenant SP grant, Databricks SCIM, Dataverse AppUser) runs as the last step of each deploy stage.

GCC-High variant

For Azure Government, replace azureSubscription: values with a service connection that targets AzureUSGovernment cloud, and set LOOM_LOCATION=usgovvirginia.