Microsoft Fabric CI/CD
The `fabric-cicd` library provides a Pythonic interface and command-line tool for implementing Continuous Integration/Continuous Deployment (CI/CD) pipelines for Microsoft Fabric artifacts. It enables programmatic deployment, lifecycle management, and automation of Fabric items like notebooks, lakehouses, and data pipelines. Currently at version 0.3.1, it is under active development with frequent releases targeting new Fabric capabilities and improvements.
Common errors
-
ModuleNotFoundError: No module named 'fabric_cicd'
cause The `fabric-cicd` package is not installed in your current Python environment.fixRun `pip install fabric-cicd` to install the library. -
msal.exceptions.MsalServiceException: AADSTS700016: Application with identifier '...' was not found in the directory '...' or 'AADSTS500011: The resource principal named '...' was not found in the tenant named '...'
cause Authentication failed. This typically means the Client ID (Application ID) is incorrect, the Tenant ID is wrong, or the Service Principal has not been registered in the specified Azure AD tenant.fixDouble-check the `FABRIC_CLIENT_ID` and `FABRIC_TENANT_ID` values. Verify the Service Principal exists and is correctly configured in your Azure Active Directory. -
msal.exceptions.MsalServiceException: AADSTS7000215: Invalid client secret is provided.
cause The client secret provided for the Service Principal is incorrect or has expired.fixGenerate a new client secret in Azure AD for your Service Principal and update the `FABRIC_CLIENT_SECRET` environment variable or configuration. -
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: ...
cause The authenticated Service Principal lacks the necessary permissions (e.g., Read, Write, Deploy) on the target Microsoft Fabric workspace or item to perform the requested operation.fixGrant the Service Principal appropriate permissions in the Microsoft Fabric workspace settings (e.g., 'Contributor' role) or through specific item-level permissions. Confirm the Service Principal is added to the workspace access list.
Warnings
- gotcha Authentication heavily relies on Azure Service Principals. Ensure your Service Principal has the necessary permissions (e.g., Fabric Contributor or specific delegated permissions) on the target workspaces/items in Microsoft Fabric and is correctly registered in Azure AD. Incorrect permissions are a common source of 'Forbidden' or 'Unauthorized' errors.
- gotcha The library differentiates between source and target workspaces during deployment. Understand the lifecycle of your Fabric items and how they are identified (e.g., by ID, type, name). Misunderstanding item identifiers or workspace relationships can lead to deployment failures.
- breaking As of version 0.3.x, the library is still under active development, and its API is subject to change. Future versions (especially leading up to 1.0) may introduce breaking changes to method signatures, class structures, or authentication flows.
Install
-
pip install fabric-cicd
Imports
- FabricCICDClient
from fabric_cicd import FabricCICDClient
from fabric_cicd.fabric_cicd_client import FabricCICDClient
Quickstart
import os
from fabric_cicd.fabric_cicd_client import FabricCICDClient
# Ensure these environment variables are set for your service principal
TENANT_ID = os.environ.get('FABRIC_TENANT_ID', 'YOUR_TENANT_ID')
CLIENT_ID = os.environ.get('FABRIC_CLIENT_ID', 'YOUR_CLIENT_ID')
CLIENT_SECRET = os.environ.get('FABRIC_CLIENT_SECRET', 'YOUR_CLIENT_SECRET')
if not all([TENANT_ID, CLIENT_ID, CLIENT_SECRET]):
print("Error: FABRIC_TENANT_ID, FABRIC_CLIENT_ID, and FABRIC_CLIENT_SECRET environment variables must be set.")
print("Please configure these environment variables with your Azure Service Principal credentials.")
exit(1)
try:
# Initialize the client
client = FabricCICDClient(
tenant_id=TENANT_ID,
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET
)
# Example: List workspaces (requires appropriate permissions)
print("\nFetching Fabric workspaces...")
workspaces = client.get_workspaces()
if workspaces:
print(f"Found {len(workspaces)} workspaces:")
for ws in workspaces[:3]: # Print first 3 for brevity
print(f" - {ws.display_name} (ID: {ws.id})")
else:
print("No workspaces found or insufficient permissions.")
# Example: Deploy a dummy item (requires actual item ID and target workspace ID)
# Uncomment and replace placeholders with actual values for deployment functionality.
# source_workspace_id = "<YOUR_SOURCE_WORKSPACE_ID>"
# item_id = "<YOUR_ITEM_ID>" # e.g., Notebook ID, Lakehouse ID
# target_workspace_id = "<YOUR_TARGET_WORKSPACE_ID>"
#
# print(f"\nAttempting to deploy item {item_id} from {source_workspace_id} to {target_workspace_id}...")
# try:
# result = client.deploy_item(source_workspace_id, item_id, target_workspace_id)
# print(f"Deployment successful: {result}")
# except Exception as e:
# print(f"Deployment failed: {e}")
except Exception as e:
print(f"\nAn error occurred during client operation: {e}")