Azure - Deploy Azure App using config-zip

Octopus.AzurePowerShell exported 2026-02-07 by twerthi belongs to ‘Azure’ category.

Deploy an Azure App Service (Web App or Function App) using the config-zip option. This template is compatible with deploying to Azure App Services that are on the Flexible Consumption Plan.

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Azure Account

Template.Azure.Account =

Choose the Azure account to use when executing this template.

Azure Resource Group Name

Template.Azure.ResourceGroup.Name =

The name of the Azure Resource Group to deploy the App Service to.

Azure App Service Name

Template.Azure.Service.Name =

The name of the Azure App Service (web app or function app) to deploy.

Azure App Service Type

Template.Azure.Service.Type =

Select the type of App Service you want to deploy.

Slot Name

Template.Azure.Slot.Name =

(Optional) Name of the slot to deploy to. Leave blank if you’re not using slot capabilities.

App Service Package

Template.Package =

The package to deploy.

Variable replacement in files pattern

Template.Replace.VariablesInFiles.Pattern = #{Octopus.Action.Package[Template.Package].ExtractedPath}/*.json

This template has the feature of Substitute Variables in Templates enabled, giving you the ability to replace Octopus Variable place holders in files. You can specify more than one file or pattern, newline separated.

Structured configuration variable replacement

Template.Replace.StructuredConfigurationVariables.Pattern = #{Octopus.Action.Package[Template.Package].ExtractedPath}/*.json

This template has the Structured Configuration Variables feature enabled giving you the ability to replace existing values within files. You can specify more than one file or pattern, newline separated.

Script body

Steps based on this template will execute the following PowerShell script.

Write-Host "Determining Operating System..."
# Check to see if $IsWindows is available
if ($null -eq $IsWindows)
{
    switch ([System.Environment]::OSVersion.Platform)
    {
    	"Win32NT"
        {
        	# Set variable
            $IsWindows = $true
            $IsLinux = $false
        }
        "Unix"
        {
        	$IsWindows = $false
            $IsLinux = $true
        }
    }
}

if ($IsWindows)
{
	Write-Host "Detected OS is Windows"
    $ProgressPreference = 'SilentlyContinue'
}
else
{
	Write-Host "Detected OS is Linux"
}

# Fix ANSI Color on PWSH Core issues when displaying objects
if ($PSEdition -eq "Core") {
    $PSStyle.OutputRendering = "PlainText"
}

# Get working variables
$packageExtractedPath = $OctopusParameters['Octopus.Action.Package[Template.Package].ExtractedPath']
$originalPath = $OctopusParameters['Octopus.Action.Package[Template.Package].OriginalPath']
$packageId = $OctopusParameters['Octopus.Action.Package[Template.Package].PackageId']
$packageVersion = $OctopusParameters['Octopus.Action.Package[Template.Package].PackageVersion']
$azureResourceGroupName = $OctopusParameters['Template.Azure.ResourceGroup.Name']
$azureServiceName = $OctopusParameters['Template.Azure.Service.Name']
$azureServiceType = $OctopusParameters['Template.Azure.Service.Type']
$slotName = $OctopusParameters['Template.Slot.Name']

# Check for Windows
if ($isWindows)
{
  ###########
  # Okay, I know this looks really weird, but during development and testing, I found that the method used in the else statement did something weird to the archive where
  # the deployment would fail, claiming the .azurfunctions folder is missing when it is clearly there only on Windows.  Grabbing the original file and only updating the changed files
  # from the variable replacement operations and uploading the updated file seems to work
  ###########
  # Grab the original archive file
  Copy-Item -Path $originalPath -Destination "$PWD/$($packageId).$($packageVersion).zip"

  # Update the original archive with the items from the repackaged one so it includes any replacement
  Compress-Archive -Path "$packageExtractedPath/*" -DestinationPath "$PWD/$($packageId).$($packageVersion).zip"  -Update
}
else
{
  # Repackage the files
  Get-ChildItem -Path $packageExtractedPath -Force | Compress-Archive -DestinationPath "$PWD/$($packageId).$($packageVersion).zip"
}

$archiveFile = Get-ChildItem -Path "$PWD/$($packageId).$($packageVersion).zip"

# Create argument array
$commandArguments = @()

# Deploy the service
switch ($azureServiceType)
{
  "functionapp"
  {
    # Append functionapp specific arguments
    $commandArguments += @("functionapp")
    break
  }
  "webapp"
  {
    $commandArguments += @("webapp")
    break
  }
}

