2016年7月29日 星期五

[DevOps]透過 xdt:Transform 設定Debug/Release Build時的組態

有些好功能不常用到你就不容易覺得它有價值。

隨著CI流程在每一個專案中被建立,現在在團隊中,只要看到有個專案無法跑CI流程,就會讓人覺得全身不對勁。因此我們開始要求團隊成員,每一個Project至少都能夠在Build Server上能被建置,這個要求幾年前可能很辛苦,但現在一點都不會覺得不合理。如果能夠建置完自動佈署,當然就更加理想了。

前陣子有位同仁碰到一個問題,客戶的專案需要要求用戶強制跑在https的環境中,這問題不難解決,在asp.net中的web.config裡面,把URL rewrite設定一下即可,你在網路上隨處都可以找到這個解決方案,例如:
http://stackoverflow.com/questions/9823010/how-to-force-https-using-a-web-config-file

但這個組態在Web.config設定之後,會導致開發階段Local的IIS Express無法運行,這問題當然可以透過調整Project設定和IIS Express來解決。但其實,這個專案我們也不想在local開發測試的階段走SSL,因為沒必要也不方便。因此,最理想的方式是開發階段的時候走http,而Build到正式(或RC)環境的時候走https。

這時候,Web.config中的release設定就派上用場了。

如果你從來沒打開過Web.Release.config,你可以開啟來瞧瞧,會發現,它預設內容類似底下這樣

 <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--
    In the example below, the "SetAttributes" transform will change the value of
    "connectionString" to use "ReleaseSQLServer" only when the "Match" locator
    finds an attribute "name" that has a value of "MyDB".
   
    <connectionStrings>
      <add name="MyDB"
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
  -->
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
    <!--
      In the example below, the "Replace" transform will replace the entire
      <customErrors> section of your web.config file.
      Note that because there is only one customErrors section under the
      <system.web> node, there is no need to use the "xdt:Locator" attribute.
     
      <customErrors defaultRedirect="GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500" redirect="InternalError.htm"/>
      </customErrors>
    -->
  </system.web>
</configuration>

你可以在標記的後面加上 xdt:Transform="…" 來決定release build階段,相對於Web.config,要增減哪些設定。

注意,Web.Release.config和Web.Debug.config中的設定,是”相對於”Web.config的,因此不管是Debug/Release哪一個build,都是以web.config為主,以Web.Debug/Release.config為輔。

舉例來說,倘若我們希望在一般測試階段,不要有URL rewrite的功能,但佈署到正式機之後,則加上URL rewrite,那Web.config中就不要做任何修改,而在Web.Release.config中加上底下這段:

 <system.webServer xdt:Transform="Insert">
        <rewrite>
            <rules>
                <clear />
                <rule name="Redirect to https" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
 

留意上面的xdt:Transform="Insert",這是指當release build的時候,在Web.config中Insert(插入)上面這段<system.webServer> … </system.webServer>中的內容。

請注意,這是因為我們在Web.config中完全沒有輸入<system.webServer> … </system.webServer>這個區段,因此在Web.Release.config中我們才會用xdt:Transform="Insert"這個指令。

倘若,你在Web.config中已經有輸入<system.webServer> … </system.webServer>這個區段,你則應該在Web.Release.config中改用xdt:Transform="Replace"這個指令。可以參考底下這些微薄的資訊:https://msdn.microsoft.com/zh-tw/library/dd465326(VS.100).aspx

Web.config 轉換語法不是一個新的東西,只是平時用不到可能也不會留意,但由於CI和DevOps的逐漸成熟,現在auto Build幾乎已經是常態,build – deploy 的自動化也已經是上軌道一點的專案必須有的機制,所以這個以前可能被忽略掉的功能,剛好可以拿出來複習一下…