Jenkins持續集成學習-Windows環境進行.Net開發
目錄
Jenkins持續集成學習-Windows環境進行.Net開發1
Jenkins持續集成學習-Windows環境進行.Net開發2
Jenkins持續集成學習-Windows環境進行.Net開發3
Jenkins持續集成學習-Windows環境進行.Net開發4
Jenkins持續集成學習-搭建jenkins問題匯總
前言
本文探究在.net環境下的持續集成環境研究並使用。關於為什么使用Jenkins,可以參考一下jenkins持續集成原理
目標
學習jenkins的基本使用,完成以下2點任務。
- 搭建jenkins任務完成自動編譯。
- 自動從nuget上獲取需要的包。
使用Jenkins
安裝
到Jenkins官網下載安裝包,進行安裝。安裝完成后會自動打開一個頁面。默認是網站是localhost:8080。若端口已被占用則需要修改成別的端口。
具體安裝問題可以看這里淺談.net jenkins svn下自動化集成環境安裝 搭建 配置
主要是安裝完后需要安裝.net的環境的一些插件及svn(或git)等相關插件。
根據官網描述是需要安裝java環境的
添加.net環境配置
安裝完后如果要在.net環境使用,在MSBuild插件安裝完的前提下。配置msbuild.exe的路徑。這樣jenkins就能通過msbuild來編譯.net項目了。具體配置可以可以參考《為 Jenkins 配置 .NET 持續集成環境》
我本地的jenkins的全局配置配的MSBuild也為14.0
安裝了不同版本的VS的MSBuild版本可能不一樣。

部署
我們通過VS先新建一個控制台項目.net framework4.5的項目,項目名稱叫做JenkinsTest。在Program.cs中簡單的輸出hello world
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
程序目錄如下
│ JenkinsTest.sln
│
└─JenkinsTest
│ App.config
│ JenkinsTest.csproj
│ Program.cs
│
└─Properties
AssemblyInfo.cs
編譯通過后將項目上傳到SVN上,我在我本地建了SVN的服務,並增加了用戶名和密碼分別為test。

新建項目

創建一個名為test的自由風格軟件項目。

我本地使用的是SVN,因此選擇Subversion,輸入SVN的路徑。Local module directory為SVN獲取代碼的路徑。.表示獲取到jenkins的根目錄下。

首次創建的時候需要創建SVN的登錄憑據,在Credentials項點擊Add添加一個新的憑據,類型就選擇Username with password即可,id需要輸入一個唯一憑據標識。

在Build Environment下勾選Add timestamps to the Console Output,這樣可以顯示時間戳。

在Build選擇MSBuild的版本,這個版本在全局配置設置過,在這里就可以顯示出來。MSBuild Build File輸入需要編譯的程序集文件名。在Command Line Arguments輸入編譯的參數,我們編譯成Realse版本。完成后點擊保存即可。具體MSBuild指令不做具體探究,有什么問題直接可以看官方文檔
點擊立即構建就會自動編譯,完成就會顯示一個結果


點擊#1即可調轉到該次編譯的詳細信息中,在左側點擊Console Output可以看到編譯的過程日志。

