日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

基于Jenkins Pipeline的ASP.NET Core持续集成实践

發布時間:2023/12/4 asp.net 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Jenkins Pipeline的ASP.NET Core持续集成实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近在公司實踐持續集成,使用到了Jenkins的Pipeline來提高團隊基于ASP.NET Core API服務的集成與部署,因此這里總結一下。

一、關于持續集成與Jenkins?Pipeline

1.1 持續集成相關概念

  互聯網軟件的開發和發布,已經形成了一套標準流程,最重要的組成部分就是持續集成(Continuous integration,簡稱 CI) 。

  持續集成指的是,頻繁地 (一天多次) 將代碼集成到主干

  它的好處主要有兩個:

(1)快速發現錯誤每完成一點更新,就集成到主干,可以快速發現錯誤,定位錯誤也比較容易。

(2)防止分支大幅偏離主干如果不是經常集成,主干又在不斷更新,會導致以后集成的難度變大,甚至難以集成。

  持續集成的目的,就是讓產品可以快速迭代,同時還能保持高質量

Martin Fowler 說:“ 持續集成并不能消除 Bug,而是讓它們非常容易發現和改正。” 

  與持續集成相關的,還有持續交付和持續部署。

  持續交付指的是:頻繁地將軟件的新版本,交付給質量團隊或者用戶,以供評審如果評審通過,代碼就進入生產階段。它強調的是,不管怎么更新,軟件是隨時隨地可以交付的

  持續部署是持續交付的下一步,指的是代碼通過評審以后,自動部署到生產環境它強調的是代碼在任何時刻都是可部署的,可以進入生產階段

1.2 Jenkins Pipeline

  Jenkins 是一款流行的開源持續集成(CI)與持續部署(CD)工具,廣泛用于項目開發,具有自動化構建、測試和部署等功能。有關Jenkins的安裝,可以參考我的這一篇文章進行安裝。

  相信很多童鞋都已經在使用Jenkins或者計劃使用Jenkins來代替傳統的人工發布流程了,因此我們創建了很多自由風格(Free Style)的構建任務用于多個Job,而我們經常會聽到說流水線任務,那么流水線是什么呢?

  流水線Pipeline是一套運行于Jenkins上的工作流框架,將原本獨立運行于單個或者多個節點的任務連接起來,實現單個任務難以完成的復雜流程編排與可視化。下圖是一個Jenkins Pipeline的實例效果:

Pipeline :Build => Test => Deploy

  這里涉及到Pipeline中的幾個重要概念,需要了解一下:

  • Stage: 階段,一個Pipeline可以劃分為若干個Stage,每個Stage代表一組操作。注意,Stage是一個邏輯分組的概念,可以跨多個Node。如上圖所示,Build,Test和Deploy就是Stage,代表了三個不同的階段:編譯、測試和部署。

  • Node: 節點,一個Node就是一個Jenkins節點,或者是Master,或者是Slave,是執行Step的具體運行期環境。

  • Step: 步驟,Step是最基本的操作單元,小到創建一個目錄,大到構建一個Docker鏡像,由各類Jenkins Plugin提供。

二、準備ASP.NET Core Docker環境

2.1 安裝Docker環境

  可以參考我的這一篇《.NET Core微服務之ASP.NET Core on Docker》來安裝和配置Docker環境,建議在Linux環境下配置。

2.2 安裝SFTP服務

  在Linux下,SSH服務默認會安裝,而在Windows Server下,需要單獨安裝,可以借助FreeSSHD這個免費工具來實現。由于我的物理機都是Windows Server,物理機上的VM是Linux(Docker運行環境),所以需要給物理機配置FreeSSHD,用來實現從CI服務器發布Release到物理服務器中的VM。

  至于如何安裝配置FreeSSHD,可以參考這一篇《freeSSHD在windows環境下搭建SFTP服務器》。

三、配置Pipeline流水線任務

