Skip to content
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
b32c344
Introduce deploy command
Feb 19, 2026
a5f3d49
add changie
Feb 19, 2026
c319fb6
Resolve PR commants
Feb 19, 2026
a727e79
Create MSAL bridge
Feb 22, 2026
3c3bf67
remove metavar
Feb 22, 2026
c472fac
align context with other commands - will handle it in another PR
Feb 22, 2026
176c090
Merge pull request #2 from aviatco/deploy-command-interface
aviatco Feb 22, 2026
f9cb1f7
Merge branch 'dev/aviatcohen/cli-cicd-intergation-main' into dv/aviat…
Feb 22, 2026
1a9bd67
call cicd deploy_with_config
Feb 22, 2026
4c53e4e
resolve PR cooments
Feb 24, 2026
508b7ca
Update src/fabric_cli/core/fab_auth.py
aviatco Feb 26, 2026
06c2dd8
resolve commants
Mar 1, 2026
d844bba
remove handling of expires_on when converting msal token to azure ide…
Mar 1, 2026
170b45a
make sure expires_on is int
Mar 1, 2026
a02687e
Merge pull request #3 from aviatco/dev/aviatcohen/msal-bridge
aviatco Mar 1, 2026
5972eb1
support deploy command
Mar 1, 2026
73bbdbd
Merge branch 'dev/aviatcohen/msal-bridge' into dev/aviatcohen/deploy-…
Mar 1, 2026
e9c0fc0
using expires_in if expires_on is not avilable
Mar 2, 2026
d1de4ec
Merge branch 'dev/aviatcohen/cli-cicd-intergation-main' into dev/avia…
Mar 2, 2026
870e923
comment to disable live recording mode
Mar 2, 2026
4fb7b7b
change --deploy_with_config flag to config; fix PR comments
Mar 3, 2026
3d733cd
create deploy_setup fixture and update tests
Mar 4, 2026
08d7d8d
add tests
Mar 5, 2026
9991a00
Update src/fabric_cli/commands/fs/deploy/fab_fs_deploy_config_file.py
aviatco Mar 5, 2026
d3e8dba
update cicd feature flags and debug_enabled
Mar 5, 2026
69ef52c
Merge branch 'dev/aviatcohen/deploy-with-config' of https://github.co…
Mar 5, 2026
d21ff0d
update cicd feature flags and debug_enabled
Mar 5, 2026
ca31a7b
Merge pull request #4 from aviatco/dev/aviatcohen/deploy-with-config
aviatco Mar 5, 2026
a2a3243
add changie
Mar 5, 2026
785ee13
align seccess msg with cicd updates
Mar 5, 2026
58acead
define VALID_DEFATULT_SCOPES at module level
Mar 5, 2026
a4c8c96
Merge branch 'main' into dev/aviatcohen/cli-cicd-intergation-main
aviatco Mar 5, 2026
c13be3d
Fix type check tests
Mar 5, 2026
1511aba
fix type check error for expires_on
Mar 5, 2026
de8660f
remove python 3.13 from test build just for testing - will be revertg…
Mar 5, 2026
8d55167
resolve backslash issue in prompt message
Mar 5, 2026
a764267
fix test_get_access_token_token_error
Mar 5, 2026
128702c
Apply suggestion from @aviatco
aviatco Mar 5, 2026
75c35f1
trying to fix interactive_cli tests
Mar 5, 2026
264bdbc
Merge branch 'dev/aviatcohen/cli-cicd-intergation-main' of https://gi…
Mar 5, 2026
39aa30e
deploy documentation
Mar 9, 2026
e6cf9d5
Merge branch 'main' into dev/aviatcohen/cli-cicd-intergation-main
aviatco Mar 9, 2026
9467b6b
bump cicd version
Mar 9, 2026
d4f5f52
remove deploy docs
Mar 9, 2026
c1082b3
Merge branch 'dev/aviatcohen/cli-cicd-intergation-main' of https://gi…
Mar 9, 2026
1b8b174
revert - remove python 3.13 support
Mar 9, 2026
64838f0
fix deploy tests
Mar 9, 2026
b7bdfde
mock acquire_token method
Mar 9, 2026
0a8def4
mock acquire_token
Mar 10, 2026
7fb1e55
new decording for test_deploy_single_item_success
Mar 10, 2026
dc7fd75
revert scope class fixture
Mar 10, 2026
23f06f1
revert setup_default_format scopr class in mock_fab_set_state_config
Mar 10, 2026
e4cf5b2
revert setup_default_format scope class in setup_default_format
Mar 10, 2026
17e4a67
recorde fail tests
Mar 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/added-20260305-091728.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: added
body: Introduces the new deploy command that integrates with the fabric-cicd library, enabling users to deploy multiple Fabric items in a single
time: 2026-03-05T09:17:28.270036405Z
custom:
Author: aviatco
AuthorLink: https://github.com/aviatco
4 changes: 2 additions & 2 deletions .github/workflows/fab-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ jobs:
tox-env: "py311"
- python-version: "3.12"
tox-env: "py312"
- python-version: "3.13"
tox-env: "py313"
# - python-version: "3.13"
# tox-env: "py313"
steps:
- uses: actions/checkout@v3

