Managing Configuration and App Settings for Multiple Environments in Your CD Pipeline

Your continuous delivery pipeline typically consists of multiple environments. You may want to deploy changes first to a test or staging environment before deploying to a production environment. Furthermore, your production environment may itself comprise of multiple scale units, each of which you may deploy in parallel or one after the other for a gradual roll out.

As a best practice, you would want to deploy the same bits and follow the same procedure to deploy those bits in every environment. The only thing that should change from one environment to the next is the configuration you want to apply. For example, the database connection strings may point to different databases for different environments, or app settings may change between environments. Configuration and app settings changes may range from simple to complex but all generally follow the same strategy. The deployment tool stores the configuration values for each environment and performs configuration transforms at deployment time . If you have sensitive data in app settings such as passwords, they should be stored in the deployment tool rather than in plaintext in settings files.

Visual Studio Team Services allows you to define pipelines or release definitions with configuration management and transformations for each environment.

Why manage configuration changes through Visual Studio Team Services?

Here are the top five reasons to manage configuration and app settings variations per environment in a deployment tool like Visual Studio Team Services.

  1. More maintainable

Team Services allows you to manage variables and secrets at multiple levels. For variables that are needed in many release definitions, you can store variables in a project. You can also define configuration variables that are scoped to a specific release definition or to a specific environment in a release definition. Team Services provides an easy interface to manage these variables at each of these scopes.

  1. Fewer locations to update

By storing your configuration and app settings in a deployment tool, if settings change in a given time, you only need to update the settings in the deployment tool rather than in every possible file that the setting is hard-coded in. Furthermore, by storing them at the right scope, you do not have to update all the release definitions or environments in which they are used.

  1. Fewer mistakes

When storing the appropriate settings for each environment in the environment itself in the deployment tool, you won’t accidentally point to the development connection string when in production. The values for settings are siloed out per environment so it would be hard to actively mix up if using a deployment tool.

  1. More secure

When you have connection strings, passwords, or any other settings stored in plaintext in a settings file (such as a web.config file), anyone who has access to the code can potentially access a database or machine. Team Services provides a rich permissions model for who can manage and use secrets at each scope.

  1. More reliable

By automating the process of transforming configurations through a deployment tool, you’ll be able to count on the transforms always happening during a deployment and setting the appropriate values.

The concept of managing configuration and app settings for multiple environments in your continuous deployment seems straightforward enough, but how does it look in practice? It’s likely simpler than you’d expect.

What does configuration and app settings transforms look like in Visual Studio Team Services?

Let us take an example of deploying an application to an Azure website. We will look at two approaches for changing the configuration of the website in each environment – transform the web.config file just before deploying the website, and apply the settings directly in Azure.

The simplest approach is to transform the configuration and app settings in the web package’s web.config file just before deploying the package to each environment. Using the new version of the “Azure App Service Deploy” task in Visual Studio Team Services makes it easy to implement this approach as long as you define the values of the settings that you want to replace in each environment! Here are the steps for doing this.

  • Make sure that you have set up the build process for your app correctly; then in the Release Definition for your app, add the “Azure App Service Deploy” task into each environment. In the task, select the 3.* version from the dropdown for the task, then in the File Transforms and Variable Substitution Options group, click on the checkbox next to “XML variable substitution” to enable variable replacement in any config file.
    config-transforms-1
  • Define the key/value pairs in each environment, making sure to have the key/name match in the config file.config-transforms-2config-transforms-3
  • When the task runs in the release, it will match the name of the variable defined in Visual Studio Team Services and replace the value in any config files in the app package before deploying to Azure. In the above example, it replaces the value of appSettings key “Key1” from the web.config with the value of variable “Key1” defined in the environment.
  • After the replacement, the task re-packages the website and pushes it to Azure.
  • When the deployment of the release proceeds to the next environment in the pipeline, the same process is repeated to replace the value of “Key1” in web.config with the corresponding value defined on that environment.

In some cases, you may not want sensitive settings to be stored into your web.config file. Instead, you want those sensitive settings to be directly applied to an Azure website. In this case, your flow looks as follows:

  • Define the key/value pairs in each environment of your release definition.
  • Include a script in each environment to apply the settings directly to your Azure website. You can write such a script using the “Set-AzureRmWebApp” commandlet. Infact, the Visual Studio Marketplace has an extension that just does this for you. When you install this extension in your account, you will notice an additional task in your account called “Apply variables to Azure webapp”, which takes the variables defined in your environment as per a convention, and then applies them in the Azure web app directly.

Azure Web App Configuration Task

For more information about setting up continuous integration and continuous deployment for your ASP.NET, ASP.NET core, Node, or other apps, see these documents:

CI for ASP.NET apps
CI for ASP.NET core apps
CI/CD for Node apps
Deploy your web package to Azure websites from VSTS

The IIS web deployment tasks in Team Services support similar transformations when you want to deploy a web package to on-premises or Azure virtual machines. For more information about deploying websites to IIS servers, see:

Deploy your web package to IIS servers

If you are deploying your application to a different platform or using a different technology, you have the power of generic task execution to run any scripts as part of your deployment. For instance, you can author a script to transform your custom configuration file using PowerShell, batch, or shell scripts. Alternatively, there are many extensions available in Visual Studio Marketplace to help you with deploying your applications.

Organizing the process for configuration differences for each environment may seem challenging, but is simple to implement using Visual Studio Team Services and you can remove much of the pain of managing settings transforms in configuration files.

 

Many thanks to the contributors & reviewers for this post:  Sachi Williamson, Abel Wang, Martin Woodward, and Ed Blankenship

5