3.1 總體目標

  (1)持續集成:實現編譯+單元測試的自動運行

  這里我要實現的目標是:當有人push代碼到git server中(這里我使用的git server是Gogs,需要給Gogs設置一個Webhook,如下圖所示,需要注意的是設置的密鑰文本要和在Pipeline中填寫的一致,否則Jenkins無法正確接收Web鉤子),git server會觸發一個webhook發送一個post的請求給CI server,CI server會觸發Pipeline任務的構建,一路pull代碼+編譯+單元測試。

  (2)持續發布:實現編譯+發布到具體的測試環境

  由于在開發階段,我不需要每次Push都進行發布,因此我這里設置的是手動在Jenkins中觸發發布任務來實現自動化發布。

3.2 全局設置

  首先,肯定是Jenkins的插件安裝了。

  (1)Generic WebHook Trigger => 觸發WebHook必備

  (2)Gogs Plugin => 因為我使用的Git Server是Gogs搭建的

  (3)MSBuild Plugin => 進行sln、csproj項目文件的編譯

  (4)MSTest & xUnit => 進行基于MSTest或基于xUnit的單元測試

  (5)Nuget Plugin => 拉取Nuget包必備

  (6)Pipeline => 實現Pipeline任務必備,建議將Pipeline相關插件都安裝上

  (7)Powershell Plugin => 如果你的CI服務器是基于Windows的,那么安裝一下Powershell插件來執行命令吧

  (8)Publish Over SSH => 遠程發布Release必備

  (9)WallDisplay => 電視投屏構建任務列表必備

  其次,為了提示郵件,也要Email插件(Email Extension)的支持,并進行以下配置:

  (1)第一處:Jenkins Location

  (2)第二處:Email擴展插件全局變量設置

  這里主要是需要設置Subject和Content,就可以在各個Pipeline中使用了。因此,這里貼出我的Default Content內容:

<!DOCTYPE?html> <html> <head> <meta charset="UTF-8"> <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次構建日志</title> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <table width="95%" cellpadding="0" cellspacing="0" style="font-size:?11pt;?font-family:?Microsoft?YaHei,?Tahoma,?Arial,?Helvetica"> <tr> <td>各位同事,大家好,以下為 ${PROJECT_NAME } 構建任務信息</td> </tr> <tr> <td><br /> <b style="font-weight:bold;?color:#66cc00">構建信息</b> <hr size="2" width="100%" align="center" /></td> </tr> <tr> <td> <ul> <li>任務名稱 :${PROJECT_NAME}</li> <li>構建編號 :第${BUILD_NUMBER}次構建</li> <li>觸發原因:${CAUSE}</li> <li>構建狀態:<span style="font-weight:bold;?color:#FF0000">${BUILD_STATUS}</span></li> <li>構建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li> <li>構建 Url :<a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>工作目錄 :<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li> <li>項目 Url :<a href="${PROJECT_URL}">${PROJECT_URL}</a></li> </ul> </td> </tr> </table> </body> </html>

  為了能夠發給更多的人,建議勾選以上兩個選項。

  這里是Email通知必填的SMTP服務器配置。

  最后,是SSH服務器的聲明,指定可以進行SSH發布的服務器有哪些,IP又是多少:

3.3 新增Pipeline腳本

  (1)持續集成Pipeline

  首先,填寫Webhook的密鑰文本:

  其次,Build Triggers的時機選擇“Build when a change is pushed to Gogs”,即有人push代碼到倉庫就觸發。當然,這里需要提前在Gogs設置Webhook。

  其次,編寫Pipeline腳本,各個Stage寫清楚職責:

  具體的Pipeline腳本在下邊:

pipeline{ agent any stages { stage('XDP Core Services Checkout') { steps{ checkout([$class: 'GitSCM',?branches:?[[name:?'*/dev-xds']],?doGenerateSubmoduleConfigurations:?false,?extensions:?[],?submoduleCfg:?[],?userRemoteConfigs:?[[credentialsId:?'35b9890b-2338-45e2-8a1a-78e9bbe1d3e2',?url:?'http://192.168.18.150:3000/EDC.ITC.XDP.Core/EDC.XDP.Core.git']]]) echo 'Core Services Checkout Done' } } stage('XDP Core Services Build') { steps{ bat '''cd?"D:\\Jenkins\\workspace\\XDS.Dev.CI.Pipeline\\src\\services\\EDC.XDP.Core\\" dotnet build EDC.XDP.Core-All.sln''' echo 'Core Services Build Done' } } stage('Core Delivery Service Unit Test') { steps{ bat '''cd?"D:\\Jenkins\\workspace\\XDS.Dev.CI.Pipeline\\src\\services\\EDC.XDP.Core\\Services\\EDC.XDP.Core.Delivery.UnitTest" dotnet test -v n --no-build EDC.XDP.Core.Delivery.UnitTest.csproj''' echo 'Core Delivery Service Unit Test Done' } } stage('XDS Delivery Service Checkout') { steps{ checkout([$class: 'GitSCM',?branches:?[[name:?'*/dev-service']],?doGenerateSubmoduleConfigurations:?false,?extensions:?[],?submoduleCfg:?[],?userRemoteConfigs:?[[credentialsId:?'35b9890b-2338-45e2-8a1a-78e9bbe1d3e2',?url:?'http://192.168.18.150:3000/EDC.ITC.XDP.XDS/EDC.XDP.XDS.git']]]) echo 'Core Delivery Service Checkout Done' } } stage('XDS Delivery Service Build') { steps{ bat '''cd?"D:\\Jenkins\\workspace\\XDS.Dev.CI.Pipeline\\src\\services\\EDC.XDP.XDS" dotnet build EDC.XDP.XDS.sln''' echo 'XDS Service Build Done' } } stage('XDS Delivery Service Unit Test') { steps{ bat '''cd?"D:\\Jenkins\\workspace\\XDS.Dev.CI.Pipeline\\src\\services\\EDC.XDP.XDS\\EDC.XDP.XDS.Delivery.UnitTest" dotnet test -v n --no-build EDC.XDP.XDS.Delivery.UnitTest.csproj''' echo 'XDS Service Unit Test Done' } } } post{ failure { emailext (????????????????subject:?'${DEFAULT_SUBJECT}',????????????????body:?'${DEFAULT_CONTENT}',????????????????to:?"edisonchou@qq.com,xxxxx@qq.com") } }}

????(2)持續發布Pipeline

  持續發布Pipeline與持續集成Pipeline類似,只是在腳本處有所不同:

pipeline{????agent?any stages { stage('Core Delivery Service Checkout') { steps{ checkout([$class: 'GitSCM',?branches:?[[name:?'*/dev-xds']],?doGenerateSubmoduleConfigurations:?false,?extensions:?[],?submoduleCfg:?[],?userRemoteConfigs:?[[credentialsId:?'35b9890b-2338-45e2-8a1a-78e9bbe1d3e2',?url:?'http://192.168.18.150:3000/EDC.ITC.XDP.Core/EDC.XDP.Core.git']]]) echo 'Core Delivery Service Dev Branch Checkout Done' } } stage('Core Delivery Service Build & Publish') { steps{ bat '''cd?"D:\\Jenkins\\workspace\\XDS.API.Dev.CD.Pipeline\\src\\services\\EDC.XDP.Core" dotnet build EDC.XDP.Core-DataServices.sln dotnet publish "%WORKSPACE%\\src\\services\\EDC.XDP.Core\\Services\\EDC.XDP.Core.Delivery.API\\EDC.XDP.Core.Delivery.API.csproj" -o "%WORKSPACE%\\EDC.XDP.Core.Delivery.API/publish" --framework netcoreapp2.1 ''' echo 'Core Delivery Service Build & Publish Done' } } stage('Core Delivery Service Deploy To 190 Server') { steps{????????????sshPublisher(publishers:?[sshPublisherDesc(configName:?'XDP-DEV-Server',?transfers:?[sshTransfer(cleanRemote:?false,?excludes:?'',?execCommand:?'''docker?stop?xdp_core_deliveryservice;?docker?rm?xdp_core_deliveryservice;?docker?run?--ulimit?core=0?--restart=always?-v?/etc/localtime:/etc/localtime?-d?-e?ASPNETCORE_ENVIRONMENT=dev?--privileged=true?--name=xdp_core_deliveryservice?-p?8010:80?-v?/XiLife/publish/EDC.XDP.Core.Delivery.API/:/app?-w?/app?xdp_service_runtime:latest??dotnet?EDC.XDP.Core.Delivery.API.dll''',?execTimeout:?120000,?flatten:?false,?makeEmptyDirs:?false,?noDefaultExcludes:?false,?patternSeparator:?'[, ]+',?remoteDirectory:?'EDC.XDP.Core.Delivery.API/',?remoteDirectorySDF:?false,?removePrefix:?'EDC.XDP.Core.Delivery.API/publish/',?sourceFiles:?'EDC.XDP.Core.Delivery.API/publish/**')],?usePromotionTimestamp:?false,?useWorkspaceInPromotion:?false,?verbose:?false)]) echo 'Delivery Service Deploy To 190 Done' } } stage('Core Delivery Service Deploy To 175 Server') { steps{????????????sshPublisher(publishers:?[sshPublisherDesc(configName:?'XDP-DEV-MT-Server',?transfers:?[sshTransfer(cleanRemote:?false,?excludes:?'',?execCommand:?'''docker?stop?xdp_core_deliveryservice;?docker?rm?xdp_core_deliveryservice;?docker?run?--ulimit?core=0?--restart=always?-v?/etc/localtime:/etc/localtime?-d?-e?ASPNETCORE_ENVIRONMENT=devmt?--privileged=true?--name=xdp_core_deliveryservice?-p?8010:80?-v?/XiLife/publish/EDC.XDP.Core.Delivery.API/:/app?-w?/app?xdp_service_runtime:latest??dotnet?EDC.XDP.Core.Delivery.API.dll''',?execTimeout:?120000,?flatten:?false,?makeEmptyDirs:?false,?noDefaultExcludes:?false,?patternSeparator:?'[, ]+',?remoteDirectory:?'EDC.XDP.Core.Delivery.API/',?remoteDirectorySDF:?false,?removePrefix:?'EDC.XDP.Core.Delivery.API/publish/',?sourceFiles:?'EDC.XDP.Core.Delivery.API/publish/**')],?usePromotionTimestamp:?false,?useWorkspaceInPromotion:?false,?verbose:?false)]) echo 'Delivery Service Deploy To 175 Done' } } stage('XDS Delivery Service Checkout') { steps{ checkout([$class: 'GitSCM',?branches:?[[name:?'*/dev-service']],?doGenerateSubmoduleConfigurations:?false,?extensions:?[],?submoduleCfg:?[],?userRemoteConfigs:?[[credentialsId:?'35b9890b-2338-45e2-8a1a-78e9bbe1d3e2',?url:?'http://192.168.18.150:3000/EDC.ITC.XDP.XDS/EDC.XDP.XDS.git']]]) echo 'XDS Delivery Service Checkout Done' } } stage('XDS Delivery Service Build & Publish') { steps{ bat '''cd?"D:\\Jenkins\\workspace\\XDS.API.Dev.CD.Pipeline\\src\\services\\EDC.XDP.XDS" dotnet build EDC.XDP.XDS.sln dotnet publish "%WORKSPACE%\\src\\services\\EDC.XDP.XDS\\EDC.XDP.XDS.Delivery.API\\EDC.XDP.XDS.Delivery.API.csproj" -o "%WORKSPACE%\\EDC.XDP.XDS.Delivery.API/publish" --framework netcoreapp2.1 ''' echo 'XDS Delivery Service Build & Publish Done' } } stage('XDS Delivery Service Deploy To 190 Server') { steps{????????????sshPublisher(publishers:?[sshPublisherDesc(configName:?'XDP-DEV-Server',?transfers:?[sshTransfer(cleanRemote:?false,?excludes:?'',?execCommand:?'''docker?stop?xdp_xds_delivery_service;docker?rm?xdp_xds_delivery_service;?docker?run?--ulimit?core=0?--restart=always?-v?/etc/localtime:/etc/localtime?-d?-e?ASPNETCORE_ENVIRONMENT=dev?--privileged=true?--name=xdp_xds_delivery_service?-p?9020:80?-v?/XiLife/publish/EDC.XDP.XDS.Delivery.API/:/app?-w?/app?xdp_service_runtime:latest??dotnet?EDC.XDP.XDS.Delivery.API.dll''',?execTimeout:?120000,?flatten:?false,?makeEmptyDirs:?false,?noDefaultExcludes:?false,?patternSeparator:?'[, ]+',?remoteDirectory:?'EDC.XDP.XDS.Delivery.API/',?remoteDirectorySDF:?false,?removePrefix:?'EDC.XDP.XDS.Delivery.API/publish/',?sourceFiles:?'EDC.XDP.XDS.Delivery.API/publish/**')],?usePromotionTimestamp:?false,?useWorkspaceInPromotion:?false,?verbose:?false)]) echo 'XDS Delivery Service Deploy to 190 Done' } } stage('XDS Delivery Service Deploy To 175 Server') { steps{????????????sshPublisher(publishers:?[sshPublisherDesc(configName:?'XDP-DEV-MT-Server',?transfers:?[sshTransfer(cleanRemote:?false,?excludes:?'',?execCommand:?'''docker?stop?xdp_xds_delivery_service;docker?rm?xdp_xds_delivery_service;?docker?run?--ulimit?core=0?--restart=always?-v?/etc/localtime:/etc/localtime?-d?-e?ASPNETCORE_ENVIRONMENT=devmt?--privileged=true?--name=xdp_xds_delivery_service?-p?9020:80?-v?/XiLife/publish/EDC.XDP.XDS.Delivery.API/:/app?-w?/app?xdp_service_runtime:latest??dotnet?EDC.XDP.XDS.Delivery.API.dll''',?execTimeout:?120000,?flatten:?false,?makeEmptyDirs:?false,?noDefaultExcludes:?false,?patternSeparator:?'[, ]+',?remoteDirectory:?'EDC.XDP.XDS.Delivery.API/',?remoteDirectorySDF:?false,?removePrefix:?'EDC.XDP.XDS.Delivery.API/publish/',?sourceFiles:?'EDC.XDP.XDS.Delivery.API/publish/**')],?usePromotionTimestamp:?false,?useWorkspaceInPromotion:?false,?verbose:?false)]) echo 'XDS Delivery Service Deploy to 175 Done' } } }}

