Azure / Azure/bicep

Proposal: Bicep CLI commands for Azure operations

Open
#17,949 21 comments 14 reactions 0 assignees View on GitHub
enhancement proposal
Dominant language
Bicep
Stars
3.6k
Forks
830
Avg merge
1d 2h
Merged PRs (30d)
79

Description

# Bicep CLI commands for Azure operations

Today, Bicep CLI has no built-in deployment capabilities - it purely exposes compiler functionality such as `bicep build` or `bicep lint`. To provide deployment capabilities, Bicep CLI is tightly integrated into Azure CLI and Azure PowerShell, such that these tools invoke Bicep CLI for compilation, and deploy the compiled artifacts themselves.

This was the right decision at the time; it was made during the early phases of Bicep development, as we wanted a seamless experience to ease migration, and didn't want to invest energy in building a deployment experience ourselves. There are various things that have changed since this decision was made:
* Bicep is now a mature project with significant adoption. We have more energy to spend on providing a better CLI experience.
* New features such as `externalInputs`, variable expressions, extension configs, snapshot files, and local deploy exist.
* `.bicepparam` files exist, and we have a better handle on some of the friction points associated with them.

One common concept that this proposal explores is simplifying the CLI experience by shifting configuration into the `.bicepparam` files. For example, rather than writing:
```sh
az deployment group create --subscription-id --resource-group --parameters a=
```
The user should be able to write:
```sh
bicep deploy
```

The reasons why I think this is beneficial are:
* Reduces duplication in CI pipelines, and simplifies local reproducability.
* Gives the Bicep author more control over exposing configuration.
* Permits better validation during authoring, and a more coherent validation experience when deploying.
* Works well with other proposed commands such as `bicep what-if` and `bicep destroy`.

## Goals

### Main Goals
* Propose a set of `.bicepparam` syntax changes and new Bicep CLI command groups for managing deployments.
* Propose an approach on rationalizing some of the more recent language features against each other (extension configs, external inputs), along with other proposed features such as `bicep deploy`.
* Propose improvements to visualization of deployments.

### Other Goals
* Simplify migration from deployments to deployment stacks.
* Provide higher-quality visualization for errors, diagnostics, and real-time operations.

## New Syntax

The syntax proposals are all changes to the `.bicepparam` file syntax.

### Changes to `using`

Rather than relying on CLI arguments for configuration, configuration can be specified using a `with` clause:

```bicep
using 'main.bicep' with {
mode: 'deployment'
scope: resourceGroup('f794b1c4-c575-4f8d-9eb0-1816c630c110', 'myRg')
name: 'main' // optional
}

param foo = 'bar'
```

For Deployment Stacks:
```bicep
using 'main.bicep' with {
mode: 'stack'
scope: resourceGroup('f794b1c4-c575-4f8d-9eb0-1816c630c110', 'myRg')
name: 'myStack'
actionOnUnmanage: {
resources: 'delete'
}
denySettings: {
mode: 'denyDelete'
}
}

param foo = 'bar'
```

CLI usage:
```sh
bicep what-if main.bicepparam
bicep deploy main.bicepparam
# if using stacks
bicep destroy main.bicepparam
```

### New `readEnvVar()` & `readCliArg()` functions

Use the new `externalInput()` function as a way of giving the author control over how run-time values are read.

Define `readCliArg()` and `readEnvVar()` as syntactic sugar for `externalInput`:
* `readCliArg()` would be syntactic sugar for `externalInput('sys.cliArg', )`
* `readEnvVar()` would be syntactic sugar for `externalInput('sys.envVar', )`

* Example usage for `readEnvVar`:
```bicep
var subscriptionId = readEnvVar('AZURE_SUBSCRIPTION_ID')

using 'main.bicep' with {
mode: 'deployment'
scope: resourceGroup(subscriptionId, 'myRg')
}
```

CLI experience:
```sh
export AZURE_SUBSCRIPTION_ID=f794b1c4-c575-4f8d-9eb0-1816c630c110
bicep what-if main.bicepparam
bicep deploy main.bicepparam
```
* Example usage for `readCliArg`:
```bicep
var subscriptionId = readCliArg('subscription-id')

using 'main.bicep' with {
mode: 'deployment'
scope: resourceGroup(subscriptionId, 'myRg')
}
```

CLI experience:
```sh
bicep what-if --arg-subscription-id f794b1c4-c575-4f8d-9eb0-1816c630c110 main.bicepparam
bicep deploy --arg-subscription-id f794b1c4-c575-4f8d-9eb0-1816c630c110 main.bicepparam
```

These functions would be valid anywhere in the param file - not just in the `scope` field. For example:
```bicep
using 'main.bicep' with {
mode: 'deployment'
scope: resourceGroup('f794b1c4-c575-4f8d-9eb0-1816c630c110', 'myRg')
}

type EnvironmentType = 'test' | 'prod'

var environment EnvironmentType = readCliArg('env-name')

var config = {
test: ...
prod: ...
}[environment]

param envSuffix = config.suffix
```

Usage:
```sh
bicep deploy --arg-env-name test
bicep deploy --arg-env-name prod
```

## New CLI Commands

### `bicep deploy`

Initiates a deployment to Azure.

Provides a clean interface for tracking operations in real time and visualizing failures:

Image

### `bicep what-if`

Runs a what-if on Azure and reports results. Can also be used for validation only without returning results.

### `bicep destroy`

Deletes a Deployment Stack. Only valid if the `.bicepparam` file has been configured as a Stack with the `mode` property.

## Changes to existing CLI Commands

### `bicep local-deploy`

Remove this command group entirely, and just have "Local" be available under the `bicep deploy` command.

### `bicep snapshot`

Align with the arguments proposed for the new CLI command groups (`bicep deploy` etc).

## Other notes
### Deploy Pane
If accepted, the Deployment pane should be updated to operate with this new form of configuration.

## Trying this out

This functionality is currently available on an experimental branch. See [here](https://github.com/Azure/bicep/blob/ant/poc_cli/deploy/README.md) for information on previewing it.

https://github.com/user-attachments/assets/da64f3a3-3c11-411b-94b6-6324f79af107

## Open Questions
* Does the concept of "CLI Arguments" (as opposed to parameters) feel confusing?
* Could we simplify further by avoiding the need to type the file name in cases where it's unambiguous (e.g. `bicep deploy` if there's only a single `.bicepparam` file in the current directory)?
* How would we rationalize this with the experience already in Azure CLI & Azure PowerShell?

Contributor guide

Open the contributing guide

Research direction

Read the proposal and the experimental branch's deploy/README.md to understand the current proof of concept and the proposed command groups. The issue leaves several design questions open and does not define a bounded implementation or acceptance criteria, so completion would require an agreed direction before coding.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure
Domain
cli, cloud, devops
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.