Unable to dynamically specify Web App Name in Octopus v2018.7.7

We have recently upgraded to Octopus v2018.7.7, but we have run in to a major issue with the way that Azure Web Apps are now deployed. I sincerely hope that I’m missing something, but I fear not.

Previously (sorry, don’t know the old version) we were able to specify Azure and Web App settings within the Deploy an Azure Web App step, and it was perfect as it allowed us to dynamically set things like a Web App Name (Function Apps in our case) and the Resource Group.

Now it seems that we have to add Azure Web App targets and pre-specify both the Web App Name and the Resource Group. This is hugely undesirable for the majority of our projects, and simply not possible for the others.

Currently when deploying our Web Apps we have a two step approach -

  1. Use the Run an Azure Resource Group step to create a Function App and any associated resources. This seems unchanged.
  2. Use the Deploy an Azure Web App step to push the contents of a NuGet package to the newly created Function App.

So our problem is two-fold -

  1. For projects where we know in advance what environments should exist, in the first instance we’d have to create an Azure Web App target for each environment. It means that we’d have to manually create a Function App in every environment so that we can create target for it, which would be a very laborious process, and destroys the entire point of automation via Octopus.
  2. For projects where we utilise dynamic environment naming, I can’t see that it’s possible for us to continue using Octopus. Our larger projects require us to create an environment (including various Function Apps) based on the name of Git feature branch being deployed. It’s therefore impossible for us to know in advance what it will be.

Note that previously configured deployments still work, so as an emergency I could look to clone on of them, but I’m guessing that this legacy functionality will be removed in the future.

As previously mentioned, I hope that I’m missing something on the updated version, so any advise is welcome.

Hi David,

Thanks for getting in touch.

We did make changes to introduce Azure PaaS targets starting in 2018.5, but along with the new targets, there is also some built-in target management available through PowerShell Cmdlets, which will help you create or delete your targets dynamically in the same way you are creating the Azure infrastructure.

On this blog post, there is a walk-through on using the dynamic infrastructure cmdlets, with examples on how to use them via ARM template step in a post-deploy script.
One benefit that is available out of managing your Azure Apps/Functions through deployment targets, you can have a separate process to provision your infrastructure and another process for deploying the applications, through the use of Automatic Deployment, new infrastructure could be provisioned and the supporting applications can be deployed after a health check has occurred. When a new version of the application is published to Octopus, this can be deployed to all targets, through the use of roles, without the need to scope your infrastructure steps in the same process.

Would you be able to explain what you mean in regards to dynamic environment naming? Are you wanting to dynamically create Octopus logical environments, or is it the way in which you are naming your Azure web apps/functions?

At this point in time, there is no plan to remove the legacy functionality of the Azure Web App, you can expect it to continue working as it is today.

I hope I have answered all your questions. Feel free to get back to me if you have any further questions.

Regards
Ben

Hi Ben,

Thanks for your reply.

Currently we use Cloud Regions, thus enabling us to deploy to a single region in lower environments but to multiple regions in our production environment. We achieve this through variable scoping. Please see the screen shots below that show examples of how we create Cloud Region Deployment Targets, how we scope variables and how we target Cloud Regions in our process - much easier then me describing exactly what we do!

So if I was to create a Deployment target via a pre-deployment script in the Deploy an Azure Web App step, and then delete it via a post-deployment script, how would I be able to scope my variables for specific regions? I’m assuming I would also need to keep the Cloud Regions that have already been set up, and that I assign the same roles as they have to the dynamically created Azure Web App deployment target?

Deployment targets

Variables

Process

For your information, for our dynamic environment naming, I mean that we dynamically name Azure Web Apps based on the name of the Git feature branch that a release was created from. For example, if our Git feature branch is called newfeature1, we’d want to create an Azure Function App called lmk-bvt-appname-newfeature1. Previously, we could declare the name of the Web App in the Deploy an Azure Web App step by setting the value of the Web App Name setting to #{AzureWebAppName}. The AzureWebAppName variable value is set upon release creation, which we use Bamboo to handle.

Thanks,
David

Hi David,

Sorry for the delay in getting back to you.
Regarding your question about scoping of your variables, I would suggest using specific roles for each specific region, scoping the variable values to those roles and creating your deployment targets with these same roles. In the cmdlet the role parameter is a comma separated list, so you can apply multiple roles to a new deployment target.
You shouldn’t need to keep the Cloud Regions, you can run the script steps on behalf of the region-specific roles, even if they map to an Azure Web App target, but you also don’t have to stop using as they don’t contribute your license limits.

Please let me know if this doesn’t answer your question.

Regards
Ben

Hi Ben,

