DEV Community

Cover image for Using bicep-deploy in GitHub action, part 2, deploymentStack
Olivier Miossec
Olivier Miossec

Posted on

Using bicep-deploy in GitHub action, part 2, deploymentStack

A few weeks ago, I presented the Bicep-Deploy GitHub Action that could test and deploy Bicep templates and validate, deploy, and delete deploymentStacks. The first part was about Bicep templates, the second is for deploymentStack.

With DeploymentStack you can perform these operations with bicep-deploy

  • Validate, to lint the code.
  • Create, to create a stack at the Management Group, Subscription, or Resource Group level.
  • Delete, to delete a stack.

To illustrate this post, I will use a simple resource group-level template, creating a network infrastructure (a VNET with its subnets, and a Network Security Group.

param location string = resourceGroup().location
param vnetName string = 'mainVnet'

var vnetTags object = {
  environment: 'production'
  owner: 'admin'  
  }  

var nsgRules = [
  {
    name: 'default-nsg'
    rules: [
      {
      name: 'rule-deny-all'
      properties: {
        description: 'description'
        protocol: 'Tcp'
        sourcePortRange: '*'
        destinationPortRange: '*'
        sourceAddressPrefix: '*'
        destinationAddressPrefix: '*'
        access: 'Deny'
        priority: 3000
        direction: 'Inbound'
        }      
      }
      {
      name: 'rule-allow-rdp'
      properties: {
        description: 'description'
        protocol: 'Tcp'
        sourcePortRange: '*'
        destinationPortRange: '3389'
        sourceAddressPrefix: '*'
        destinationAddressPrefix: '*'
        access: 'Allow'
        priority: 150
        direction: 'Inbound'
        } 
      }
      {
        name: 'rule-allow-ssh'
        properties: {
          description: 'description'
          protocol: 'Tcp'
          sourcePortRange: '*'
          destinationPortRange: '22'
          sourceAddressPrefix: '*'
          destinationAddressPrefix: '*'
          access: 'Allow'
          priority: 110
          direction: 'Inbound'
        } 
      }
    ]
  }    
]

resource NetworkSecurityGroups 'Microsoft.Network/networkSecurityGroups@2024-07-01' = [for rule in nsgRules: {
  name: rule.name
  location: resourceGroup().location
  properties: {
    securityRules: rule.rules
  }
}]

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-07-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'Subnet-1'
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
      {
        name: 'Subnet-2'
        properties: {
          addressPrefix: '10.0.1.0/24'

        }
      }
    ]
  }
}
resource crutialSubnet 'Microsoft.Network/virtualNetworks/subnets@2024-07-01' = {
  name: 'crucial'
  parent: virtualNetwork
  properties: {
    addressPrefix: '10.0.2.0/24'
  }
}
Enter fullscreen mode Exit fullscreen mode

But first, let’s build the workflow. I will reuse the workflow from the first part for the connection.

name: Bicep-deploy stack demo

on: 
  push: 
    branches: 
      - main

permissions:
  id-token: write
  contents: read

jobs:
  Bicep-deploy-demo:
    name: Bicep-Deploy Stack
    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
Enter fullscreen mode Exit fullscreen mode

Validating a deployment stack is similar to validating a Bicep code.

Before trying to validate a deploymentStack we need to make sure that the identity running the pipeline has the privilege to manage deploymentStack, including the deny settings; Azure Deployment Stack Contributor. Without this role, you will not be able to validate the stack.

      - name: Validate deploymentStack Code in GitHub
        uses: azure/bicep-deploy@v2
        with:
          type:  deploymentStack
          operation: validate
          name: Validate-code
          scope: resourceGroup
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
          resource-group-name: bicep-deploy
          template-file: ./Stack/vnet.bicep
          action-on-unmanage-resources: delete
          deny-settings-mode: denyWriteAndDelete
Enter fullscreen mode Exit fullscreen mode

You will need to give the deploymentStack type, the operation, the scope (here at the resource group level), and what will happen to unmanaged resources (delete or detach) and deny settings (none, denyDelete or denyWriteAndDelete).

You can customize the validation by adding a bicepconfig.json file in the same directory. You can trigger an error if the validation finds unused variables or parameters. See

There is no whatif operation for deploymentStack to test what will be deployed, there are only two other operations create and delete.

The “Create” operation creates the deployment stack in the scope defined by the scope parameter (Management Group, Subscription, or resource group).

Here’s an example

      - name: Validate deploymentStack Code in GitHub
        uses: azure/bicep-deploy@v2
        with:
          type:  deploymentStack
          operation: create
          name: create-stack
          scope: resourceGroup
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
          resource-group-name: bicep-deploy
          template-file: ./Stack/vnet.bicep
          action-on-unmanage-resources: delete
          deny-settings-mode: denyWriteAndDelete
Enter fullscreen mode Exit fullscreen mode

The same code we use to validate is used to deploy the Stack. In this example, the unmanaged resources are deleted, and users are not allowed to update or delete resources deployed by the stack. You can also use the deny-settings-excluded-actions to exclude action from the deny settings and deny-settings-excluded-principals to exclude a list of users/applications from the deny settings. Check this post for more details

Running the pipeline will create the deploymentStack create-stack.

The last operation that we can do with the bicep-deploy action. The delete operation is similar to the create operation. It takes the same parameters; you need to provide the name of the deployment, the scope, the template you used to deploy the stack (and parameters if any), the action-on-unmanage-resources and deny-settings-mode parameters (if you omit then you will have an error).

     - name: Validate deploymentStack Code in GitHub
        uses: azure/bicep-deploy@v2
        with:
          type:  deploymentStack
          operation: delete
          name: create-stack
          scope: resourceGroup
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
          resource-group-name: bicep-deploy
          template-file: ./Stack/vnet.bicep
          action-on-unmanage-resources: delete
          deny-settings-mode: denyWriteAndDelete
Enter fullscreen mode Exit fullscreen mode

This will delete the deploymentStack object on the resource group and remove all resources associated with this stack.

$150K MiniMax AI Agent Challenge — Build Smarter, Remix Bolder, Win Bigger!

Join the MiniMax AI Agent Challenge — Build your first AI Agent 🤖

Developers, innovators, and AI tinkerers, build your AI Agent and win $150,000 in cash. 💰

Read more →

Top comments (0)

Heroku

Tired of jumping between terminals, dashboards, and code?

Check out this demo showcasing how tools like Cursor can connect to Heroku through the MCP, letting you trigger actions like deployments, scaling, or provisioning—all without leaving your editor.

Learn More

👋 Kindness is contagious

Explore this practical breakdown on DEV’s open platform, where developers from every background come together to push boundaries. No matter your experience, your viewpoint enriches the conversation.

Dropping a simple “thank you” or question in the comments goes a long way in supporting authors—your feedback helps ideas evolve.

At DEV, shared discovery drives progress and builds lasting bonds. If this post resonated, a quick nod of appreciation can make all the difference.

Okay