There are several options for deploying resources in Azure with Bicep from a GitHub repository. You can use Azure CLI or Azure PowerShell, but you can also use the GitHub Action Bicep-deploy.
The Bicep-Deploy (Azure/bicep-deploy@v2) action is versatile and can be used in different situations. You can deploy or test a Bicep template or create a stack using a deployment stack.
Every bicep-deploy action must have a name and a location. The name is a free text, the location must be a valid Azure Region. A description can be added to the action with the parameter description, but it is optional.
The bicep-deploy action can deploy Bicep templates and Azure Stack. The “type” parameter determines this: deployment for Bicep template deployment or deploymentStack for Stack deployment.
The second parameter to use with the bicep-deploy is “operation”. This parameter can take two sets of values, depending on the type of deployment.
For Bicep deployment
- Create, to create the infrastructure using the Bicep code
- Validate, to lint the Bicep code
- WhatIf, to perform a WhatIf (that can be used with the validation-level and what-if-exclude-change-types parameters)
The validation-level parameter can take 3 values:
- Template, do not validate the template at the provider level
- ProviderNoRbac, perform a validation at the provider level using a read-only permission
- Provider, perform a validation at the provider level
For DeploymentStack
- Create, to create the deploymentStack
- Validate, to lint the code
- Delete, to delete the deploymentStack
The scope also depends on the deployment type; tenant, managementGroup, subscription, resourceGroup for deployment and managementGroup, subscription, resourceGroup for deploymentStack.
Some parameters are specific to deploymentStack
- action-on-unmanage-resources Detach or delete
- action-on-unmanage-resourcegroups Detach or delete
- action-on-unmanage-managementgroup Detach or delete
- deny-settings-mode denyDelete, denyWriteAndDelete, or none
- deny-settings-excluded-actions List of role-based management operations that will not be deny
- deny-settings-excluded-principals List of Service Principal that will not be deny
- deny-settings-apply-to-child-scopes True if you want to apply the deny to child resources
- bypass-stack-out-of-sync-error To run the deployment when the stack is not correctly in sync
Let’s try to view that with a Bicep Deployment.
We have a simple Bicep Code to deploy a VNET with two subnets.
param location string = resourceGroup().location
@description('VNet name') param vnetName string = 'vnet1' @description('Vnet Address space') param vnetAddressPrefix string = '10.0.0.0/8' @description('Subnet1 Prefix') param subnet1Prefix string = '10.0.0.0/24' @description('Subnet1 Name') param subnet1Name string = 'sub1' @description('Subnet2 Prefix') param subnet2Prefix string = '10.0.1.0/24' @description('Subnet2 Name') param subnet2Name string = 'sub2' // an unused variable to test Bicep linter var unusedVariable = 'nice to have' resource vnet 'Microsoft.Network/virtualNetworks@2024-01-01' = { name: vnetName location: location properties: { addressSpace: { addressPrefixes: [ vnetAddressPrefix ] } } } resource subnet1 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' = { parent: vnet name: subnet1Name properties: { addressPrefix: subnet1Prefix } } resource subnet2 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' = { parent: vnet name: subnet2Name properties: { addressPrefix: subnet2Prefix } }
We need to set the workflow.
I already covered how to test, apply a what-if, and deploy a Bicep template with PowerShell in a previous [blog post]((https://dev.to/omiossec/create-a-github-pipeline-to-test-review-and-deploy-a-bicep-template-h45), here I will reproduce the same template I used before and deploy a Stack.
First, we need an identity to connect to Azure, I will use a Federated identity; the process is described in my last post. You can check this page
The identity will be used to connect to Azure using 3 secrets: AZURE_CLIENT_ID, secrets.AZURE_TENANT_ID, and secrets.AZURE_SUBSCRIPTION_ID in a GitHub environment called DevTo-Demo.
name: Bicep-deploy demo on: push: branches: - main permissions: id-token: write contents: read jobs: Bicep-deploy-demo: name: Bicep-Deploy Demo runs-on: ubuntu-latest environment: DevTo-Demo steps: - name: Checkout uses: actions/checkout@v4 - name: login to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} enable-AzPSSession: true
The first action should be to test the code with Bicep Lint with the validate operation.
- name: Validate Bicep Code uses: azure/bicep-deploy@v2 with: type: deployment operation: validate name: Validate-code scope: resourceGroup subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} resource-group-name: bicep-deploy template-file: ./Bicep/main.bicep
This will check for errors in the Bicep code by using the default rules
You can use a bicepconfig.json rule to customize the linter see
For example, there is an unused variable in the Bicep code
// an unused variable to test linter var unusedVariable = 'nice to have'
By default, it will trigger a warning, but this behavior can be changed by using the bicepconfig.json
"no-unused-vars": { "level": "error" },
The second action is to perform a what-if to see what will be deployed/changed with the Bicep code.
- name: Execute Whatif uses: azure/bicep-deploy@v2 with: type: deployment operation: whatIf name: whatIf-Bicep_code scope: resourceGroup subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} resource-group-name: bicep-deploy template-file: ./Bicep/main.bicep
The result of the what-if action will be something like that (if it is the first time you run it).
Scope: /subscriptions/***/resourceGroups/bicep-deploy 34 35 + Microsoft.Network/virtualNetworks/vnet1 [2024-01-01] 36 37 apiVersion: "2024-01-01" 38 id: "/subscriptions/***/resourceGroups/bicep-deploy/providers/Microsoft.Network/virtualNetworks/vnet1" 39 location: "westeurope" 40 name: "vnet1" 41 properties.addressSpace.addressPrefixes: [ 42 0: "10.0.0.0/8" 43 ] properties.subnets: [ 44 0: 45 46 name: "sub1" 47 properties.addressPrefix: "10.0.0.0/24" 48 49 1: 50 51 name: "sub2" 52 properties.addressPrefix: "10.0.1.0/24" 53 54 ] type: "Microsoft.Network/virtualNetworks" 55 56 + Microsoft.Network/virtualNetworks/vnet1/subnets/sub1 [2024-01-01] 57 58 apiVersion: "2024-01-01" 59 id: "/subscriptions/***/resourceGroups/bicep-deploy/providers/Microsoft.Network/virtualNetworks/vnet1/subnets/sub1" 60 name: "sub1" 61 properties.addressPrefix: "10.0.0.0/24" 62 type: "Microsoft.Network/virtualNetworks/subnets" 63 64 + Microsoft.Network/virtualNetworks/vnet1/subnets/sub2 [2024-01-01] 65 66 apiVersion: "2024-01-01" 67 id: "/subscriptions/***/resourceGroups/bicep-deploy/providers/Microsoft.Network/virtualNetworks/vnet1/subnets/sub2" 68 name: "sub2" 69 properties.addressPrefix: "10.0.1.0/24" 70 type: "Microsoft.Network/virtualNetworks/subnets" 71 72Resource changes: 3 to create.
The next step will be to deploy the resource from the template. However, before deploying the Bicep template, you would like to validate the Bicep What-if action to ensure that nothing goes wrong.
You need to set up a new GitHub environment where the option “Required reviewers” is selected.
Then you add a new job to deploy the Bicep template and add the “need” to reference the previous job.
Bicep-deploy-after-review: name: run azure deploy runs-on: ubuntu-latest environment: bicep-deploy needs: Bicep-deploy-demo steps: - name: Checkout uses: actions/checkout@v4 - name: login to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} enable-AzPSSession: true - name: Deploy Bicep Code uses: azure/bicep-deploy@v2 with: type: deployment operation: create name: deploy-Bicep_code scope: resourceGroup subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} resource-group-name: bicep-deploy template-file: ./Bicep/main.bicep
In part 2, I will cover deploymentStack
Top comments (1)
Great walkthrough! Could you explain some common issues or errors you’ve run into when using bicep-deploy in GitHub Actions? For your next post, maybe you could show how to manage rollbacks or handle failures in Bicep deployments automatically.