Apologies for my slow reply, I have been on holiday.

In reference to suggestion that we shouldn’t need to keep the Cloud Regions, I have been doing some testing, but I can’t get the deployment to work. Currently our deployment has four steps, all of which targets to role dgtest-non-live -

  1. Deploy ARM Template: Built in Deploy an Azure Resource Group step. I have to run this step first, as Octopus doesn’t allow creation of an Azure Web App deployment target if the Web App it targets doesn’t exist.
  2. Create Azure Web App Deployment Target: Custom scrip to create an Azure Web App deployment target.
  3. Deploy NuGet Package: Built in Deploy an Azure Web App step. We’re talking about Function Apps here, so this is were we actually deploy the code.
  4. Remove Octopus Deployment Target: Custom scrip to delete a deployment target. Many of our Web Apps are only ever deployed once (and cleaned daily), so we don’t want superfluous deployment targets hanging around.

Upon first run, I was presented with an error -

There was a problem with your request.

There must be at least one enabled healthy machine to deploy to in the environment, or the Project Deployment Target settings must be set to allow deployments to empty environments.
Once you have corrected these problems you can try again.
If the problem is related to a variable you will need to update the variables for this release or recreate the release for the changes to take effect.
If the problem is related to the deployment process you will need to create a new release for the changes to take effect.

After changing the project setting Deployment Targets to Allow deployments to be created when there are no deployment targets, I tried again, but this time every single step was simply skipped -

Skipping this step as no machines were found in the roles: dgtest-non-live

I’ve tried many different variations, each of which seems to have it’s own failings. For example, if we try to create the Azure Web App deployment target first, the deployment fails because the actual Azure Web App doesn’t exist yet, and Octopus won’t allow as to pre-stage the deployment targets.

The closest I’ve been able to get to a working solution is as below, however this still has a major flaw and a major annoyance. The major problem is that in our live environment we deploy to multiple environments (thus target multiple roles for that environment), but on first run step 3 will only deploy to one region (seemingly random), and the major annoyance is that we have to scope variables against two roles for live (due to deploying to multiple regions), not just one. -

  1. Deploy ARM Template: Target a Cloud Region deployment target.
  2. Create Azure Web App Deployment Target: Target a Cloud Region deployment target.
  3. Deploy NuGet Package: Target a role that was assigned to the Azure Web App deployment target created in step 2.
  4. Remove Octopus Deployment Target: Target a Cloud Region.

I sincerely hope that I am missing something, because you’d hope that things like this before were tested? I mean, adding the ability to create Azure Web App deployment targets is one thing, but it seems absurd to remove a working solution at the same time.

Thanks,
David

Hi David, sorry for the slow response.

This is definitely a scenario which we have tested and as long as the target created has the same role that is used as part of the deployment everything will work. As an example, you could create a target per cloud region with the same name as the function and give it a role name such as AzureFunction. You would then use the AzureFunction as the role in the web deployment step. The target contains all the necessary information for what we are targeting but how that is chosen based on the scoping applied i.e. environments, tenants etc.

Could I get a bit more information from you as to how you are creating your targets, the roles you are assigning to them and which roles you are using in your deployment, please?

Regards,
Shaun

Hi Shaun,

I can get single region deployments working, albeit with two additional steps compared to what was required pre-update - a scripted solution to create a deployment target, and then another to delete the deployment target, because we don’t want it hanging around (will likely never be used again).

However, the issue with multi-region deployments still remains. I have amended my deployment process slightly from the one I described previously based on your suggestion -

  1. Deploy ARM Template: Target Cloud Regions with roles azure-live-uk-west and azure-live-uk-south.
  2. Create Azure Web App Deployment Target: Target Cloud Regions with roles azure-live-uk-west and azure-live-uk-south. The new targets both have the role dgtest-live, while one also has dgtest-live-uk-west and the other dgtest-live-uk-south to allow for variable scoping to set different values for the different regions.
  3. Deploy NuGet Package: Target newly created Azure Web App deployment targets with role dgtest-live.
  4. Remove Octopus Deployment Target: Target Cloud Regions with roles azure-live-uk-west and azure-live-uk-south.

As you can see from the Results below, when deploying to a multi-region environment, the Deploy NuGet Package Process step is only run against one region. The region it picks is seemingly random and changes from one deployment to the next.

Results

Process

See this GitHub issue related to this problem

I can confirm that the workaround suggested by Ben seems to work.

Until this has been resolved, a workaround is to add a Health Check step into the process between the step responsible for creating the target and the step responsible for deploying the package.

However, don’t just use the default settings for the Health Check step; change the New Deployment Targets option to Include new deployment targets in the deployment.