構建過程分析
-
先從SVN獲取代碼
16:21:55 由用戶 jake 啟動 16:21:55 構建中 在工作空間 D:\Program Files (x86)\Jenkins\workspace\test 中 16:21:55 Updating https://jakepc/svn/JenkinsTest/trunk/JenkinsTest at revision '2019-01-18T16:21:55.792 +0800' --quiet 16:21:55 Using sole credentials test/****** (本地svn服務器) in realm ‘<https://jakepc:443> VisualSVN Server’ 16:21:55 At revision 3 -
調用MSBuild命令進行編譯,這里會查找我們全局配置的MSBuild.exe執行我們在創建時輸入的
Command Line Arguments指令。16:21:56 Path To MSBuild.exe: C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe 16:21:56 Executing the command cmd.exe /C " "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" /t:Build /p:Configuration=Release JenkinsTest.csproj " && exit %%ERRORLEVEL%% from D:\Program Files (x86)\Jenkins\workspace\test 16:21:56 [test] $ cmd.exe /C " "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" /t:Build /p:Configuration=Release JenkinsTest.csproj " && exit %%ERRORLEVEL%% -
編譯完成,顯示警告,錯誤和結果
... 16:21:57 _CopyAppConfigFile: 16:21:57 正在將文件從“App.config”復制到“bin\Release\JenkinsTest.exe.config”。 16:21:57 CopyFilesToOutputDirectory: 16:21:57 正在將文件從“obj\Release\JenkinsTest.exe”復制到“bin\Release\JenkinsTest.exe”。 16:21:57 JenkinsTest -> D:\Program Files (x86)\Jenkins\workspace\test\bin\Release\JenkinsTest.exe 16:21:57 正在將文件從“obj\Release\JenkinsTest.pdb”復制到“bin\Release\JenkinsTest.pdb”。 16:21:57 已完成生成項目“D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest.csproj”(Build 個目標)的操作。 16:21:57 16:21:57 已成功生成。 16:21:57 0 個警告 16:21:57 0 個錯誤 16:21:57 16:21:57 已用時間 00:00:01.22 16:21:59 Finished: SUCCESS
通過以上三步驟,實際和我們自己使用VS編譯過程也是一樣的。
增加依賴dll
上面我們創建了一個最簡單的項目,並通過jenkins獲取並編譯成功了,下面我們增加項目復雜性,增加其他依賴項。
新建一個jenkins.Common的類庫。我們把HelloWorld的字符串通過該類庫獲取到,然后主項目進行輸出。
增加HelloWolrdHelper類獲取字符串
public class HelloWolrdHelper
{
public static string GetString()
{
return "Hello World!";
}
}
修改原項目
static void Main(string[] args)
{
Console.WriteLine(HelloWolrdHelper.GetString());
Console.ReadKey();
}

然后提交代碼到SVN后在jenkins再次構建,結構如下。
│ JenkinsTest.sln
│
├─Jenkins.Common
│ │ HelloWolrdHelper.cs
│ │ Jenkins.Common.csproj
│ │
│ └─Properties
│ AssemblyInfo.cs
│
└─JenkinsTest
│ App.config
│ JenkinsTest.csproj
│ Program.cs
│
└─Properties
AssemblyInfo.cs
構建一下,編譯成功了,MSBuild會根據csproj文件內的依賴關系編譯其他程序集。

生成啟動時間為 2019/1/18 17:16:03。
17:16:03 項目“D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj”在節點 1 上(Build 個目標)。
17:16:03 PrepareForBuild:
17:16:03 正在創建目錄“bin\Release\”。
17:16:03 正在創建目錄“obj\Release\”。
17:16:03 項目“D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj”(1)正在節點 1 上生成“D:\Program Files (x86)\Jenkins\workspace\test\Jenkins.Common\Jenkins.Common.csproj”(2) (默認目標)。
17:16:03 PrepareForBuild:
17:16:03 正在創建目錄“bin\Release\”。
17:16:03 正在創建目錄“obj\Release\”。
17:16:03 GenerateTargetFrameworkMonikerAttribute:
17:16:03 正在跳過目標“GenerateTargetFrameworkMonikerAttribute”,因為所有輸出文件相對於輸入文件而言都是最新的。
增加Nuget依賴
新建一個Jenkins.Core項目,並生成Nuget包上傳到Nuget服務器上。
關於Nuget如何打包可以看我之前的博客NuGet的使用、部署、搭建私有服務,這里不做討論。
為了簡單起見,創建一個和Jenkins.Common程序集一樣的輸出HelloWorld的方法,但是為了作為區分,分別略作修改。
Jenkins.Common的代碼
public class HelloWolrdHelper
{
public static string GetString()
{
return "Hello World! Jenkins.Common";
}
}
Jenkins.Core的代碼
public class HelloWolrdHelper
{
public static string GetString()
{
return "Hello World! Jenkins.Core";
}
}
程序結構如下
│ JenkinsTest.sln
│
├─.nuget
│ NuGet.Config
│ NuGet.exe
│ NuGet.targets
│
├─Jenkins.Common
│ │ HelloWolrdHelper.cs
│ │ Jenkins.Common.csproj
│ │
│ └─Properties
│ AssemblyInfo.cs
│
├─Jenkins.Core
│ │ HelloWorldHelper.cs
│ │ Jenkins.Core.csproj
│ │ Jenkins.Core.sln
│ │
│ └─Properties
│ AssemblyInfo.cs
│
└─JenkinsTest
│ App.config
│ JenkinsTest.csproj
│ packages.config
│ Program.cs
│
└─Properties
AssemblyInfo.cs
注意:Jenkins.Core我放到一個單獨的項目中打包的。原本我是放到原項目一起。但是Nuget似乎有個bug,導致編譯通不過。

