Fabric Deployment Plans - Swipe Left or Swipe Right
What the new deployment plan item does and where does it fit into CICD?
FabCon announcements are coming in thick and fast, including the Deployment Plan item, which I have been eyeing up on the Fabric Roadmap for a while. It lets you say what order items deploy in, within a workspace, and run a notebook or pipeline before or after each one. But would I reach for it on my next deployment?
The documentation is reasonably good, so I'm not going to rewrite it. This post hits the key points of how a plan behaves, then gives my two cents on where it fits.
Preview
Deployment plans are in preview. To turn them on you need to toggle a new tenant setting Users can create deployment plan (preview) items for the organisation or a security group before you can use them.
Deployment Plans¶
First of all a deployment plan is a new Fabric Item. It holds a Directed Acyclic Graph (DAG) of deployment groups. A deployment group is a single Fabric item, with optional pre-deploy and post-deploy actions (a notebook run, a pipeline run, and so on) around it. Deployment groups are the nodes of the DAG, and the edges are defined by the dependsOn relationships between them.
You build the plan on a canvas in the source workspace, and when the workspace is git-connected it is committed like any other item, as a plan.yml. Items are referenced by logical id, the same id that sits in each item's .platform file, so the plan stays valid as the items move between workspaces. Saving the plan assigns a logical id to any referenced item that doesn't have one yet.
So a plan might look like this:
flowchart TB
subgraph G1["Sales_Lakehouse group"]
direction TB
L1[("Sales_Lakehouse")]
A1["post: Run Hydrate_TopCustomers"]
A2["post: Run Publish_TopCustomers"]
L1 --> A1 -- dependsOn --> A2
end
subgraph G2["Reference_Lakehouse group"]
direction TB
L2[("Reference_Lakehouse")]
end
subgraph G3["Sales_Warehouse group"]
direction TB
W[("Sales_Warehouse")]
end
G1 -- dependsOn --> G3
G2 -- dependsOn --> G3
%% translucent fills so the theme's label colour stays readable in light and dark
linkStyle default stroke:#db2777,stroke-width:2px
classDef item fill:#db277766,stroke:#db2777,stroke-width:2px
classDef action fill:#f59e0b66,stroke:#f59e0b,stroke-width:2px
class L1,L2,W item
class A1,A2 action
style G1 fill:#f472b61a,stroke:#f472b6,stroke-width:1.5px
style G2 fill:#f472b61a,stroke:#f472b6,stroke-width:1.5px
style G3 fill:#f472b61a,stroke:#f472b6,stroke-width:1.5px
Giving the plan.yml below. Groups are a list under groups:, each with a name, a logicalId, optional preActions and postActions, and dependsOn for the edges.
$schema: https://developer.microsoft.com/json-schemas/fabric/item/deploymentPlan/definition/plan/1.0.0/schema.json
version: 1.0.0
groups:
- name: Sales_Lakehouse
logicalId: 11111111-1111-1111-1111-111111111111
postActions:
- name: Run Hydrate_TopCustomers
job:
type: Execute
logicalId: 22222222-2222-2222-2222-222222222222
- name: Run Publish_TopCustomers
dependsOn:
- actionName: Run Hydrate_TopCustomers
job:
type: Execute
logicalId: 33333333-3333-3333-3333-333333333333
- name: Reference_Lakehouse
logicalId: 55555555-5555-5555-5555-555555555555
- name: Sales_Warehouse
logicalId: 44444444-4444-4444-4444-444444444444
dependsOn:
- groupName: Sales_Lakehouse
- groupName: Reference_Lakehouse
Why Does It Exist?¶
Microsoft Docs: What is a deployment plan in Microsoft Fabric?
A Microsoft Fabric deployment plan is a workspace item that adds explicit item order and automated actions to a deployment operation. Use a plan to deploy items in a specific sequence. You can also use it to run a notebook, data pipeline, or another supported item before or after an item deploys. -- Microsoft Docs: What is a deployment plan in Microsoft Fabric?
Every deployment tool in Fabric (Git integration, deployment pipelines and the bulk import API) already orders items by lineage. A plan adds the dependencies and actions lineage can't represent: if the lineage order is enough and nothing has to run, you don't need one, and you only add the items that need explicit ordering or an action. The rest deploy as they always did.
Microsoft Docs: What is a deployment plan in Microsoft Fabric?
Fabric combines explicit dependencies between deployment groups with dependencies detected from lineage. A plan can add an order that lineage doesn't represent, but it doesn't remove dependencies that Fabric detects. -- Microsoft Docs: What is a deployment plan in Microsoft Fabric?
"Combines" means the deployment tool's existing lineage DAG is enriched with the plan's DAG, and the order is resolved over the lot. A plan edge can only add a constraint; one that contradicts lineage is a cycle and the plan won't save. So the edges worth drawing are the ones lineage can't see: a dependency through a connection, a table that has to be populated before a view can be created.
Item selection is the deployment tool's job, not the plan's. An item in the deployment operation but not in the deployment plan deploys as it always did, and attaching a plan doesn't select the items it names, so on a selective branch-out you need to manually select items yourself, including items that will be run in an action.
Actions¶
An action is a run of another item in the workspace, and nothing more. The plan starts the job, the item decides what happens. Five item types are supported, and every one of them runs as an Execute job, so a Dataflow Gen2 action is a refresh and nothing else:
- Notebook
- Data pipeline
- Dataflow Gen2
- Copy job
- User data function
Actions in a group are chained with dependsOn and are only ever run one at a time. The deploying identity needs Item.Execute.All on top of the operation's own scope.
An action can carry up to twenty parameters, passed straight through to the item, so the names have to be the ones the item declares. A value is either a literal (the same in every workspace), or a reference to a Variable Library variable, which is the only way to vary a value per environment. A reference resolves against whichever value set is active in the target workspace, which is where greenfield deployments fall over:
Microsoft Docs: Deployment plan considerations and limitations
You can't use a deployment plan to change the active value set of a Variable Library during deployment. Variable references resolve against the value set that's already active in the target workspace. In a newly created target workspace, Default is active until you select and save another value set. -- Microsoft Docs: What is a deployment plan in Microsoft Fabric?
Failure¶
The deployment stops at the first item or action that fails and doesn't roll back. What was deployed stays, and later items are left undeployed. A failed action's detail is logged in that item's run history rather than on the plan.
When Does It Apply¶
Never on its own. A plan is a passive item until it is attached to one operation, and the attachment lasts for that operation only.
Microsoft Docs: What is a deployment plan in Microsoft Fabric?
A plan attachment applies only to the current operation. You can't configure a plan as the default for future deployments or schedule the plan itself. If a deployment tool schedules an operation, the operation must attach the plan each time it runs. -- Microsoft Docs: What is a deployment plan in Microsoft Fabric?
The operations that can carry one:
- Git integration, in the git to workspace direction only: the initial sync after connecting, Update from Git, switch branch, and branch out. A commit from the workspace never runs a plan.
- Deployment pipelines, deploying between stages. You choose the target stage's existing plan or the incoming one from the source stage.
- REST: Update From Git, Deploy Stage Content and Bulk Import Item Definitions, each with
beta=trueon the URL and adeploymentPlanobject insideoptions
For a branch-out the plan has to be committed to the branch you are branching from; only plans in git show up in the picker. Where the plan comes from otherwise depends on the operation: git integration takes one from the workspace or the incoming git content, a deployment pipeline offers the target stage's plan or the source stage's, and the APIs take a logical id (git and bulk import) or an item id (pipelines).
Deployment plans are not supported by fabric-cicd.
Swipe Left or Swipe Right¶
| Consideration | Swipe Left | Swipe Right |
|---|---|---|
| Source control | Order and post-deploy runs live in git as plan.yml, keyed by logical id, reviewed in a pull request |
|
| No build agent | Runs inside Fabric, so a branch-out from the portal and a deployment pipeline get the same order and actions | |
| Native release process | Fits deployment pipelines plus variable libraries | |
| Auto-binding | Unchanged. A plan orders and runs, it doesn't rebind, and carries no connections or workspace settings. Existing auto-binding gaps are not addressed | |
| fabric-cicd | Can't use with the one tool that does resolve auto-binding gaps | |
| Greenfield | A variable library lands on Default active set in a new workspace and the plan can't change it, so a cold deploy reads the wrong values | |
| Multi-workspace | One plan, one workspace. Nothing crosses workspaces | |
| Control | No environment filter on a step, no continue on error, and the first failure stops the operation |
It feels like there are two parallel worlds in Fabric CI/CD: one low-code with git integration, branch-out, deployment pipelines and variable libraries, and one higher-code with a repo, pipelines and fabric-cicd. There doesn't seem to be a solid bridge between these two worlds. I believe Deployment Plans are built for the former Fabric-native world, and if you live in that world Deployment Plans are a welcome addition.
The problem is that there are still large gaps in the native CICD story: auto-binding gaps, deployment into an empty workspace, and cross-workspace dependencies, which can only be fully addressed by fabric-cicd, which does not support deployment plans.
Conclusion¶
But if they were supported by fabric-cicd, would I use them? I think the answer would be yes. It does fill a gap in that you can't specify the deployment order of items with fabric-cicd, and it has no built-in pre- or post-deployment mechanism. But I would like some more control over failure handling and rollback mechanisms. Today a failed pre- or post-deploy action stops the whole operation, with no way to say carry on,, and no rollback of what already landed, so a flaky refresh leaves a half-deployed workspace. So right now I'll have to swipe left.