? ? ? ?這里由于我的測試環境分為兩個,一個是開發人員聯調環境190,另一個是集成測試環境175,統一在一個Pipeline任務中進行發布。

  對于Master分支,我們還可以將Web系統的發布也集成到同一個Pipeline任務中,實現一個一條龍的發布流水線任務,由于各個Web系統的實現技術不一樣,這里就不再貼腳本了。

四、效果演示

  (1)持續集成示例

  (2)持續發布示例

  (3)構建失敗告警

  (4)構建大屏顯示

  再來一張投屏到工作區域電視屏幕中的效果,大家抬頭就可以看到構建結果,是綠了還是紅了?當然,我們都喜歡“綠”的,呼呼。

五、小結

  借助持續集成和持續發布,我們開發人員可以節省很多質量保證和發布部署的時間,從而減少很多因為人為QA和Deploy造成的失誤影響,從另一個層面上,它也可以使我們避免996(好吧,雖然關聯有點牽強)。后續,我還會探索K8S,到時候希望能夠分享一個ASP.NET?Core?on?K8S的系列文章,敬請期待。

參考資料

大寶魚,《玩轉Jenkins Pipeline

李志強,《Jenkins高級用法 - Pipeline 安裝

李志強,《Jenkins高級用法 - Jenkinsfile 介紹及實戰經驗

三只松鼠,《jenkins + pipeline構建自動化部署

ofnhkb1,《.NET項目從CI到CD-Jenkins_Pipeline的應用



總結

以上是生活随笔為你收集整理的基于Jenkins Pipeline的ASP.NET Core持续集成实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。