顯示具有 Azure Devops Server 2019 標籤的文章。 顯示所有文章
顯示具有 Azure Devops Server 2019 標籤的文章。 顯示所有文章

2019年7月10日 星期三

在Azure Pipeline 裡使用 docker build 執行 asp.net core 的 unit test 後,把測試結果跟code coverage 上傳到組建裡

在Azure Pipeline 裡使用 docker build 執行 asp.net core 的 unit test 後,把測試結果跟code coverage 上傳到組建裡

在Pipeline建置時,如果要看到測試結果跟code coverage , 需要在Pipeline中建置,才能在azure devops server 的介面中看到測試結果跟程式碼含蓋範圍。像這樣
enter image description here

但是如果要把unit test 放在 docker 裡,在 multi stage builds 的過程之中執行unit test,在預設的狀況下,測試結果會在某一個build stage中,就不能使用pipeline的task來上傳測試結果。

解決方法

在docker 建置過程中做unit test , 另外產生測試結果。等到docker build 結束之後,用powershell把測試結果copy出來,然後再分別用 pipeline 的task 上傳測試結果及程式碼含蓋範圍。 就像下圖的步驟 3,4,5一樣。

enter image description here

Build docker image

因為我有好幾個測試專案,預設會產生好幾個code coverage的report 。 所以在執行dotnet test 有一些特殊的參數來讓這些report 合併成一個。

第一個是 CoverletOutputFormat=“json%2ccobertura” ,用來指定產出report的格式,注意這個 %2c 是分號 ; 的意思。 但是如果直接寫;在docker build 時會有powershell的錯誤。弄了很久才找到解法,改成%2C (是ascii code ; 的意思)就可以過了。

第二個是MergeWith=/testresults/coverage/coverage.json 。用MergeWith 來指定多個 code coverage 的report 跟誰合併,要指定report的位置在個目錄。

另外,在dockerfile 裡我有下了一個 label 叫 test=true ,這個是用來讓docker build 完之後還可以找到暫存的stage ,從裡面把我們的測試報告copy出來。

底下是我部份的dockerfile , 我的web.sln 裡面有3個程式專案及4個測試專案。

RUN dotnet restore web.sln
RUN dotnet build web.csproj -c Release -o /app/out 

# unit test
#先下一個label 
LABEL test=true
# 安裝dotnet-reportgenerator-globaltool 用來產生cobertura 格式的 code coverage report
RUN dotnet tool install dotnet-reportgenerator-globaltool --version 4.2.2 --tool-path /tools  

# %2c 是 ;(分號) 很重要!! 很重要!! 因為直接用; 會出錯。
RUN dotnet test --results-directory /testresults --logger:trx /p:CollectCoverage=true /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=/testresults/coverage/coverage.json /p:Exclude="[xunit.*]*" /p:CoverletOutput=/testresults/coverage/ web.sln

RUN /tools/reportgenerator.exe "-reports:/testresults/coverage/coverage.cobertura.xml"  "-targetdir:/testresults/coverage/reports"  "-reporttypes:HTMLInline`;HTMLChart"

用powershell 取得測試結果

enter image description here

script說明

  1. 先找到下label=test的 docker id, 預設會新的在最上面,所以抓第 0 個
  2. 用找到的id 建立一個臨時的container
  3. 從container把測試結果copy 出來
  4. 這個臨時的container就可以移除惹
$id=$($(docker images --filter "label=test=true" -q)[0]);
docker create --name testcontainer $id;
docker cp testcontainer:/testresults ./;
docker rm testcontainer;

發行測試結果

enter image description here
測試結果格式選 VSTest
搜尋資料夾要選對,我的例子是 testresults

發行程式碼涵蓋範圍結果

enter image description here
程式碼涵蓋範圍工具 選cobertura
摘要檔案 跟 報告目錄 路徑要設對


如果都成功了,就可以在組建的摘要裡看到測試結果了,就像第一張圖一樣。 也可以在測試的tab看到詳細的結果
enter image description here

同場加映

看完上面的,有沒有感到奇怪,為什麼沒有code coverage 的詳細資料。
因為這是 Azure Devops Server 2019 目前版本的bug,但是線上版的Azure devops 是有詳細資料的。

在 2019/5/22 己經有人回報給 visual studio team了 ,MS也有回覆下個release會修好。

Code coverage tab missing in Azure DevOps Server

另外

前端(angular) 的unit test 也可以用類似的方法,產出測試報告跟上傳到devops server上,有空再來分享另一段血淚史。

2019年6月20日 星期四

Azure Devops Server 2019 更改電腦名稱

Azure Devops Server 2019 更改電腦名稱

在新VM裡安裝 Azure Devops Server 2019 時,沒有注意電腦名稱是什麼,後來想要改電腦名稱時,也沒想那麼多就直接改了。結果,改完重開機就連不上web 介面了,一直轉圈圈。
心裡想一定有什麼跟電腦名稱綁在一起無法執行。 後來在

C:\Program Files\Azure DevOps Server 2019\Application Tier\Web Services\web.config

找到資料庫連線字串的設定是用電腦名稱

    <add key="applicationDatabase" value="Data Source=WIN-IL123HEV1A2;Initial Catalog=AzureDevOps_Configuration;Integrated Security=True;Encrypt=False" />

