
最近在重新檢視 CI/CD (Continuous Integration / Continuous Delivery) 流程,順手把 Build Config 的方式都改了。
目前有部分 Config 還是 XML 格式,其它大多以換成 JSON 格式,Config 我們都是透過 MSBuild 來置換個環境的變數。
本篇將介紹透過 MSBuild 替換 XML 的內容。
檔案結構
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
   | Input/   ProjectA/     Log4net.DEV.config     Log4net.QAT.config     Log4net.Release.config     Web.DEV.config     Web.QAT.config     Web.Release.config   ProjectB/     Log4net.DEV.config     Log4net.QAT.config     Log4net.Release.config     Web.DEV.config     Web.QAT.config     Web.Release.config   ...   ProjectN/     Log4net.DEV.config     Log4net.QAT.config     Log4net.Release.config     Web.DEV.config     Web.QAT.config     Web.Release.config Source/   ProjectA/     Log4net.config     Web.config   ProjectB/     Log4net.config     Web.config   ...   ProjectN/     Log4net.Release.config     Web.Release.config Configuration.xml
   | 
我們要把 *.Release.config 的特定區塊,替換掉 *.config。
例如:
Input/Web.Release.config
1 2 3 4 5 6
   | <?xml version="1.0" encoding="utf-8"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">   <system.web>     <compilation xdt:Transform="RemoveAttributes(debug)" />   </system.web> </configuration>
   | 
此範例會找到 Web.config 中的 compilation 標籤,移除 debug 屬性。
建立 MSBuild 專案
MSBuild 專案是 XML 格式,所以建個 XML 檔案 Configuration.xml,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>     <SourcePath>Source\</SourcePath>     <InputPath>Input\</InputPath>     <OutputPath>Output\</OutputPath>   </PropertyGroup>      <ItemGroup>     <TransformConfigs Include="$(InputPath)**\*.$(Configuration).config" />   </ItemGroup>      <Target Name="Clean">     <RemoveDir Directories="$(OutputPath)" Condition="Exists('$(OutputPath)')" />   </Target>      <Target Name="Rebuild" DependsOnTargets="Clean;Build" />      <Target Name="TransformConfigs"     Inputs="@(TransformConfigs)"     Outputs="%(Identity).AlwaysRun">     <PropertyGroup>       <TransformFile>@(TransformConfigs->'%(RecursiveDir)')@(TransformConfigs->'%(Filename).config'->ToLower())</TransformFile>       <SourceFile>$(TransformFile.Replace('.$(Configuration.ToLower())', ''))</SourceFile>     </PropertyGroup>     <TransformXml Condition="Exists('$(SourcePath)$(SourceFile)')"       Source="$(SourcePath)$(SourceFile)"       Transform="$(InputPath)$(TransformFile)"       Destination="$(OutputPath)$(SourceFile)" />   </Target>
    <Target Name="Build">     <MakeDir Directories="$(OutputPath)"/>       <CallTarget Targets="TransformConfigs" />   </Target>      <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" />    </Project>
   | 
Import Project 中的路徑 v15.0 是 Visual Studio 2017 MSBuild 的路徑。
用不同版本的 MSBuild 記得更換。
執行結果
執行指令
1
   | msbuild Configuration.xml /p:Configuration=Release /t:rebuild
   | 

要在 console 使用 msbuild,要先在環境變數中加入 msbuild 的 Path。
Visual Studio 2017 預設路徑為 C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin
透過不同的 Configuration 參數,就可以輕易的把各環境 Configuration 產出,很方便吧~
參考
MSBuild 參考 Web.config Transformation - Transform on build