【2021鐵人賽】CI/CD從這裡:第2個Pipeline,建立共用的Build Pipeline

從前面的幾篇文章應該已經知道建立新的Pipeline可以從哪裡開始,所以廢話不多說,第二個Pipeline就直接從Starter範本再度開始。

首先,這個共用的Build Pipeline是純粹用來手動輸入C#的Project名稱來讓Pipeline執行Build csproj的動作,所以先把Yaml中的trigger設定改為none:

trigger:
- none

接下來在Save and run的按鈕旁邊有個Variables按鈕,按下去之後就會出現Variables對話框,如果沒設定過任何變數會像下圖左邊的樣子,點選New variable之後就會出現新增變數的對話框:

第一次設定Pipeline的Variables

這裡我設定一個ProjectName變數,預設值設定為**,並且將下面的Let users override this value when running this pipeline打勾,這麼做是為了讓執行Pipeline的使用者可以在執行Pipeline的時候設定這個變數的值,以達成這個共用的Pipeline設計目的。

設定Pipeline的新變數

設定完成之後按下OK,這時候會看到下圖的Variables對話框,按下Save之後如果重新再從Save and run旁邊的Variables點進來也是同樣的畫面:

設定完Pipeline的變數之後就可以Save了

這時候會發現,怎麼好像Yaml的內容並沒有變化?前面的文章看到.NET Desktop範本裡面不是有variables的設定區段嗎?

沒錯!Pipeline設定變數的方式有好幾種,在Yaml中的variables設定是其中的一種,透過上圖UI的設定是另外一種方式。透過UI設定的方式可以讓使用者在執行Pipeline的時候選擇是否填入他需要的值,並且有些機密的內容可以勾選Keep this value secret(如上圖),像是金鑰值或是密碼之類的,在Yaml中透過變數取得內容,又不會將機密的值曝露在Yaml檔案內容中。

更多設定變數的方式,可以點擊對話框左下的Learn about variables官方的文件有更詳細的說明。

接著同樣將steps底下不需要的script部份刪除,然後從右邊的Task清單加入.NET Core task,在Path to project(s)屬性中填入$(ProjectName)/*.csproj。這裡我們假設C#專案檔會放在同名稱的資料夾內,所以在前面使用$(ProjectName),後面的*.csproj也可以改成$(ProjectName).csproj。

Arguments的部份則是輸入-o $(Build.BinariesDirectory),代表要將Build產生的檔案放到$(Build.BinariesDirectory)所代表的位置。

Task的Yaml內容如下:

- task: DotNetCoreCLI@2
  inputs:
    command: 'build'
    projects: '$(ProjectName)/*.csproj'
    arguments: '-o $(Build.BinariesDirectory)'

接著為了節省篇幅,可以參考前一篇文章的內容,將壓縮為zip檔案的ArchiveFiles task和上傳Artifact的PublishPipelineArtifact task陸續加入Yaml中。其中壓縮zip的task內容在zip檔名的部份加入了$(ProjectName)這個變數,讓檔案更具有識別性,詳細內容可以參考下面的Yaml內容:

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- none

pool:
  vmImage: ubuntu-latest

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'build'
    projects: '$(ProjectName)/*.csproj'
    arguments: '-o $(Build.BinariesDirectory)'
- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: '$(Build.BinariesDirectory)'
    includeRootFolder: false
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/$(ProjectName)-$(Build.BuildId).zip'
    replaceExistingArchive: true
- task: PublishPipelineArtifact@1
  inputs:
    targetPath: '$(Build.ArtifactStagingDirectory)'
    artifact: 'BuildOutputFiles'
    publishLocation: 'pipeline'

最後別忘了修改一下Pipeline的Yaml檔名,此例我將檔名設為CommonBuildPipeline.yml,按下Save(不Run)之後,在Pipeline清單中將剛才建立的Pipeline改名為BuildSpecifiedProject。

上面按Save而不是Save and run的原因是Save and run會直接使用變數的預設值執行Pipeline,雖然在前面我們設定變數的預設值是**,搭配Task中設定的是$(ProjectName)/*.csproj,使用預設值的情況下就會變成**/*.csproj,其實也就是將Repo中的所有csproj檔案都拿來Build的意思。

這裡再複習一下Git Repo中先前放入的C#專案如下:

方案中的3個專案

進入剛才建立的BuildSpecifiedProject Pipeline,按下右上角的Run pipeline,在Variables選項中選擇ProjectName變數將Value更新為ModuleA之後按下對話框下面的Update,回到上一層之後按下左上角的箭頭回到Run pipeline對話框之後就可以按下右下角的Run按鈕執行Pipeline了。

執行Pipeline的時候設定Pipeline變數值

Pipeline執行成功之後,進入成品庫(Artifacts)中就可以看到ModuleA的zip檔案,檔案內容就是ModuleA相關的dll等檔案。同樣的方式可以再試試將變數值換成ConsoleApp或ModuleBase。

透過這樣的設計就可以讓使用者手動執行這個Pipeline並指定要編譯哪一個專案,在切分很多專案或是Module開發的情況,又需要在後續的Release中設計多個不同的成品來源時,可以不需要設計多個不同的Pipeline。

發佈留言

%d 位部落客按了讚: