Native Bicep deployments using Bicep's CLI

No more AZ CLI or Azure PowerShell to perform Bicep file deployments

Natie Bicep deployments with Bicep's CLI
Natie Bicep deployments with Bicep's CLI

Say goodbye to the Azure CLI or Azure PowerShell for Bicep deployment. There's a new sheriff in town.

A couple of weeks ago, Anthony Martin, the Engineering Manager for Bicep deployments, created a new issue on GitHub. The issue describes that the Bicep CLI doesn't natively support deployment capabilities using Bicep's CLI.

Fast forward and a couple of pull requests further, a new subcommand has been added to the CLI: bicep deploy.

Not released, not final — but you can pull the main branch and see it in action now. In this blog post, we will dive into what's already available to us.

💡
Please be aware that what’s shown here is subject to changes. Refer to the official documentation when the feature becomes available.

What is Bicep deploy

As Anthony described in the issue, the Bicep CLI tightly integrates with Azure CLI and Azure PowerShell. Think of the commands you'll typically use to deploy Bicep files:

  • Azure CLI:
    • az deployment sub create
    • az deployment group create
    • az deployment mg create
    • az deployment tenant create
  • Azure PowerShell:
    • New-AzResourceGroupDeployment
    • New-AzSubscriptionDeployment
    • New-AzManagementGroupDeployment
    • New-AzTenantDeployment

But with this tight integration, you always had to install one of the two to deploy Bicep files to Azure. Now, Bicep has grown. It supports features like externalInputs, variable expressions, and more. With that maturity, the team decided to put their energy into a native CLI experience.

So the bicep deploy command was born. With this new subcommand added, you can now natively use the Bicep CLI to deploy Bicep files. Based on the scope defined in the .bicepparam file, you can target where you want the .bicep to deploy towards. Here's an example snippet:

// main.bicepparam
using 'main.bicep' with {
  mode: 'deployment'
  scope: '/subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName>'
}

How to try it out today

The experimental feature has not been officially released, as mentioned from the beginning. But don't worry, the Bicep team has you covered already.

To grab one of the latest nightly builds for the Bicep CLI, you can run the following commands:

# Install on MacOS/Linux
bash <(curl -Ls https://aka.ms/bicep/nightly-cli.sh)

Or use PowerShell:

# Installl on Windows
iex "& { $(irm https://aka.ms/bicep/nightly-cli.ps1) }"

When the CLI is installed, you need to set the experimental feature flag in the known bicepconfig.json file:

{
  "experimentalFeaturesEnabled": {
    "deployCommands": true
  }
}

Now that's set up, let's take a closer look by deploying an actual resource to a Resource Group:

// main.bicep
param storageAccountName string

module st 'br/public:avm/res/storage/storage-account:0.27.0' = {
  params: {
    name: storageAccountName
  }
}

// main.bicepparam
var subscriptionId = readEnvVar('AZURE_SUBSCRIPTION_ID')
var resourceGroupName = readEnvVar('AZURE_RESOURCE_GROUP')

using 'main.bicep' with {
  mode: 'deployment'
  scope: '/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}'
}

param storageAccountName = 'afakeststorageaccount123'

The readEnvVar is a new function to read environment variables for the bicep deploy command. If these values are not set while deploying, the CLI will throw an error. Let's test it out by running the command.

When the command was executed, the duration was incrementally displayed, showing how long it took. This experience was made possible by using the Spectre console.

Capabilities and constraints

bicep deploy is brand new. You can already see useful commands landing. It supports what-if to preview changes. The teardown for stack clean-up, and the --format option to output JSON for easier parsing. It also works with completions, making the authoring experience smoother.

That said, the feature isn't without limits. At this stage, it still appears to rely on the Azure CLI or Azure PowerShell to fetch an authentication token.

In my tests, the resourceGroup() function failed, showing that scope handling isn't completed. I expected constraints already, but it's already clear that the team is laying the foundation for bicep-deploy.

The road ahead

The vision for bicep deploy goes well beyond a new subcommand. The Bicep team is exploring various syntax changes for .bicepparam files. The new CLI groups (deploy, what-if, destroy), and functions like readEnvVar() and readCliArg() bring in runtime values straight into deployments. Together, these aim to simplify the authoring and configuration experience.

Bicep's community is always active, and feedback highlighted where this could sparkle even further:

  • Better CI/CD integration with Azure DevOps and GitHub Actions.
  • Parity with Azure PowerShell's rich output.
  • Improved visualization across pipelines.
  • Multiple version support and stronger handling of context/scopes.
  • Friendly diagnostics with links to Azure Portal.

If these ideas take hold, the Bicep CLI could provide a single, self-contained tool for authoring, validating, deploying, and troubleshooting your Azure infrastructure.