Expand Down
224 changes: 224 additions & 0 deletions docs/commands/fs/deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
# `deploy` Command

Deploy a Fabric workspace from local source content into a target Microsoft Fabric workspace.

---

## Description

The `deploy` command imports workspace content from a local source into a target Fabric workspace.

You can deploy:
- an entire workspace
- specific folders
- specific items

The scope and behavior of the deployment are defined entirely by the deployment configuration file.

During execution, the command:
- publishes items found in the source into the target workspace
- resolves dependencies between items automatically when logical IDs are present
- removes items from the target workspace that no longer exist in the source (unpublish)

By default, **both publish and unpublish operations are enabled and executed**.
To disable either operation for a specific environment, it must be explicitly skipped in the configuration file.

The deployment is executed directly against Fabric workspaces using Fabric APIs.

---

## Usage

```bash
fab deploy --config <config_file> [--target_env <environment>] [--params <parameters>] [--force]
```

---

## Options

| Option | Description |
|------|-------------|
| `--config <file>` | Path to the deployment configuration file. **Required**. |
| `--target_env, -tenv <env>` | Environment name used to select environment-specific settings from the configuration file. |
| `--params, -P <params>` | JSON-formatted parameters provided to the deployment process at runtime. |
| `--force, -f` | Run the deployment without interactive confirmation prompts. |
| `--help` | Show detailed help for the `deploy` command. |

---

## Configuration Behavior

- The configuration file controls what is published and unpublished.
- Publish and unpublish operations are enabled by default.
- Skipping publish or unpublish must be explicitly defined per environment.
- Environment selection is resolved only when environment mappings are present in the configuration.
- If `--target_env` is not specified, the configuration must not contain environment-specific mappings.

---

## Configuration File

### Minimal Configuration (No Environments)

```yaml
core:
workspace_id: "12345678-1234-1234-1234-123456789abc"
repository_directory: "."
```

---

### Configuration Fields

| Field | Description | Mandatory |
|------|------------|-----------|
| `core.workspace_id` | Target workspace ID (GUID). Takes precedence over `workspace`. | βœ… Yes |
| `core.workspace` | Target workspace name. Alternative to `workspace_id`. | ❌ No |
| `core.repository_directory` | Path to local directory containing workspace content. | βœ… Yes |
| `core.item_types_in_scope` | List of item types included in deployment. | ❌ No |
| `core.parameter` | Path to parameter file. | ❌ No |
| `publish` | Controls publishing behavior. | ❌ No |
| `unpublish` | Controls unpublishing behavior. | ❌ No |
| `features` | Feature flags. | ❌ No |
| `constants` | API constant overrides. | ❌ No |

Relative paths are resolved relative to the configuration file location.

---

## Publish and Unpublish Settings

### Publish

```yaml
publish:
exclude_regex: "^DONT_DEPLOY.*" # Excludes items matching this pattern from publishing
folder_exclude_regex: "^legacy/" # Excludes items under matching folders from publishing
items_to_include: # Publishes only the specified items (requires feature flags)
- "MainNotebook.Notebook"
skip: # Skips publishing per environment
dev: true
test: false
prod: false
```

### Unpublish

```yaml
unpublish:
exclude_regex: "^DEBUG.*" # Prevents matching items from being removed
items_to_include: # Unpublishes only the specified items (requires feature flags)
- "OldPipeline.DataPipeline"
skip: # Skips unpublishing per environment
dev: true
test: false
prod: false
```

> **Note**
> While selective deployment is supported, it is not recommended due to potential issues with dependency management. Use selective deployment options with caution.

---

## Parameter File

The parameter file enables environment-specific transformation of deployed content.

It can be used to:
- replace workspace and item identifiers
- replace connection strings and URLs
- update embedded values inside item definitions
- parameterize environment-specific configuration values

The parameter file is optional and is applied only when specified in the configuration.

When items were exported or created using Fabric CLI (and not through Git integration), dependencies must be explicitly defined in the parameter file to ensure correct resolution during deployment.

### Example

```yaml
find_replace:
- find_value: "dev-connection-string"
replace_value:
dev: "dev-connection-string"
test: "test-connection-string"
prod: "prod-connection-string"
```

### Supported Variables

- `$workspace.$id` β€” resolves to the target workspace ID
- `$items.<ItemType>.<ItemName>.$id` β€” resolves to the deployed item ID

Parameterization behavior follows the documented model described here:

https://microsoft.github.io/fabric-cicd/0.1.3/how_to/parameterization/add

---

## Examples

### Basic Deployment

```bash
fab deploy --config config.yml
```

### Deployment to a Specific Environment

```bash
fab deploy --config config.yml --target_env prod
```

### Deployment with Runtime Parameters

```bash
fab deploy --config config.yml --target_env test -P '{"core":{"item_types_in_scope":["Notebook"]}}'
```

---

## Preparing Source Content

### Using Git Integration

If the workspace is connected to Git, clone the repository locally:

```bash
git clone https://github.com/org/fabric-workspace.git
```

Use the cloned repository as the deployment source.

---

### Using `fab export`