因為控制台項目更新的時候會向JenkinsTest.csproj文件寫入nuget包還原的指令
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
而中解決方案的目錄是在上一層目錄
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>,最終編譯的時候會校驗pacakges是否存在已下載的包。通過路徑$(SolutionDir)\packages\下查找,即..\\packages\。多了一個\導致存在包仍然報錯查找不到,最終編譯不過。
上傳nuget包

然后從Nuget本地nuget服務器上獲取。

Program的代碼增加新的helloworld輸出
class Program
{
static void Main(string[] args)
{
Console.WriteLine(HelloWolrdHelper.GetString());
Console.WriteLine(Jenkins.Core.HelloWolrdHelper.GetString());
Console.ReadKey();
}
}
重新編譯項目后上傳代碼到SVN后再次到Jenkins上構建項目。

可以看到構建失敗了,去看下具體失敗原因。
正在將文件從“obj\Release\Jenkins.Common.pdb”復制到“bin\Release\Jenkins.Common.pdb”。
12:51:14 已完成生成項目“D:\Program Files (x86)\Jenkins\workspace\test\Jenkins.Common\Jenkins.Common.csproj”(默認目標)的操作。
12:51:14 ResolveAssemblyReferences:
12:51:14 主引用“Jenkins.Core, Version=0.2.0.0, Culture=neutral, processorArchitecture=MSIL”。
12:51:14 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): warning MSB3245: 未能解析此引用。未能找到程序集“Jenkins.Core, Version=0.2.0.0, Culture=neutral, processorArchitecture=MSIL”。請檢查磁盤上是否存在該程序集。 如果您的代碼需要此引用,則可能出現編譯錯誤。 [D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj]
12:51:14 用於 SearchPath“{HintPathFromItem}”。
12:51:14 已考慮使用“..\packages\Jenkins.Core.0.2.0\lib\net45\Jenkins.Core.dll”,但它不存在。
12:51:14 用於 SearchPath“{TargetFrameworkDirectory}”。
12:51:14 已考慮使用“C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Jenkins.Core.winmd”,但它不存在。
12:51:14 已考慮使用“C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Jenkins.Core.dll”,但它不存在
...
12:51:14 Program.cs(15,22): error CS0234: The type or namespace name 'Core' does not exist in the namespace 'Jenkins' (are you missing an assembly reference?) [D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj]
12:51:14 已完成生成項目“D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj”(Build 個目標)的操作 - 失敗。
12:51:15
12:51:15 生成失敗。
12:51:15
12:51:15 “D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj”(Build 目標) (1) ->
12:51:15 (ResolveAssemblyReferences 目標) ->
12:51:15 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): warning MSB3245: 未能解析此引用。未能找到程序集“Jenkins.Core, Version=0.2.0.0, Culture=neutral, processorArchitecture=MSIL”。請檢查磁盤上是否存在該程序集。 如果您的代碼需要此引用,則可能出現編譯錯誤。 [D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj]
12:51:15
12:51:15
12:51:15 “D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj”(Build 目標) (1) ->
12:51:15 (CoreCompile 目標) ->
12:51:15 Program.cs(15,22): error CS0234: The type or namespace name 'Core' does not exist in the namespace 'Jenkins' (are you missing an assembly reference?) [D:\Program Files (x86)\Jenkins\workspace\test\JenkinsTest\JenkinsTest.csproj]
12:51:15
12:51:15 1 個警告
12:51:15 1 個錯誤
12:51:15
12:51:15 已用時間 00:00:01.43
12:51:15 Build step 'Build a Visual Studio project or solution using MSBuild' marked build as failure
12:51:16 Finished: FAILURE
一開始會去..\packages\Jenkins.Core.0.2.0\lib\net45\Jenkins.Core.dll獲取,但是因為沒有包,后面就去遍歷其他目錄獲取,最終都沒有找到包導致編譯失敗。因此我們需要使用nuget,在MSBuild編譯之前將包下載下來。
為了方便我將nuget一同上傳到SVN上,SVN的程序目錄如下
│ JenkinsTest.sln
│
├─.nuget
│ NuGet.Config
│ NuGet.exe
│ NuGet.targets
│
├─Jenkins.Common
│ │ HelloWolrdHelper.cs
│ │ Jenkins.Common.csproj
│ │
│ └─Properties
│ AssemblyInfo.cs
│
└─JenkinsTest
│ App.config
│ JenkinsTest.csproj
│ packages.config
│ Program.cs
└─Properties
AssemblyInfo.cs
由於Jenkins.Core可以理解為第三方依賴,不是和JenkinsTest放一起。
在Build配置中新增一項批處理命令,執行nuget包還原。如圖拖動到編譯之前。

