2018年1月26日 星期五

【CI/CD】4. 在佈署階段置換參數值,以Web.Config為例


接續前篇 : 【CI/CD】3. 透過VSTS 切換Azure AppService Slot

如果你的佈署狀況如下
原諒我只繪畫醜圖....

有一次更版進到到Master Branch,而CI設定Trigger是Master更動時自動建置,CD接收到CI建置完成後執行佈署機器,而每台機器的Web.Config值都有差異,這時候該可以這樣做?


XML variable substitution

Azure App Service Deploy有提供XML variable substitutuin可以選擇


依據註解中說明就是,當這個選項勾選時,他會自動去找專案中的所有.Config檔案,檔案中的appSettings,application Settings , connectionString區塊,
如果有Key或Name與設定的變數相同時自動置換,且是發生在Config transforms之後。


什麼意思呢? 直接看範例,如果我們的Web.Config裡面長這樣

那他就會在去比對appSettings、connectionString區塊,裡面的Name或是Key有對應到變數設定的話,Value值會自動被替換,而變數設定又在哪邊呢?



以上面兩張圖來說,那他在WebDeploy到Azure App Service之前就會將我的StaticDomains、DomainValue換掉,因為我們在變數檔案裡面有設定。


這樣我們就能透過建置多個環境的方式,在每個環境中設定好對應的變數值,只要執行一次CI流程,觸發多個CD流程,達到多台同時佈署的目的




如果參數不在appSettings,application Settings , connectionString區塊之中呢?

這邊特別注意,剛剛那種置換的值方法僅適用於上述區塊之中,換句話說,如果我們有環境設定變數,但他又不在這幾個區塊之中,該如何做?

Parameter.xml

還好微軟有提供另一種方式能處理這個問題,就是透過Parameters.xml


建立parameters.xml


<parameters>
  <parameter name="ExceptionlessAPIKey" defaultValue="#{ExceptionlessAPIKey}#" >
    <parameterEntry
      kind="XmlFile"
      scope="Web\.config"
      match="//exceptionless/@apiKey" />
  </parameter>
  <parameter name="SessionConnectionString" defaultValue="#{SessionConnectionString}#" >
    <parameterEntry
      kind="XmlFile"
      scope="Web\.config"
      match="//configuration/system.web/sessionState/@sqlConnectionString" />
  </parameter>
</parameters>


Name : 變數名稱

Scope : 受影響的檔案為和,你可以設定整個專案底下全部的.Config也行

Match : 在這些檔案底下如何尋找要被替換的值
Example 1 :  Web.Config底下從根結點開始找起,找到一個叫做exceptionLess的Tag,然後把apiKey這個屬性換成我設定的值

Example 2 :  Web.Config底下從根結點開始找起,找到configuration底下的system.web底下的sessionState Tag,然後把sqlConnectionString這個屬性換成我設定的值

DefaultValue : 如果在佈署時沒有設定參數值時,預設給的Value



接著在VisualStudio按發行後應該會看到檔案長出SetParameters.xml


打開來會看到



到這邊我們已經成功將Web.Config的指定位置挖成變數值,等等在CD階段,我們就是要想辦法把SetParameters.xml的Value值換掉



回到CD設定介面

告訴Azure App Service Deploy Task,你有SetParameters.xml




安裝Replace Token Task

為了置換掉SetParameters.xml裡面的值,必須幫我們VSTS安裝套件

安裝連結 :  Replace Token MarketPlace 



Azure App Service Deploy之前加上 Replace Token Task



設定


Root Directory : 要替換的目標檔案Root資料夾位置

Target files : 告訴它我們要找的檔案是誰,以這邊來說就是SetParameters.xml

Token prefix、Token suffix : 比對什麼是它要幫我們置換的,而這邊就是#{xxxx}#包起來的就是參數


這樣設定完之後,它就會在WebDeploy之前執行Replace Token Task,而這個Task會去找到SetParameters.xml,然後找到#{xxx}#符號的,然後用我們之前設定在Variables的參數置換掉






參考文章 :


2018年1月25日 星期四

【CI/CD】3. 透過VSTS 切換Azure AppService Slot


接續前篇 : 【CI/CD】2. 透過VSTS自動佈署程式到Azure AppService

一般為了服務的順暢,一般都會在正式機的Azure App Service開啟Slot服務
參考 : 在 Azure App Service 中設定預備環境

好讓服務更新時,能無痛更新且不會中斷Session。