`fab export` exports one item at a time and does not include logical IDs.

```bash
fab export --output ./path-to-ws MyDataPipeline.DataPipeline --format .py
```

To export Notebook items use the `--format .py` option.

```bash
fab export --output ./path-to-ws MyNotebook.Notebook --format .py
```

---

## Notes

- `fab deploy` does not require Git integration; however, using Git integration is strongly recommended to ensure dependencies.
- The deploy command supports content sourced from Git repositories, locally exported items, and items created locally.
- Specifying a target environment is optional. If --target_env is provided, only values for that environment are applied. If environment‑specific values exist in the configuration, --target_env is required.
- Parameter files are optional and apply to all deployment scenarios.

---

## Related Commands

- `export` β€” Export individual items from a workspace
- `import` β€” Import individual items into a workspace
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies = [
"msal[broker]>=1.34,<2 ; platform_system != 'Linux'",
"msal>=1.34,<2",
"msal_extensions",
"azure-core>=1.29.0",
"questionary",
"prompt_toolkit>=3.0.41",
"cachetools>=5.5.0",
Expand All @@ -28,6 +29,7 @@ dependencies = [
"psutil==7.0.0",
"requests",
"cryptography",
"fabric-cicd>=0.2.0",
]

[project.scripts]
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ argcomplete>=3.6.2
psutil==7.0.0
requests
cryptography
fabric-cicd>=0.2.0

# Testing and Building Requirements
tox>=4.20.0
Expand Down
56 changes: 56 additions & 0 deletions src/fabric_cli/commands/fs/deploy/fab_fs_deploy_config_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import json
from argparse import Namespace

from fabric_cicd import append_feature_flag, configure_external_file_logging, deploy_with_config, disable_file_logging # type: ignore

from fabric_cli.core import fab_constant, fab_state_config
from fabric_cli.core import fab_logger
from fabric_cli.core.fab_exceptions import FabricCLIError
from fabric_cli.core.fab_msal_bridge import create_fabric_token_credential
from fabric_cli.utils import fab_ui
from fabric_cli.utils.fab_util import get_dict_from_params


def deploy_with_config_file(args: Namespace) -> None:
"""deploy fabric items to a workspace using a configuration file and target environment - delegates to CICD library."""

try:
if fab_state_config.get_config(fab_constant.FAB_DEBUG_ENABLED) == "true":
cli_logger = fab_logger.get_logger()
# configure file logging for CICD library to use the same file handler as the CLI
configure_external_file_logging(cli_logger)
else:
# prevent creation of a log file for fabric-cicd logs when debug mode is disabled
disable_file_logging()

# feature flags to avoid printing identity info in logs
append_feature_flag("disable_print_identity")

deploy_config_file = args.config
deploy_parameters = get_dict_from_params(args.params, max_depth=1)
for param in deploy_parameters:
if isinstance(deploy_parameters[param], str):
try:
deploy_parameters[param] = json.loads(
deploy_parameters[param])
except json.JSONDecodeError:
# If it's not a valid JSON string, keep it as is
pass
result = deploy_with_config(
config_file_path=deploy_config_file,
environment=args.target_env,
token_credential=create_fabric_token_credential(), # MSAL bridge TokenCredential
**deploy_parameters
)

if result:
fab_ui.print_output_format(
args, message=result.message)

except Exception as e:
raise FabricCLIError(
f"Deployment failed: {str(e)}",
fab_constant.ERROR_IN_DEPLOYMENT)
7 changes: 7 additions & 0 deletions src/fabric_cli/commands/fs/fab_fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from fabric_cli.commands.fs import fab_fs_export as fs_export
from fabric_cli.commands.fs import fab_fs_get as fs_get
from fabric_cli.commands.fs import fab_fs_import as fs_import
from fabric_cli.commands.fs import fab_fs_deploy as fs_deploy
from fabric_cli.commands.fs import fab_fs_ln as fs_ln
from fabric_cli.commands.fs import fab_fs_ls as fs_ls
from fabric_cli.commands.fs import fab_fs_mkdir as fs_mkdir
Expand Down Expand Up @@ -144,6 +145,12 @@ def import_command(args: Namespace) -> None:
fs_import.exec_command(args, context)


@handle_exceptions()
@set_command_context()
def deploy_command(args: Namespace) -> None:
fs_deploy.exec_command(args)


@handle_exceptions()
@set_command_context()
def set_command(args: Namespace) -> None:
Expand Down
14 changes: 14 additions & 0 deletions src/fabric_cli/commands/fs/fab_fs_deploy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from argparse import Namespace

from fabric_cli.commands.fs.deploy.fab_fs_deploy_config_file import deploy_with_config_file
from fabric_cli.utils import fab_ui


def exec_command(args: Namespace) -> None:
"""deploy fabric items to a workspace using a configuration file and target environment - CICD flow."""
target_env_msg = 'without a target environment' if args.target_env == 'N/A' else f"to target environment '{args.target_env}'"
if args.force or fab_ui.prompt_confirm(f"Are you sure you want to deploy {target_env_msg} using the specified configuration file?"):
deploy_with_config_file(args)
Loading
Loading