先前已經有直接在 pipeline 專案內執行批次指令來分析專案,但這樣做的話其實並沒有辦法在專案分析的時候,判斷分析結果,只能依照原先做好的流程一直走下去,因此這一篇文章主要在解決這一點,透過 Jenkins 套件來處理這件事情
事前準備 整體的流程如下
專案建置、產生測試報告等等
執行分析
等候分析結果
SonarQube:新增全域 token 這裡新增的 token 請選擇 Global
,這個是為了要給 Jenkins 後續分析專案、取得結果使用,那行只顯示一次的 token 也要先記起來,等等在 Jenkins 新增認證的時候會需要輸入
SonarQube:新增分析專案 webHook 要設定專案的 webHook,從下圖的地方點選進去
從右上角點新增跳出燈箱,輸入資料,名稱隨意,URL 指的是當分析完成之後 sonarQube 要打的網址,這個就填 Jenkins 主機加上sonarqube-webhook
,例如:http://localhost:8080/sonarqube-webhook
,最後面密碼指的是剛剛新增的全域 token,例如:sqa_e6a8c5e3a2ce39b60501c5ddc319b3c90442daf1
在分析的流程當中所需要的 token 都要用相同的,否則在 Jenkins 請求訪問分析結果的時候,會出現 http 401
Jenkins:SonarQube Scanner for Jenkins 在這個步驟裡面,我們會需要透過SonarQube Scanner for Jenkins 套件來完成分析、等候的這兩個部分,從管理Jenkins
->外掛總管
並選擇可用的,找到套件安裝即可
Jenkins:新增認證 在 Jenkins 透過 SonarQube Scanner for Jenkins
互動的時候會需要 sonarQube 的有效 token,因此在 Jenkins Credentials 這邊也需要新增一個 Secret Text
。Secret 欄位就輸入上面新增的全域 token
Jenkins:SonarQube Server 設定 接著是設定系統
,在這裡需要將我們的 sonarQube server 資訊設定好,包含
Name: 填寫一個名稱,後續會用到,我這邊是填寫 local-sonarqube
Server URL: 這邊我的 SonarQube Server 是架在 localhost:9000
Server authentication token: 使用先前建立的 sonarqube-key
Webhook Secret: 使用先前建立的 sonarqube-key
Jenkins:SonarQube Scanner 設定 因為先前已經有下載過 scanner,所以我就直接把 scanner 路徑填一填,雖然他有自動安裝的選項但我沒有用過,這樣在隨後的 pipeline 就可以透過套件提供的工具 tool 來呼叫 scanner,如果是非 C# 專案,就要自己再去找找對的 scanner
pipeline 設定 執行分析的範例如下,理論上測試報告產生之前要先 build 一次最新的建置,實務上請自行斟酌作法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 node() { ws('D:\\code\\Github\\Repos\\TaskProject' ) { stage('Coverage' ) { bat "del *.dcvr" bat ''' "D:\\art\\programs\\JetBrains.dotCover.CommandLineTools.2022.1.2\\dotCover.exe" cover /TargetExecutable="D:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\Extensions\\TestPlatform\\vstest.console.exe" /TargetArguments="TaskProjectTests.dll" /TargetWorkingDir="TaskProjectTests\\bin\\debug" /Output="TaskProjectTests.dcvr" ''' bat '"D:\\art\\programs\\JetBrains.dotCover.CommandLineTools.2022.1.2\\dotCover.exe" report --source=TaskProjectTests.dcvr --output=report.html --reportType=html' } stage('UnitTest' ) { bat "del testResults /s /q" bat ''' "D:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow\\vstest.console.exe" /Logger:trx TaskProjectTests\\bin\\Debug\\TaskProjectTests.dll ''' } stage('SonarQube analysis' ) { def scanner = tool name: 'SonarScanner.MSBuild-net46' withSonarQubeEnv(installationName: 'local-sonarqube' ,credentialsId: 'sonarqube-key' ) { bat "del .sonarqube /s /q" bat "${scanner}\\SonarScanner.MSBuild.exe begin /k:taskProject /d:sonar.host.url=http://localhost:9000 /d:sonar.cs.dotcover.reportsPaths=report.html /d:sonar.cs.vstest.reportsPaths=TestResults/*.trx" bat "msbuild.exe /t:Rebuild" bat "${scanner}\\SonarScanner.MSBuild.exe end" } script { timeout(time: 1 , unit: 'HOURS' ) { def qg = waitForQualityGate(webhookSecretId: 'sonarqube-key' ) if (qg.status != 'OK' ) { error "Pipeline aborted due to quality gate failure: ${qg.status}" } } } } stage('END' ) { bat '@echo OK' } } }
測試 這裡的測試專案我拿了一個 C# 的簡單的單元測試,因為之前有做過很多次這方面的練習了,如何分析專案的細節,怎麼加入測試數量、測試覆蓋率就不再贅述,利用 sonarQube 的 quality gate 設定,我設定了一個新增的程式碼覆蓋率必須要達到 99%才算成功,利用這個東西設定讓 Jenkins 取得分析結果是失敗的,然後看看他能不能中止
第一次先跑專案,當然先讓他過,第二次隨意加一些沒有用到的 code 並再次分析就會失敗了
在主畫面也可以看到建置紀錄與左側都有 SonarQube 的超連結,點過去就可以看到分析專案的資料了
結論 CI流程中若分析失敗,通常需要通知某些人,做某一些事情,而 SonarQube 本身的通知機制我是覺得有點難用,所以流程的事情最好還是交給 Jenkins 來處理,不管是透過 Email 通知,還是要透過 Teams 都很方便。接下來要考慮的就是什麼時間點進行分析的動作,這就看公司資源及需要了。
補充:加入信件通知 主要還是依靠外掛套件Email Extension 來做,測試用的 SMTP 服務可以用 smtp4dev ,寄送 EMAIL 還要去設定一下,這裡就不贅述了,pipeline 範例如下
1 2 emailext attachLog: true , body: '' , recipientProviders: [buildUser(), developers()], subject: '[TaskProject] Success'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 node() { ws('D:\\code\\Github\\Repos\\TaskProject' ) { stage('Coverage' ) { bat "del *.dcvr" bat ''' "D:\\art\\programs\\JetBrains.dotCover.CommandLineTools.2022.1.2\\dotCover.exe" cover /TargetExecutable="D:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\Extensions\\TestPlatform\\vstest.console.exe" /TargetArguments="TaskProjectTests.dll" /TargetWorkingDir="TaskProjectTests\\bin\\debug" /Output="TaskProjectTests.dcvr" ''' bat '"D:\\art\\programs\\JetBrains.dotCover.CommandLineTools.2022.1.2\\dotCover.exe" report --source=TaskProjectTests.dcvr --output=report.html --reportType=html' } stage('UnitTest' ) { bat "del testResults /s /q" bat ''' "D:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow\\vstest.console.exe" /Logger:trx TaskProjectTests\\bin\\Debug\\TaskProjectTests.dll ''' } stage('SonarQube analysis' ) { def scanner = tool name: 'SonarScanner.MSBuild-net46' bat "@echo Scanner Path:${scanner}" withSonarQubeEnv(installationName: 'local-sonarqube' ,credentialsId: 'sonarqube-key' ) { bat "del .sonarqube /s /q" bat "${scanner}\\SonarScanner.MSBuild.exe begin /k:taskProject /d:sonar.host.url=http://localhost:9000 /d:sonar.cs.dotcover.reportsPaths=report.html /d:sonar.cs.vstest.reportsPaths=TestResults/*.trx" bat "msbuild.exe /t:Rebuild" bat "${scanner}\\SonarScanner.MSBuild.exe end" } script { timeout(time: 1 , unit: 'HOURS' ) { def qg = waitForQualityGate(webhookSecretId: 'sonarqube-key' ) if (qg.status != 'OK' ) { emailext attachLog: true , body: '' , recipientProviders: [buildUser(), developers()], subject: '[TaskProject] Failed' error "Pipeline aborted due to quality gate failure: ${qg.status}" } } } } stage('END' ) { bat '@echo OK' emailext attachLog: true , body: '' , recipientProviders: [buildUser(), developers()], subject: '[TaskProject] Success' } } }
補充:執行建置成功後觸發分析 JOB 先前的做法是在同一台主機上面執行,如果專案不多,或只是自己練習應該是合適的,但如果能夠拆開各自獨立的任務,應該更容易運用,因此將建置的部分獨立一個任務,在建置成功完畢後觸發分析任務。 因為建置任務先前採用的是 pipeline script
,所以只需要透過build
即可觸發任務,同時將Git Parameter
傳遞出去即可,詳請請參照Jenkins 參數化建置與上下游專案 的 【補充:觸發另一個任務並傳遞參數範例】一節