根據我們目錄結構調用".nuget/nuget.exe" restore JenkinsTest.sln命令使用nuget進行包還原。
由於.nuget目錄帶有.因此需要用雙引號引起來執行。
再次編譯仍然失敗了。可以通過日志看到已經在編譯前已經執行了腳本,但是沒有從我們想要的地方獲取包。
13:26:47 No changes for https://jakepc/svn/JenkinsTest/trunk/JenkinsTest since the previous build
13:26:47 [test] $ cmd /c call C:\WINDOWS\TEMP\jenkins8156278399083484284.bat
13:26:47
13:26:47 D:\Program Files (x86)\Jenkins\workspace\test>".nuget/nuget.exe" restore JenkinsTest.sln
13:26:47 MSBuild auto-detection: using msbuild version '15.9.21.664' from 'D:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin'.
13:26:48 Restoring NuGet package Jenkins.Core.0.2.0.
13:26:49 GET https://api.nuget.org/v3-flatcontainer/jenkins.core/0.2.0/jenkins.core.0.2.0.nupkg
13:26:49 NotFound https://api.nuget.org/v3-flatcontainer/jenkins.core/0.2.0/jenkins.core.0.2.0.nupkg 191ms
13:26:49 警告: Unable to find version '0.2.0' of package 'Jenkins.Core'.
13:26:49 C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\: Package 'Jenkins.Core.0.2.0' is not found on source 'C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\'.
13:26:49 https://api.nuget.org/v3/index.json: Package 'Jenkins.Core.0.2.0' is not found on source 'https://api.nuget.org/v3/index.json'.
13:26:49
13:26:49 警告: Unable to find version '0.2.0' of package 'Jenkins.Core'.
13:26:49 C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\: Package 'Jenkins.Core.0.2.0' is not found on source 'C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\'.
13:26:49 https://api.nuget.org/v3/index.json: Package 'Jenkins.Core.0.2.0' is not found on source 'https://api.nuget.org/v3/index.json'.
13:26:49
13:26:49
13:26:49 Errors in packages.config projects
13:26:49 Unable to find version '0.2.0' of package 'Jenkins.Core'.
13:26:49 C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\: Package 'Jenkins.Core.0.2.0' is not found on source 'C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\'.
13:26:49 https://api.nuget.org/v3/index.json: Package 'Jenkins.Core.0.2.0' is not found on source 'https://api.nuget.org/v3/index.json'.
13:26:49
13:26:49 NuGet Config files used:
13:26:49 D:\Program Files (x86)\Jenkins\workspace\test\.nuget\NuGet.Config
13:26:49 C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config
13:26:49 C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config
13:26:49
13:26:49 Feeds used:
13:26:49 https://api.nuget.org/v3/index.json
13:26:49 C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
13:26:49
13:26:49 D:\Program Files (x86)\Jenkins\workspace\test>exit 1
13:26:49 Build step '執行 Windows 批處理命令' marked build as failure
13:26:50 Finished: FAILURE
指定nuget包下載源地址。
找到Nuget.exe的配置Nuget.Config,在configuration節點內增加packageSources節點。
<packageSources>
<add key="Jake Package source" value="http://127.0.0.1:10080/nuget" />
</packageSources>
再次編譯,終於編譯成功了,日志如下。
13:38:08 No changes for https://jakepc/svn/JenkinsTest/trunk/JenkinsTest since the previous build
13:38:08 [test] $ cmd /c call C:\WINDOWS\TEMP\jenkins5326599668058283263.bat
13:38:08
13:38:08 D:\Program Files (x86)\Jenkins\workspace\test>".nuget/nuget.exe" restore JenkinsTest.sln
13:38:08 MSBuild auto-detection: using msbuild version '15.9.21.664' from 'D:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin'.
13:38:09 Restoring NuGet package Jenkins.Core.0.2.0.
13:38:09 Adding package 'Jenkins.Core.0.2.0' to folder 'D:\Program Files (x86)\Jenkins\workspace\test\packages'
13:38:09 Added package 'Jenkins.Core.0.2.0' to folder 'D:\Program Files (x86)\Jenkins\workspace\test\packages'
13:38:09
13:38:09 NuGet Config files used:
13:38:09 D:\Program Files (x86)\Jenkins\workspace\test\.nuget\NuGet.Config
13:38:09 C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config
13:38:09 C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config
13:38:09
13:38:09 Feeds used:
13:38:09 C:\WINDOWS\system32\config\systemprofile\.nuget\packages\
13:38:09 http://127.0.0.1:10080/nuget
13:38:09 https://api.nuget.org/v3/index.json
13:38:09 C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\
13:38:09
13:38:09 Installed:
13:38:09 1 package(s) to packages.config projects
13:38:09
13:38:09 D:\Program Files (x86)\Jenkins\workspace\test>exit 0
13:38:09 Path To MSBuild.exe: C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe
13:38:09 Executing the command cmd.exe /C " "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" /t:Build /p:Configuration=Release JenkinsTest/JenkinsTest.csproj " && exit %%ERRORLEVEL%% from D:\Program Files (x86)\Jenkins\workspace\test
13:38:09 [test] $ cmd.exe /C " "C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" /t:Build /p:Configuration=Release JenkinsTest/JenkinsTest.csproj " && exit %%ERRORLEVEL%%
結語
通過N次嘗試,最終完成了.Net開發下Jenkins進行持續集成。總結起來如下:
- 安裝Java環境,由於我本地已有java環境,因此該步驟跳過。
- 安裝MSBuild,由於我本地已安裝過VS,因此該步驟跳過。
- 下載Nuget,由於我本地已安裝VS,同時已安裝過Nuget,因此該步驟跳過。
- 安裝Jenkins,並安裝MSbuild插件。
- 修改Jenkins的MSBuild插件的配置。
- 新建一個工程,修改配置
- 選擇源碼管理,我本地是SVN,因此選擇SVN(增加登錄憑據)
- 增加windows批處理腳本用於Nuget下載庫包。(在Nuget.Config中增加自己的包服務地址)
- 增加MSBuild編譯VS的項目
通過以上步驟,基本就完成了自動編譯的功能。但是光編譯還是不夠的,最終還要完成自動跑單元測試,下一篇博客再進行研究。
參考文檔
- Jenkins部署.net自動化構建
- 為 Jenkins 配置 .NET 持續集成環境
- 淺談.net jenkins svn下自動化集成環境安裝 搭建 配置
- jenkins持續集成原理
- Jenkins結合.net平台工具之Nuget
- Make Jenkins aware of custom NuGet Package Source
微信掃一掃二維碼關注訂閱號傑哥技術分享
本文地址:https://www.cnblogs.com/Jack-Blog/p/10291612.html
作者博客:傑哥很忙
歡迎轉載,請在明顯位置給出出處及鏈接

