A/B deployment strategies with Azure Web App Deployment Slots

(joona.hook) #1

Hi,
We would like to use A/B deployment strategy with Azure Web App deployment slots.
Our pipeline would be Acc->Stage->Preprod->Production.
Deployments to Stage would deploy automatically to “PreProd” deployment slot in production.
Production deployment would be done manually usually few days later.
I’ve read that recommended way to do this is to create separate environment for example “PreProd” having all deployment targets in this environment as “PreProd” deployment slots.
However this causes lots of overhead and chance of misconfiguration when dealing with variables.
Our existing variables are scoped with environments and this setup would force us to add “PreProd” to each variable scoped to “Production” in practice go through hundreds of variables manually.
Another way to handle this could be to use channels:

  • Create new channel FromAccToStageToPreProd RC->Stag->Preprod(Preprod Deployed automatically)
  • Create another channel StraightToProductionWithSwap
  • Modify deployment projects to execute slot deployment steps only with channel FromAccToStageToPreProd
  • Deploy to production using StraightToProductionWithSwap lifecycle that would be scoped to execute actual slot swap and any other production steps

Do you see that using channels would be a viable option to handle this?
Any other way to handle this?

(Shaun Marx) #4

Hi joona_hook, thanks for getting in touch,

Just to confirm, are these separate web apps for each environment or are you using a single web app with a slot to represent each environment? We tend to view web app slots as staging slots which enable zero downtime deployments (I.e. switching between staging/production), rather than creating a slot for each environment. If you are deploying to a separate web app for production then this should alleviate the issue here since:

  • The staging slot can then be viewed as pre-prod and would use the same variables scoped to prod
  • Can be verified before swapping slots
  • Allows you to add a manual intervention step in between the web app deployment steps and the slot swap steps which in turn can also be scoped to prod if necessary.

In regards to channels being a viable option to handle this. I think it may be possible, however this may be using channels in a way in which it was never intended to be used. You may end up with some complex channel rules if you ever do wish to use channels for something like hotfixes as well.

Regards,
Shaun

(joona.hook) #5

Hi,
These are separate web apps in each environment. Pre-prod is deployment slot of production environment. Idea is that when doing staging deployment we would also do a Pre-Prod deployment to production staging slot. This way we could reduce production deployment time and use this Pre-Prod environment to do any last minute testing and verifications.

(Shaun Marx) #7

Hi joona_hook, thanks for that,

This is a scenario which we currently can’t model too well as the the deployment process is slightly different for UAT -> Staging vs Staging -> Prod. You could achieve this by using a combination of roles and scoping to the appropriate environments. The following is an example of what the targets and deployment process may look like:


This will ensure that all variables scoped to pre-prod is used for the production staging slot while the deployment to prod is a simple slot swap once the green light has been given.

Please let me know if the above doesn’t work for you or if I have misunderstood anything,

Regards,
Shaun

(joona.hook) #8

Hi,
In your example there’s actual Preproduction environment. Does this mean that we should go through near hundred variables that are scoped like this now :
image
and change scope to include PreProduction?

(Shaun Marx) #10

Hi joona_hook,

Yes, unfortunately we don’t make it easy to make bulk changes to variables via the UI at present (we’re aiming to address this in the future), so the only alternative would be to script this out. The UI would be using our REST API under the covers, so you can achieve anything the UI can and more. The following is an example using the Octopus.Client using c# to scope each variable value which has been scoped to Production to include Preproduction. You can run this fairly easily using something like linqpad:

C# Example

   var projectName = "target_project";

   var endpoint = new OctopusServerEndpoint("http://octopus_server", "your_api_key");
   var repository = new OctopusRepository(endpoint);
   var project = repository.Projects.FindByName(projectName);
   var variableSet = repository.VariableSets.Get(project.VariableSetId);
   
   //Choose equivalent environments
   var production = variableSet.ScopeValues.Environments.First(x => string.Compare(x.Name, "Production", StringComparison.OrdinalIgnoreCase) == 0);
   var preProduction = variableSet.ScopeValues.Environments.First(x => string.Compare(x.Name, "Preproduction", StringComparison.OrdinalIgnoreCase) == 0);

   foreach (var variable in variableSet.Variables)
   {
       if (variable.Scope.ContainsKey(ScopeField.Environment))
       {
           var scopeValue = variable.Scope[ScopeField.Environment];
           if (scopeValue.Contains(production.Id) && !scopeValue.Contains(preProduction.Id))
           {
               scopeValue.Add(preProduction.Id);
           }
       }
   }
   
   repository.VariableSets.Modify(variableSet);

It should also be fairly straightforward to convert this to Powershell. You could also do this without using Octopus.Client, in which case you could use the following equivalent API endpoints:

[GET] $OctopusUrl/api/projects?name=$projectName
[GET] $OctopusUrl/api/variables/$project.VariableSetId 
[PUT] $OctopusUrl/api/variables/$project.VariableSetId

Hope the above helps,

Regards,
Shaun