把 Data Source 換成新的電腦名稱再重新開機一次就都正常了。

2019年6月18日 星期二

Azure Pipelines 建立部署群組卡關

Azure Pipelines 建立部署群組卡關

現在在測試新的Devpos環境, 以現有使用TFS的經驗,Azure Devops Server 2019 自然是第一個考慮的工具。

把Azure Devops Server 2019 的安裝比較沒什麼問題,基本上安裝程式會檢查環境,有缺什麼會顯示出來。例如:要先安裝SQL SERVER;要有JDK(沒有的話,打個勾勾會自動裝OpenJDK) 。 這個比遙遠的當年 TFS 2005 裝了好幾天才裝起來好太多了 。

不過安裝好之後,要在pipelines建第一個部署群組就卡關了,"部署群組"就是要部署到哪裡去,被部署的SERVER上面要裝一個代理程式( agent) 。

But… 安裝agent,居然是叫你自己下powershell command的方式。虧我前面還在誇Azure Devops Server 2019的安裝介面做的不錯。

雖然在介面上他己經產生好script,把他貼到powershell裡面去執行就好了。看起來一塊蛋榚啊!! 介面長的像這樣
部署群組圖1

照畫面上的指示,把那一堆Script放到powershell的command裡執行
結果
部署群組圖二

哇哩,反覆的仔細檢查script.

才發現179字元 “Administrator” 有問題, 把 “ ” 換成正常的 "

enter image description here

再來一次

PS C:\> $ErrorActionPreference="Stop";If(-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole( [Security.Principal.WindowsBuiltInRole] "Administrator")){ throw "在系統管理員 PowerShell 提示字元處執行命令"};If($PSVersionTable.PSVersion -lt (New-Object System.Version("3.0"))){ throw "指令碼 (3.0) 需要的 Windows PowerShell 最低版本,與目前正在執行的 Windows PowerShell 版本不符。" };If(-NOT (Test-Path $env:SystemDrive\'azagent')){mkdir $env:SystemDrive\'azagent'}; cd $env:SystemDrive\'azagent'; for($i=1; $i -lt 100; $i++){$destFolder="A"+$i.ToString();if(-NOT (Test-Path ($destFolder))){mkdir $destFolder;cd $destFolder;break;}}; $agentZip="$PWD\agent.zip";$DefaultProxy=[System.Net.WebRequest]::DefaultWebProxy;$securityProtocol=@();$securityProtocol+=[Net.ServicePointManager]::SecurityProtocol;$securityProtocol+=[Net.SecurityProtocolType]::Tls12;[Net.ServicePointManager]::SecurityProtocol=$securityProtocol;$WebClient=New-Object Net.WebClient; $Uri='https://go.microsoft.com/fwlink/?linkid=2066756';if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))){$WebClient.Proxy= New-Object Net.WebProxy($DefaultProxy.GetProxy($Uri).OriginalString, $True);}; $WebClient.DownloadFile($Uri, $agentZip);Add-Type -AssemblyName System.IO.Compression.FileSystem;[System.IO.Compression.ZipFile]::ExtractToDirectory( $agentZip, "$PWD");.\config.cmd --deploymentgroup --deploymentgroupname "first" --agent $env:COMPUTERNAME --runasservice --work '_work' --url 'http://172.16.1.111/' --collectionname 'DefaultCollection' --projectname 'uuuu' --auth Integrated; Remove-Item $agentZip;


    目錄: C:\azagent


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        2019/6/17  下午 03:18                A1


>> 連線:

正在連線到伺服器...

>> 註冊代理程式:

正在掃描工具功能。
正在連接至伺服器。
請輸入 代理程式的部署群組標記? (Y/N) (請為 否 按 Enter) >
已成功新增代理程式
正在測試代理程式連線。
2019-06-17 07:22:07Z: 已儲存設定。
請輸入 要用於服務的使用者帳戶 (請為 NT AUTHORITY\SYSTEM 按 Enter) >
正在將檔案權限授與 'NT AUTHORITY\SYSTEM'。
已成功安裝服務 vstsagent.172.TEST
服務 vstsagent.172.TEST 已成功設定復原選項
服務 vstsagent.172.TEST 已成功設定為延遲自動啟動
已成功設定服務 vstsagent.172.TEST
已成功啟動服務 vstsagent.172.TEST

終於可以註冊上去了,握拳!!


同場加映:如何移除 agent

從上面的script可以發現,他其實只做2件事,

  1. 下載1個zip 檔,然後解壓縮到C:\azagent\A1
  2. 執行裡面的config.cmd 跟著一堆參數

所以要移除agent , 一樣用有管理員身分的powershell到C:\azagent\A1 裡執行 config.cmd 只是參數換成remove

PS C:\azagent\a1> .\config.cmd remove
正在移除服務
正在等候服務結束...
成功:正在移除服務
正在從伺服器移除代理程式
請輸入 驗證類型 (請為 Integrated 按 Enter) >
正在連線到伺服器...
成功:正在從伺服器移除代理程式
正在移除 .credentials
成功:正在移除 .credentials
正在移除 .agent
成功:正在移除 .agent