而上一篇有提到如何更新Azure App Service,但如果在有開啟Slot的情形下,設定要做一些變更。

首先先將設定從佈署正式機改成佈署到Slot


勾選Deploy to Slot後,會需要選擇Resource groupSlot,分別選擇好後存檔。


新增一組切換Slot Enviroment


因為我們是希望佈署到Slot後,再決定要不要跟正式機進行交換,所以是按第一組環境的Add而不是Enviroments Add,兩個差異如下

Enviroments Add : 同時觸發

DeployToStage Add : 依序


設定Swap Slot

新增Azure App Service Manage




跟前面的設定基本上都一樣,只要是Action的地方要選擇Swap Slots


加上啟動切換Slot的條件

正式機加上上述設定後帶來了一些好處

1.上線時推程式會先進到Slot,先連到Slot測試確定沒問題
2.讓正式機跟Slot交換,線上服務感受不到中斷,但程式已經更新了

而我們為了安全起見,在切換Slot前會再加一到人工審核,當核准時才會進行切換




這樣設定後,切換Slot就會需要審核


第一關審核是佈署到Slot

第二關審核是將正式機跟Slot切換





下一篇來寫如何在CD階段置換參數值

【CI/CD】2. 透過VSTS自動佈署程式到Azure AppService


接續前篇 : 【CI/CD】1. 如何透過VSTS來達成CI的目標

這邊的目標是當CI完成時,自動將程式佈署到Azure AppService,也就是所謂的CD部分

持續部署(Continuous Deployment)
大部分的持續整合系統允許在建置完成後自動執行程式碼。因此能夠寫一段程式碼來布署應用程式至任何人都可以觀察的測試伺服器。在持續性整合未來的思考發展成像持續性布署邁進。
持續性布署將要求直接將軟體布署至測試環境中,這通常需要額外的自動化機制來防止程式缺陷。

希望
1.CI部分執行完畢後,將程式自動佈署到機器
2.依據不同的CI Task,決定佈署到哪些機器 (測試機 or 多台正式機...等)
3.人員核准 (正式機通常需要一定權限核准才能執行佈署)




1.先進到VSTS的Release > Create release Definitions




2.選擇Empty Process




3.Artifacts選擇佈署要用哪一組CI建置的成品




4.設定Trigger條件

我們希望上一步驟選擇的CI Task建置完成後,自動觸發這個的CD流程,所以要加上Trigger條件





5.新增Enviroment Task > Azure App Service Deploy




6.設定相關參數

Azure subscription : 選擇你訂閱的Azure服務,基本如果是同一個帳號,下拉選單就可以看到

Package or folder : 因為我們是採用WebDeploy的方式佈署,所以要輸入Pakage的路徑,紅色區塊請填你CI Task所設定的名稱,CI建置會放置在同名的資料夾底下,之後就是Drop底下建置出來的.zip檔


人員核准

依照上述步驟做完,基本上佈署流程大致上已經完成,但通常會有一些狀況是希望做佈署動作前能夠先透過人來審核,例如正式機佈署。 我們一定不希望隨便人簽入程式後,正式機的CD流程就自動觸發佈署去了。

設定審核人員

Any Order : 上面所選的人員每一個都要核准才會觸發

In sequence : 上面所選的人員每一個都要依序核准才會觸發

Any One Order  : 上面所選的人員任何一人核准即可


如果有卡核准的話,Release不會自動執行,而是看到這個畫面
點兩下進去後可以核准





選擇特定版本佈署







小結

以上這邊,之後只要有人簽入程式,CI流程有設定Trigger的話就會自動觸發,CI流程沒問題,CD流程就會接著做,再依據有無卡審核做後續行為。

每次的執行狀況也都可以清楚看到狀況



下一篇來說如何透過VSTS來執行切換Slot,感覺還有好幾篇可以寫...

【CI/CD】1. 如何透過VSTS來達成CI的目標


以下是Wiki對於CI的解釋

持續整合(英語:Continuous integration,縮寫CI)是一種軟體工程流程,是將所有軟體工程師對於軟體的工作副本持續整合到共用主線(mainline)的一種舉措。
該名稱最早由[1]葛來迪·布區(Grady Booch)在他的布區方法[2]中提出,不過他並沒有提到要每天整合數次。之後該舉措成為極限編程(extreme programming)的一部份時,其中建議每天應整合超過一次,甚至達到數十次。
[3]在測試驅動開發(TDD)的作法中,通常還會搭配自動單元測試。持續整合的提出主要是為解決軟體進行系統整合時面臨的各項問題,極限編程稱這些問題為整合地獄(integration hell)。

