6
votes

I want to configure our pipeline to allow one build to be used for multiple environments without having to create separate builds. According to the docs, it seems like it is possible, as it says:

  • You can use this technique to create a default package and deploy it to multiple stages.

I named my stage as my environment (preview), and I created a web.config file for that environment (web.preview.config) file. All my environment configuration files in the same path as Web.Config file.

The logs say transformation was complete:

2018-11-17T00:26:52.0383966Z [command]D:\a_tasks\AzureRmWebAppDeployment_497d490f-eea7-4f2b-ab94-48d9c1acdcb1\3.4.13\ctt\ctt.exe s:D:\a_temp\temp_web_package_06958915987488234\Content\D_C\a\1\s\Microsoft.Xbox.Mvp\Microsoft.Xbox.Mvp.Api\obj\Preview\Package\PackageTmp\bin\Web.config t:D:\a_temp\temp_web_package_06958915987488234\Content\D_C\a\1\s\Microsoft.Xbox.Mvp\Microsoft.Xbox.Mvp.Api\obj\Preview\Package\PackageTmp\bin\Web.Release.config d:D:\a_temp\temp_web_package_06958915987488234\Content\D_C\a\1\s\Microsoft.Xbox.Mvp\Microsoft.Xbox.Mvp.Api\obj\Preview\Package\PackageTmp\bin\Web.config pw i 2018-11-17T00:26:52.4335280Z [command]D:\a_tasks\AzureRmWebAppDeployment_497d490f-eea7-4f2b-ab94-48d9c1acdcb1\3.4.13\ctt\ctt.exe s:D:\a_temp\temp_web_package_06958915987488234\Content\D_C\a\1\s\Microsoft.Xbox.Mvp\Microsoft.Xbox.Mvp.Api\obj\Preview\Package\PackageTmp\bin\Web.config t:D:\a_temp\temp_web_package_06958915987488234\Content\D_C\a\1\s\Microsoft.Xbox.Mvp\Microsoft.Xbox.Mvp.Api\obj\Preview\Package\PackageTmp\bin\Web.Preview.config d:D:\a_temp\temp_web_package_06958915987488234\Content\D_C\a\1\s\Microsoft.Xbox.Mvp\Microsoft.Xbox.Mvp.Api\obj\Preview\Package\PackageTmp\bin\Web.config pw i 2018-11-17T00:26:52.5443873Z XML Transformations applied successfully

I can see that it first transformed to release and then it applied preview as the doc says (release then environment). However, although it says XML Transformations applied successfully, when I check the config variables, they are not changed. The only way I could make the transformation work was to define the buildConfiguration variable when I queue a new build, which blocks me from using the same build for different environments.

When I was researching, I found this from this link:

Web.config is transformed during the build process, if you generate the deployment package from "Build" and then deploy it in "Release", then you cannot transform it before deployment.

But the doc said I can use one default package for multiple stages...Does that still mean I have to create separate build for each environment? Is XML transformation not what I should be looking at for the scenario I wanna solve?

Thank you in advance!

++ Edit:

Release Settings: ReleaseSettings

Release steps (I think? I have a strong feeling that this is what you are looking for...): ReleaseSteps

4
How are you checking your config variables?JleruOHeP
On Azure app service, i can see what current variables are from remote execution console.Sahngah Lee
The scenario you described should work. Basically you include your base web.config and all web.{stage}.config files to your artefacts from build and then apply transformation during the release. Can you check what is inside your artefacts and maybe include screenshots of your release step and settings?JleruOHeP
@JleruOHeP I just looked up our artifacts but I don't see anything transformation related except setParameters.xml which I'm doing nothing about. I'm not sure if I'm supposed to be seeing something else or this is correct. I can include screenshots of our release steps and settings.Thanks!Sahngah Lee
Images looking good, inside your artefacts (your .zip file) there supposed to be at least 3 xmls: Web.config , Web.Release.config , Web.Preview.config. Can you confirm that all of those have the right settings?JleruOHeP

4 Answers

16
votes

1) Make sure you transform works. Test it here.

2) Ensure in your VS project that you are including the transform file, Web.Preview.config, and copying to output dir.

3) Disable the config transform during the build, you just need to add argument /p:TransformWebConfigEnabled=False in MSBuild Arguments section of your Build task. You also need to add /p:AutoParameterizationWebConfigConnectionStrings=False if you want to update the connection string during the release. This will use the Web.Preview.config to "transform" the web.config.

4) Double check that in your release for the IIS Web App Deploy task under File Transforms & Variable Substitution Options you have XML transformation checked.

4
votes

None of the answers I found on the internet worked for me on their own for my build and release pipeline. The web.config I got from the release pipeline was always pointing to the non transformed values.

After a few hours pulling my hair I got it to work though.

Some short info about my setup

I want to be able to deploy on all environments with just one build and one release pipeline.

My setup:

  • One build pipeline that builds all of our standard branches (test, release, master).
  • One release pipeline that has different stages depending on branch that started the release.

enter image description here Our test stage releases the test branch on our test server. Stage/Production comes from the same release branch but have their own transform files.

Solution

I followed some of the guide from Microsoft and set up my web.<environment_name>.config to match the release stage names.

I did not need to remove the <Dependent Upon> rows from my .csproj for each transform. Instead all I did was set the property Build Action of each transform to Content as shown by the image bellow.

Azure DevOps Release Pipeline map

I then added these commands to the build pipeline's Build Solution -> MSBuild Arguments:

  • /p:MarkWebConfigAssistFilesAsExclude=false
  • /p:TransformWebConfigEnabled=false
  • /p:AutoParameterizationWebConfigConnectionStrings=False

The build now does not try to transform the .config on it's own and also does not exclude the transform files from the artifact, allowing the release pipeline to do the transformation instead. Also, keeping the <Dependent On> for the transform files lets us have a "cleaner" look inside our code editors.

3
votes

I just got this working so I could have one build with deployment to multiple environments. This is what I did.

In the code, I set each Web.<Environment>.config property to Build Action = "Content". I also set all mine to Copy to Output Directory = "Copy Always". I also unloaded the project and edit the csproj file, then removed the <DependendUpon>Web.config</DependentUpon> lines. This dumps all your web.configs to the root (no file nesting).

In the build, I set pipeline variable BuildConfiguration = "Release". I don't have a Web.Release.config in my project.

In the release, I named the deployment stage after the environment (in my case, Development, Staging, and Production). In all stages, on the Azure deployment task, I checked the XML transform checkbox.

In Azure, I set the ASPNETCORE_ENVIRONMENT to the naming of the staging environment, in my case, Development, Staging, and Production).

1
votes

I just got this working as well. My issue was actually at the Visual Studio Solution level. I had the MVC project pointed to a different Configuration than the others. So always double check the configs!