VSTS 雲到地的 CI CD (02) - 佈署依據環境替換 Web.config

佈署不同環境時, Web.config 的值也是會不同

根據我目前最直覺的做法就是在組態管理員下手

  • Web.Japan.config
  • Web.Taiwan.config

利用不同組態去 Publish 就可以切換成不同的組態

但是目前情境是希望不想利用這種方式去切換

希望能透過 VSTS 的 Release Management 環境切換把不同的組態值設定進去

在 VSTS 進入 Release 階段前, 先了解 Build 階段到底要做到哪些事情

預設的 Visual Studio Template Build Definition 可以看到最後是 Publish Artifact

Artifact ? 姑且稱作它為「工件」

回想一下我們手動佈署的步驟: Build -> web deploy package -> deploy

而 Artifact 就是那包要被佈署的 package

為此我們重新打造一個 Build Definition 來實作此篇主題

切換 Web.config 除了新增多個組態檔

還有另一種方式就是利用 Web Deploy Package 出來的 SetParameters.xml

去替換 Web.config Mapping 到的 key-value

Add parameters.xml & Add Replace-SetParameters.ps1

在專案根目錄底下新增 parameters.xml

<?xml version="1.0" encoding="utf-8" ?>
<parameters>
  <parameter name="DemoKey" description="The DemoKey setting" defaultvalue="__DemoKey__" tags="">
    <parameterentry kind="XmlFile" scope="\\web.config$" match="/configuration/appSettings/add[@key='DemoKey']/@value">
    </parameterentry>
  </parameter>
</parameters>

使用 Web Deploy Package 產出的 SetParameters.xml 會有對應的設定

新增一個 Power Shell Script 在專案外層的資料夾內 (Release 階段使用)

param(
    [string]$setParamsFilePath
)
Write-Verbose -Verbose "Entering script Replace-SetParameters.ps1"
Write-Verbose -Verbose ("Path to SetParametersFile: {0}" -f $setParamsFilePath)
 
# get the environment variables
$vars = gci -path env:*
 
# read in the setParameters file
$contents = gc -Path $setParamsFilePath
 
# perform a regex replacement
$newContents = "";
$contents | % {
    $line = $_
    if ($_ -match "__(\w+)__") {
        $setting = gci -path env:* | ? { $_.Name -eq $Matches[1]  }
        if ($setting) {
            Write-Verbose -Verbose ("Replacing key {0} with value from environment" -f $setting.Name)
            $line = $_ -replace "__(\w+)__", $setting.Value
        }
    }
    $newContents += $line + [Environment]::NewLine
}
 
Write-Verbose -Verbose "Overwriting SetParameters file with new values"
sc $setParamsFilePath -Value $newContents
 
Write-Verbose -Verbose "Exiting script Replace-SetParameters.ps1"

這 Script 語法不懂不打緊, 挑幾個關鍵的事情看即可

可以看到語法中是把 __(\w+)__ 替換成環境變量的 value

要注意的是環境變量永遠要保持 unique

再來就是站台名稱我也想要使用環境變量來替代

所以把 Package 發行檔的 Site Name 設置 __SiteName__

讓打包出來的 SetParameters.xml 有站台名稱替換的設定

創建 Artifact By Build

Add New Build Definition 選擇 Visual Studio template

調整 Build Soloution 的 MSBuild Arguments

/p:DeployOnBuild=true /p:PublishProfile=Package /p:PackageLocation="$(build.StagingDirectory)"

然後在 Build 底下增加兩條 Task

Copy Publish Artifact: drop - 將 package 出來的所有 files copy 到 Artifact/drop 資料夾

Publish Artifact: scripts - 把我們寫好 power shell 從 scripts 資料夾整份 copy 到 Artifact/scripts 資料夾

創建 Release Definition

創一個 Empty 的 Release Definition, 選擇剛剛我們做好的 Build Artifact

可以先勾選 

這裡我們只需要加入 2 個 Task

PowerShell & Batch Script

PowerShell 設定 (執行替換內的SetParameters.xml值)

Script Path: $(System.DefaultWorkingDirectory)/XXXXX/scripts/Replace-SetParameters.ps1

Arguments: -setParamsFilePath $(System.DefaultWorkingDirectory)\XXXXXX\drop\XXXXXX.SetParameters.xml

Batch Script 設定

Path: $(System.DefaultWorkingDirectory)/XXXXXX/drop/XXXXXX.deploy.cmd

Arguments: /Y /M:http://xxxxxx/MSDEPLOYAGENTSERVICE /U:*** /P:***

然後加入一個環境去設置我們要設置的環境變量給 PowerShell 替換的值

然後把要佈署站台名稱跟你 Web.config 想替換的 value 設定好即可

大功告成, 如果順利的話就可以在遠端的 IIS 站台檢查 Web.config 是否如期的更新成我們設定的值了

相關連結

WebDeploy, Configs and Web Release Management

WebDeploy and Release Management – The Proper Way

How to override ASP.NET deployment parameters when publishing

VSTS Release - Define custom variable in web.config and set at release time

WEBDEPLOY PARAMETERIZATION TIP: DONT PUBLISH YOUR PARAMETERIZATION FILES

Web Deploy XML File Parameterization