而自己對CI的見解是,透過軟體版本控管機制,持續將每個分支每次修改進行整合,並且透過自動化的測試、佈署、執行報告來控管軟體品質。

參考 : [軟體工程]持續整合 (Continuous integration, CI) 簡介 - 91


而這篇是要寫如何透過VSTS來達成此目標,跟整個設定的過程,先來整理要達成的目標項目。

希望
1.版控更新時,自動建置
2.自動執行單元測試
3.將建置好的檔案放到佈署資料夾(之後讓CD接手,做自動化佈署到正式機、測試機..等)
4.回報上述執行結果


版控更新時,自動建置

1.到VSTS網站頁面,選擇Build and Release  >  +New







2.選擇Empty process




Process Agent queue設定




3.加入Nuget restore Task因為我們專案都有用Nuget,所以需要在建置之前先還原Nuget,設定如下



這邊Feed to use 我選擇Feeds in my Nuget.config,原因是公司專案有用自己開發的Nuget套件,而那些Nuget放的位置就需要自訂的Config讓建置機器知道,否則抓不到那些套件,待會建置就會錯誤,如果專案沒有用內部Nuget Server的套件,就選第一個即可。

通常如果我們有用私人的Nuget套件,一定會在VS設定套件來源,而這個設定檔就會放在底下這個位置
%appdata%\NuGet\NuGet.Config
把檔案放進版控中,就可以讓VSTS選的到了



4.加入Build Solution Task


*這邊MSBuild Arguments裡面的PublishProfile=CICD,意思是說我們要用的發行檔名稱,而名稱就做CICD,所以等等我們會回VisualStudio建立一個名叫CICD的發行檔

*Configuration,是說我要用Debug的組態檔來建置,如果你不知道組態檔是什麼,請看
參考 : 發佈網站時依據組態設定的不同而轉換 Web.Config   -  MRKT




5.建立CICD發行檔





你可以先用VS發行看看,應該會在專案的Root資料夾底下長出一個Publish的資料夾,底下內容如下
之後WebDeply就靠這些檔案了。 回到VSTS繼續設定



6.加入Visual Studio Test Task


紅框處是告訴這個Task,如何找到你的單元測試Dll來執行,如果你建立單元測試專案都是用預設的方式,那單元測試的專案名稱應該都會是 xxxTest,所以建置出來的Dll也會是xxxTest.dll,符合紅框預設尋找的條件,所以不用調整


7.加入Copy Files Task

目的是如果前面幾個Task都通過執行到這邊,表示建置沒有問題,且單元測試全部通過,所發行出來的檔案,加下來要把這些檔案複製出來,準備移到成品資料夾

黑框遮掉的部分就跟之前一樣是專案名稱,我的專案名稱是XXX.Application,所以那個區段請自行置換。

另外還記得Publish這個資料夾嗎?這就是我們剛剛在Visual Studio設定在CICD發行檔的建置發行檔存放的位置,套上預設VSTS建置專案的資料夾變數位置,就變成這行的值了

參考 : VSTS Build variables 

8.將成品資料夾內容丟到Drop資料夾





到這邊CI的任務大致完成,已經能將專案自動建置、單元測試、將成品打包準備佈署到Server,接下來如何將這成品佈署到Server就是CD的議題了,留待之後在說。


這邊還有最重要的一點,既然是持續整合,那這些任務如何自動化的持續整合,如果每次版控有異動都還要人來操作這些任務,那就失去了持續整合的意義。

將CI任務加上Trigger條件

這邊設定意思是說,當這個專案的Develop分支有新的Commit進來時,剛剛設定的那些任務就會被自動化的執行。

而每次執行的結果如下

點擊每一次進去可以看到執行的狀況,或是以及錯誤的Log




也可以手動排Queue,讓他立即依據現在最新版本或是特定版本去執行





Commit可以填入Git的Commit ID,如果不填就會用最新版執行建置。



下一篇預計接著寫CD的部分,如何接著將以上建置完的檔案分別佈署到Azure AppService以及VM機器上。



參考文章

Create your first build and release | Microsoft Docs

發佈網站時依據組態設定的不同而轉換 Web.Config   -  MRKT

[軟體工程]持續整合 (Continuous integration, CI) 簡介 - 91