# Add additional arguments
$commandArguments += @("deployment", "source", "config-zip", "--src", "$($archiveFile.FullName)", "--resource-group", "$azureResourceGroupName", "--name", "$azureServiceName")

# Check to see if they're using slots
if (![string]::IsNullOrWhitespace($slotName))
{
  $commandArguments += @("--slot", "$slotName")
}

# Execute command
Write-Host "Executing: az $commandArguments"



# Redirection of stderr to stdout is done different on Windows versus Linux
if ($IsWindows) {
    $commandArguments += @("2>&1")
    # Execute Liquibase
    az $commandArguments
}

if ($IsLinux) {
    # Execute Liquibase
    az $commandArguments 2>&1
}

# Check exit code
if ($lastExitCode -ne 0) {
    # Fail the step
    Write-Error "Deployment failed!"
}


#az $commandArguments

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "7517e099-cb94-4254-bdc7-4446b897f7b4",
  "Name": "Azure - Deploy Azure App using config-zip",
  "Description": "Deploy an Azure App Service (Web App or Function App) using the `config-zip` option.  This template is compatible with deploying to Azure App Services that are on the `Flexible Consumption Plan`.",
  "Version": 1,
  "ExportedAt": "2026-02-07T00:07:05.054Z",
  "ActionType": "Octopus.AzurePowerShell",
  "Author": "twerthi",
  "Packages": [
    {
      "Id": "783596ea-9a68-49c8-9cb8-ad1265893840",
      "Name": "Template.Package",
      "PackageId": "",
      "FeedId": null,
      "AcquisitionLocation": "Server",
      "Properties": {
        "Extract": "True",
        "SelectionMode": "deferred",
        "PackageParameterName": "Template.Package"
      }
    }
  ],
  "Parameters": [
    {
      "Id": "40555b1e-248d-458b-b33d-9cfb6a115998",
      "Name": "Template.Azure.Account",
      "Label": "Azure Account",
      "HelpText": "Choose the Azure account to use when executing this template.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "AzureAccount"
      }
    },
    {
      "Id": "b0a08a4c-b887-4170-ba5b-d4ac9d41b650",
      "Name": "Template.Azure.ResourceGroup.Name",
      "Label": "Azure Resource Group Name",
      "HelpText": "The name of the Azure Resource Group to deploy the App Service to.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "d3b07e0e-bc9a-4484-9022-6bd256138d21",
      "Name": "Template.Azure.Service.Name",
      "Label": "Azure App Service Name",
      "HelpText": "The name of the Azure App Service (web app or function app) to deploy.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "a82571c5-ab29-438d-81d1-a0b88638b5d7",
      "Name": "Template.Azure.Service.Type",
      "Label": "Azure App Service Type",
      "HelpText": "Select the type of App Service you want to deploy.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "functionapp|Function App\nwebapp|Web App"
      }
    },
    {
      "Id": "a9c66943-b6ff-4a4f-a01f-d0336eb7283d",
      "Name": "Template.Azure.Slot.Name",
      "Label": "Slot Name",
      "HelpText": "(Optional) Name of the slot to deploy to.  Leave blank if you're not using slot capabilities.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "817164f5-15d4-4813-aceb-b9cc619bec6c",
      "Name": "Template.Package",
      "Label": "App Service Package",
      "HelpText": "The package to deploy.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Package"
      }
    },
    {
      "Id": "b36e78de-622f-4c5b-9f33-dc770fa14e74",
      "Name": "Template.Replace.VariablesInFiles.Pattern",
      "Label": "Variable replacement in files pattern",
      "HelpText": "This template has the feature of [Substitute Variables in Templates](https://octopus.com/docs/projects/steps/configuration-features/substitute-variables-in-templates) enabled, giving you the ability to replace Octopus Variable place holders in files.  You can specify more than one file or pattern, newline separated.",
      "DefaultValue": "#{Octopus.Action.Package[Template.Package].ExtractedPath}/*.json",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Id": "a42d44b3-c824-41d4-a18e-43cf3a55b458",
      "Name": "Template.Replace.StructuredConfigurationVariables.Pattern",
      "Label": "Structured configuration variable replacement",
      "HelpText": "This template has the [Structured Configuration Variables](https://octopus.com/docs/projects/steps/configuration-features/structured-configuration-variables-feature) feature enabled giving you the ability to replace existing values within files.  You can specify more than one file or pattern, newline separated.",
      "DefaultValue": "#{Octopus.Action.Package[Template.Package].ExtractedPath}/*.json",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "OctopusUseBundledTooling": "False",
    "Octopus.Action.Azure.AccountId": "#{Template.Azure.Account}",
    "Octopus.Action.EnabledFeatures": "Octopus.Features.JsonConfigurationVariables,Octopus.Features.SubstituteInFiles",
    "Octopus.Action.Package.JsonConfigurationVariablesTargets": "#{Template.Replace.StructuredConfigurationVariables.Pattern}",
    "Octopus.Action.SubstituteInFiles.TargetFiles": "#{Template.Replace.VariablesInFiles.Pattern}",
    "Octopus.Action.Script.ScriptBody": "Write-Host \"Determining Operating System...\"\n# Check to see if $IsWindows is available\nif ($null -eq $IsWindows)\n{\n    switch ([System.Environment]::OSVersion.Platform)\n    {\n    \t\"Win32NT\"\n        {\n        \t# Set variable\n            $IsWindows = $true\n            $IsLinux = $false\n        }\n        \"Unix\"\n        {\n        \t$IsWindows = $false\n            $IsLinux = $true\n        }\n    }\n}\n\nif ($IsWindows)\n{\n\tWrite-Host \"Detected OS is Windows\"\n    $ProgressPreference = 'SilentlyContinue'\n}\nelse\n{\n\tWrite-Host \"Detected OS is Linux\"\n}\n\n# Fix ANSI Color on PWSH Core issues when displaying objects\nif ($PSEdition -eq \"Core\") {\n    $PSStyle.OutputRendering = \"PlainText\"\n}\n\n# Get working variables\n$packageExtractedPath = $OctopusParameters['Octopus.Action.Package[Template.Package].ExtractedPath']\n$originalPath = $OctopusParameters['Octopus.Action.Package[Template.Package].OriginalPath']\n$packageId = $OctopusParameters['Octopus.Action.Package[Template.Package].PackageId']\n$packageVersion = $OctopusParameters['Octopus.Action.Package[Template.Package].PackageVersion']\n$azureResourceGroupName = $OctopusParameters['Template.Azure.ResourceGroup.Name']\n$azureServiceName = $OctopusParameters['Template.Azure.Service.Name']\n$azureServiceType = $OctopusParameters['Template.Azure.Service.Type']\n$slotName = $OctopusParameters['Template.Slot.Name']\n\n# Check for Windows\nif ($isWindows)\n{\n  ###########\n  # Okay, I know this looks really weird, but during development and testing, I found that the method used in the else statement did something weird to the archive where\n  # the deployment would fail, claiming the .azurfunctions folder is missing when it is clearly there only on Windows.  Grabbing the original file and only updating the changed files\n  # from the variable replacement operations and uploading the updated file seems to work\n  ###########\n  # Grab the original archive file\n  Copy-Item -Path $originalPath -Destination \"$PWD/$($packageId).$($packageVersion).zip\"\n\n  # Update the original archive with the items from the repackaged one so it includes any replacement\n  Compress-Archive -Path \"$packageExtractedPath/*\" -DestinationPath \"$PWD/$($packageId).$($packageVersion).zip\"  -Update\n}\nelse\n{\n  # Repackage the files\n  Get-ChildItem -Path $packageExtractedPath -Force | Compress-Archive -DestinationPath \"$PWD/$($packageId).$($packageVersion).zip\"\n}\n\n$archiveFile = Get-ChildItem -Path \"$PWD/$($packageId).$($packageVersion).zip\"\n\n# Create argument array\n$commandArguments = @()\n\n# Deploy the service\nswitch ($azureServiceType)\n{\n  \"functionapp\"\n  {\n    # Append functionapp specific arguments\n    $commandArguments += @(\"functionapp\")\n    break\n  }\n  \"webapp\"\n  {\n    $commandArguments += @(\"webapp\")\n    break\n  }\n}\n\n# Add additional arguments\n$commandArguments += @(\"deployment\", \"source\", \"config-zip\", \"--src\", \"$($archiveFile.FullName)\", \"--resource-group\", \"$azureResourceGroupName\", \"--name\", \"$azureServiceName\")\n\n# Check to see if they're using slots\nif (![string]::IsNullOrWhitespace($slotName))\n{\n  $commandArguments += @(\"--slot\", \"$slotName\")\n}\n\n# Execute command\nWrite-Host \"Executing: az $commandArguments\"\n\n\n\n# Redirection of stderr to stdout is done different on Windows versus Linux\nif ($IsWindows) {\n    $commandArguments += @(\"2>&1\")\n    # Execute Liquibase\n    az $commandArguments\n}\n\nif ($IsLinux) {\n    # Execute Liquibase\n    az $commandArguments 2>&1\n}\n\n# Check exit code\nif ($lastExitCode -ne 0) {\n    # Fail the step\n    Write-Error \"Deployment failed!\"\n}\n\n\n#az $commandArguments"
  },
  "Category": "Azure",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/a381802920158308/step-templates/azure-deploy-app-service-config-zip.json",
  "Website": "/step-templates/7517e099-cb94-4254-bdc7-4446b897f7b4",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////AHjXf7vrv931QJrh7/f8EIDaIIncMJHfYKvmz+b3n8zw3+76j8Ttr9XycLPpUKLkkKvYFAAABGZJREFUeNrsnNmCqjoQRc1MEiD8/9cer7Yt2KBJZQC8ez07sKlKTQlcLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzoUSnt8YxXlFuGHSbIaxvj+fip4btkLn1blkWLaF5v03yLhLOYlVuGYfMOMZzNGxCOzhjTJqFkXnjq3Dr1yyvPI3hGl3Ih3zzHHNKudRstRhX5O58vIcShY67Gq6EPIESlzUWvazaGAOGbvU7ArDu/g8M4o8opDZWvbvPzlL/MMBE8jT9T9W7PbAJlHPTBFRf9yVTEcs63msXz2UHLSgf650G/d5t+wjbxxB2UCMqGrk8/LFSD7uJMeNt5bcJCyQZyAe5Fo9KYfWS2flQrr4b4tpuzaeWjYs49rt9LHf9uZD7+VbyVi9EBNrjYjuq2sxQOrl+p+HuBVu45qvqfq691ttYFQ5KyKbyJgaIY/NGxrlWZwlwGvmvu1oY3PuAv0niTq6tZ78jk//9uc1r1r4lQki7y7sp2Tu4V1y2iLoqFTqi1lIGcpFiebrZNZ1dOkF0cCIlO8jQ47nCkam9Lilz9GhDF1I6XGLzfnhwDIIZVfI7+8SSgfHsijqXENOGJF5QorG4EcW0OrScqX/dDrXpr70Ut/BII+1OfECPuYz/NWxYmgrCsUskxPvyhgmrw+WGZ6lGTuOlIyCYWTFyWjpM5KIZRUIOwjRNYRQ6tZF9BXtk8hWAHPtLNJ727Fq0JSkC1FDRRF0Jalj0d5qVh2KEpM2TuSsCYTCT6ZkdmFYI9LrYp5QayWbo6NXlZwcRD/61pth5Fq5EX423QQxNjhqWvvklkljOLkYjrmphXPZOJOk6Pg7HKMsrtQKcowzZoK3rx1ZUelGMdQA/HaKkjAt2RgqpZeYqbNbH7Hp2ct4nqfSPOfe0ftiSTZJydOV6rG5bQbyLK+nRuCC0343PzDgiOXyQA5c14BTZi98uR/5KJ1SnatLdoO50WWBQZPTq0VgsklU3h932actuo17ayrHrb/3ykiegd3KbqF2wbV6RrlsJ07yLcpsWFTul9RyK6ZScr+tk7oNrFj0o7HQUlj4EiEvJ6rPLKSmlMZCrksl1OnLaRkxc+/HB1naMhNtT/6yM2bDs6azCRHrM3aVPN7aW8irD/10B8njpAMcsl8okXcdKrl4sPsLmQVy/Sj90ucPRc/d/Bxxj+dXSpCayen32D+hLi16MsIV8gfCXrYp6ySsiJKRUF0XXiLpVbFU+fNv4r7mOwhFsX4ZdwpSi1DYs2jb6ebZ9788cblTzMrYhu7sf/17IFdtuviJ2ioHA6pMHkoH4CLUeMBU7iGkxuM/YgcdderF9ibRdc7O982F1HpYhjfWUe+x5a6pjop9iNLfoePvlsdZdTSMwfxSmTY20Q0eHnUNzga1edeNmmqbg18aMVR1L9vwSXHF9TfIWBxpKLs2hj3eQeBC0USvp2HHF3eIkRdhFOd6ER8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/I/4J8AAo/80BciBec4AAAAASUVORK5CYII=",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Saturday, February 7, 2026