A bonus to all this. It is possible to transform app.config (as well as any other file) when building. Such functionality is by default in WCF service projects for web.config , but it can also be added to other types of projects.
The scheme is as follows: there is some default empty app.config , next to it are additional files called app.Debug.config , app.Release.config , app.Test.config and so on, which contain instructions for transforming the original app.config . Assuming that only certain build configurations are used in CI and CD (for example, only Release), then you can keep the necessary set of settings for working with the app.Release.config in app.Release.config . Developers can freely edit app.config locally and work with the Debug configuration (if developers need to work with Release, you can add a new CIRelease configuration that will only be used on the buildserver).
To use this approach is not in the WCF project, you need to make several frauds.
Create a ConfigurationTransform.targets file with the following content:
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" /> <PropertyGroup> <AllowedReferenceRelatedFileExtensions> $(AllowedReferenceRelatedFileExtensions); .dll.config </AllowedReferenceRelatedFileExtensions> </PropertyGroup> <PropertyGroup> <ResolveReferencesDependsOn> TransformConfig; $(ResolveReferencesDependsOn) </ResolveReferencesDependsOn> </PropertyGroup> <Target Name="TransformConfig" BeforeTargets="_CopyAppConfigFile" Condition="Exists('App.$(Configuration).config')"> <!--Создаём трансофрмированный app config в промежуточной директории.--> <TransformXml Source="App.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="App.$(Configuration).config" /> <!--Сообщаем, что для сборки нужно использовать только что сгенерированный файл.--> <ItemGroup> <AppConfigWithTargetPath Remove="App.config" /> <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config"> <TargetPath>$(TargetFileName).config</TargetPath> </AppConfigWithTargetPath> </ItemGroup> </Target> </Project>
We put the file in the solution folder ( .sln level) and connect it immediately after Microsoft.CSharp.targets .
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)\ConfigurationTransform.targets" />
In principle, you can connect this task directly to .csproj without creating an additional file, but with an add. The file automatically solves the problem with the presence of several projects for which you need to transform the app.config .
Example. Original app.config :
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <connectionStrings> <add name="Test" connectionString="" /> </connectionStrings> </configuration>
Transformation file app.Release.config :
<?xml version="1.0"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <connectionStrings> <add name="Test" connectionString="ProductionConnectionString" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> </connectionStrings> </configuration>
The transformation file uses the SetAttributes operation, which sets the attributes for the node, which is identified by the name attribute ( xdt:Locator="Match(name)" ). Other examples of transformations are here .
Voila, when building in the ConfigName configuration, if there is an app.ConfigName.config file next to app.config , it will be used for transformation and the build will be performed using the intermediate transformed file.
An example of a task from here .
Another bonus is a small life hack. To prevent the transformation files in Solution Explorer from taking up much space, they can be shown as children of the main app.config : 
To do this, in .csproj you need to correct the registration of the transformation files by adding the DependentUpon tag:
<ItemGroup> <None Include="App.config" /> <None Include="App.Release.config"> <DependentUpon>App.config</DependentUpon> </None> </ItemGroup>