【2021鐵人賽】Pipeline與Artifacts應用:Build nuget package上傳到Private nuget

前一篇內容設定了C#專案裡的Generate NuGet package on build,讓專案編譯的時候自動產生nupkg檔案,接著手動使用cli工具將nupkg檔案push到Azure DevOps Artifacts,這篇就來看看如何將這些動作設計在Pipeline裡面吧!

這邊直接借用前面文章「CI/CD從這裡:第2個Pipeline,建立共用的Build Pipeline」裡的yaml內容開始,同樣建立新的Pipeline,選擇Starter範本,然後用前面文章的Yaml內容複製過來修改,前面文章的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'

在Yaml內容最下面空白的地方,同樣選擇.NET Core task,Command的選項則改為選擇nuget push,第二個Path to NuGet package(s) to publish的設定預設是從$(Build.ArtifactStagingDirectory)資料夾內去尋找nupkg檔案(如下圖中的預設值),下面的Target feed location如果是有push到其它地方選擇第二個,但是我們是要push到自己的Artifact feed,所以可以直接從下面的選單下拉選擇即可:

不過因為我們第一個task已經設定build的時候輸出的位置是在$(Build.BinariesDirectory),所以nupkg檔案也會在那裡,所以設定的內容要改一下,改成$(Build.BinariesDirectory)/*.nupkg,最後完成的全部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
  displayName: Build C# Project
  inputs:
    command: 'build'
    projects: '$(ProjectName)/*.csproj'
    arguments: '-o $(Build.BinariesDirectory)'
- task: ArchiveFiles@2
  displayName: Zip output files
  inputs:
    rootFolderOrFile: '$(Build.BinariesDirectory)'
    includeRootFolder: false
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/$(ProjectName)-$(Build.BuildId).zip'
    replaceExistingArchive: true
- task: PublishPipelineArtifact@1
  displayName: Publish files to pipeline artifacts
  inputs:
    targetPath: '$(Build.ArtifactStagingDirectory)'
    artifact: 'BuildOutputFiles'
    publishLocation: 'pipeline'
- task: DotNetCoreCLI@2
  displayName: Push Nuget package
  inputs:
    command: 'push'
    packagesToPush: '$(Build.BinariesDirectory)/*.nupkg'
    nuGetFeedType: 'internal'
    publishVstsFeed: '15523482-96ea-4d9f-83bf-a57fc10e79ce'

因為Task變多了,所以我也在每個Task加上了displayName屬性,這個在前面的文章有提過,如果忘了可以往前面翻閱先前的文章內容喔!

另外,新建立的Pipeline也別忘了設定Variables,Yaml中的ProjectName需要設定,也是前面的文章有提過,其它的像是更改Pipeline名稱與Pipeline yaml檔名的這些動作就不再耗費篇幅重述了唷!

接著在執行Pipeline的時候會碰到下面兩個問題,其中一個是Organization層級的Artifacts feed權限設定的問題,從Push的Task log中會看到下圖紅框中的訊息,代號403:

這時候就需要去Artifact feed的Permissions設定中點選Allow project-scoped builds,將Project的Build Service加入(忘了從哪進入的請參考前面的文章):

加入之後再重新執行一次Pipeline,這時候就會碰到下面的這個問題,同樣是Push的Task log中所列出紅框中代號409的錯誤訊息:

這個問題是因為Artifact feed中對於ModuleBase這個Package已經存在了相同的版本(此例為1.0.1),相同的版本號並不會使用最新的去覆蓋先前的版本,因為這樣子沒有意義,雖然Package內容可能有更新了,但是相同的版本號對於使用者來說是沒有更新的。

可是…難不成每一次要執行Pipeline之前,都需要先將C#專案中的版本號手動更新之後Commit到Git Repo裡面再來執行這個Pipeline讓它去Push nuget package嗎?都要手動改版本號了,那我順便利用cli再把新的package push上去不就得了?

沒錯,要弄這個Pipeline就是不要這麼麻煩,所以這篇文章的錯誤只是為了引導後面的文章內容,接下來的文章將會說明如何在Pipeline中修改版本號。

發佈留言

%d 位部落客按了讚: