---
# System prepended metadata

title: Jenkins + TFS(Azure DevOps Server) + Windows
tags: [' CD', ' TFS', ' CI', Jenkins, Windows, ' Azure DevOps Server']

---

---
title: Jenkins + TFS(Azure DevOps Server) + Windows
lang: zh
tags: Jenkins, TFS, Azure DevOps Server, Windows, CI, CD
description: The steps of setting up the environment of CI/CD on Windows, using Jenkins and Azure DevOps Server.
image: https://jenkins.io/images/logos/jenkins/jenkins.svg
---

# Jenkins Intro

![Jenkins Logo](https://upload.wikimedia.org/wikipedia/commons/e/e3/Jenkins_logo_with_title.svg)

__Table of Contents__

[TOC]


## 基本流程圖

```flow
s=>start: 本地測試通過
e=>end: 收工
vc=>operation: 版本控制(commit or sign in)
Jen=>inputoutput: Jenkins
build=>condition: Build
test=>condition: Test
deploy=>condition: Deploy
notify=>operation: Notify someone

s->vc->Jen->build->test->deploy->e
build(yes)->test
build(no)->notify
test(yes)->deploy
test(no)->notify
deploy(yes)->e
deploy(no)->notify
```

## Jenkins 簡介
 
Jenkins是一款由Java編寫的開源的持續整合(Continuous Integration，簡稱 CI )工具。

Jenkins提供了軟體開發的持續整合服務。它執行在Servlet容器中（例如Apache Tomcat）。它支援軟體組態管理(SCM)工具(包括AccuRev SCM、CVS、Subversion、Git、Perforce、Clearcase和RTC)，可以執行基於Apache Ant和Apache Maven的專案，以及任意的Shell指令碼和Windows批次處理命令。

可以通過各種手段觸發構建。例如提交給版本控制系統時被觸發，也可以通過類似[Cron](https://zh.wikipedia.org/wiki/Cron)的
機制排程，也可以在其他的構建已經完成時，還可以通過一個特定的URL進行請求。


## 於Windows環境中安裝Jenkins

![Jenkins Logo](https://jenkins.io/images/logos/jenkins/jenkins.svg)

前往[Jenkins官網](https://jenkins.io/)下載Windows版的安裝檔。安裝檔內含有JRE，因此不須額外下載。
按照說明操作，即可完成安裝與初次登入。


## 啟動與開啟Jenkins

Jenkins預設於本機的8080埠，只要開啟網頁瀏覽器，並於網址列輸入` http://localhost:8080 `即可進入。

若尚未啟動Jenkins，則須依照下列指示操作：

1. Jenkins預設安裝位置為` C:\Program Files (x86)\Jenkins `
2. 開啟命令提示字元(CMD)前往該目錄下的` /jre/bin `檔案夾
3. 對根目錄下的 *jenkins.war* 執行` java -jar ../../jenkins.war `指令即可啟動

## 儀表板(Dashboard)介紹

僅針對本篇會使用到的部分大略簡單介紹

### 新增項目 (New Item)

新增工作的頁面，可新增許多不同種類的專案：

- 自由格式專案 (Freestyle project) - 本篇使用的專案
- 管線 (Pipeline) - 通常用於大量建置

安裝額外的外掛(plugin)後，能新增其他對應的工作，例如：Maven project

### 管理Jenkins (Manage Jenkins)

用於系統性的管理項目都會在此操作：

- 設定系統 (Configure Sytem) - 設定語言、E-mail設定、FTP設定
- 全域工具設定 (Global Tool Configuration) - 外掛的設定，例如：MSBuild、MSTest、VSTest
- 管理外掛程式 (Manage Plugins) - 安裝、更新或檢視外掛


## 建置Azure DevOps Server(TFS)上的專案

使用 TFVC 版本管理，利用MSBuild建置 TFS 上的專案

### 前置作業

於管理外掛程式頁面的右上角篩選欄位搜尋，安裝以下外掛：

- [Team Foundation Server Plug-in](https://plugins.jenkins.io/tfs/)
- [MSbuild Plugin](https://plugins.jenkins.io/msbuild/)

勾選需要安裝的項目後，按下**下載並於重新啟動後安裝**即可

#### 設定MSBuild

1. 若已有Visual Studio IDE則可能已安裝於該檔案夾底下；若無，則需前往Microsoft下載MSBuild。
目前[^1]最新版本為[MSBuild 2019](https://visualstudio.microsoft.com/zh-hant/downloads/?q=build+tools "Build Tools for Visual Studio 2019")。
2. 安裝完成後，前往 **Global Tool Configuration** 設定MSBuild
3. 找到MSBuild欄位，點選**新增MSBuild**
4. 輸入之後將顯示於Jenkins內的名稱，像是v15.0、MSBuild v16
5. 最後填上MSBuild.exe所在的資料夾位置即可儲存離開，例如：`"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin"`

### 新增自由格式專案 (Freestyle project)

1. 於**儀表板(Dashboard)** 左側點選 **新增項目(New Item)**
2. 輸入此工作(Job)名稱，選選 **自由格式(Freestyle)** 專案，再點選OK即完成

### 設定專案 (Configuration)

1. 進入專案後，於左側點選 **設定(Configure)**
2. 於**原始碼管理(Source Code Management)** 勾選使用 TFVC，填入相關資料
   | Name           | Value                               |
   | -------------- | ----------------------------------- |
   | Collection URL | http://192.168.xx.xxx:8080/tfs/ABD/ |
   | Project path   | $/Dev/JenkinsTest[^2]               |
   | Credentials    | Manual                              |
3. 於建置欄位新增建置步驟**Build a Visaul Studio project or solution using MSBuild**，選擇之前設定的MSBuild版本，需要建置的檔案，以及額外參數。E.g.,
   | Name                   | Value              |
   | ---------------------- | ------------------ |
   | MSBuild Version        | MSBuilv4           |
   | MSBuild File           | AsyncCoinMiner.sln |
   | Command Line Arguments | /t:restore         |
4. 按下儲存後即完成

### 建置 (Build Now)

1. 設定完成後，於專案頁面左側點選**馬上建置(Build Now)**，即開始運行
2. 結果可於**建置歷程(Build History)** 查看：:red_circle:紅色表示失敗，:large_blue_circle:藍色表示成功
3. 點擊該次建置的**Console Output**可查看詳細內容

## 測試專案

使用VSTest(或MSTest)進行測試作業

### 前置作業

於**管理外掛程式(Manage Plugins)** 頁面安裝[VSTest Runner plugin](https://plugins.jenkins.io/vstestrunner/)

若擁有Visual Studio IDE，則預設安裝於
_%Program Files(x86)%\\Microsoft Visual Studio\\<version>\\<edition>\\common7\\ide\\CommonExtensions\\<Platform | Microsoft>_
，例如：`C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Extensions\TestPlatform\vstest.console.exe`

若無則需安裝[Visual Studio](https://visualstudio.microsoft.com/zh-hant/thank-you-downloading-visual-studio/?sku=Community&rel=16 "Visual Studio 2019 Community")


#### 設定VSTest

1. 進入**Global Tool Configuration** 頁面
2. 於VSTest欄位按下**新增VSTest**
3. 填入名稱與vstest執行檔的路徑，例如：
   | Name           | Value                                                                                                                      |
   | -------------- | -------------------------------------------------------------------------------------------------------------------------- |
   | Name           | VSTest                                                                                                                     |
   | Path to VSTest | "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Extensions\TestPlatform\vstest.console.exe"[^3] |
4. 按下儲存後即完成

### 設定專案 (Configure)

1. 於建置項目按下**新增建置步驟(Add build step)**，並選擇**Run unit tests with VSTest.console**
2. 在Test Files欄位填入需要測試的檔案，e.g., `UnitTestProject1/bin/Debug/netcoreapp3.1/UnitTestProject1.dll`
3. 按下儲存即完成

### 測試結果

建置完成後，即可到**Console Output**查看測試結果


## 專案部署

利用FTP傳送檔案至指定位置

### 前置作業

於管理外掛程式(Manage Plugins)安裝[Publish over FTP](https://plugins.jenkins.io/publish-over-ftp/)

#### 設定FTP Server

1. 前往**設定系統(Configure System)** 頁面
2. 於**Publish over FTP**欄位點選**新增(Add)**
3. 填上所需資料，e.g.,
   | Name             | Value      |
   | ---------------- | ---------- |
   | Name             | Local Host |
   | Hostname         | localhost  |
   | Username         | root       |
   | Password         | pwd        |
   | Remote Directory |            |
4. 可於**進階(Advanced)** 設定埠號、TLS...
5. 按下儲存後即完成

### 設定專案 (Configure)

1. 於**建置後動作(Post-build Actions)** 欄位按下**新增建置後動作(Add post-build action)**
2. 選擇之前設定好的名稱
3. 填入需要上傳的檔案、移除路徑前綴...，e.g.,
   | Name             | Value                                   |
   | ---------------- | --------------------------------------- |
   | Source files     | AsyncCoinMiner/bin/Debug/netcoreapp3.1/ |
   | Remove Prefix    | AsyncCoinMiner/bin/                     |
   | Remote directory | /                                       |
4. 進階(Advanced)內部可設定要排除的檔案...
5. 按下儲存即完成


最後於專案頁面按下**馬上建置(Build Now)** 後即可部署至指定伺服器


## 自動建置

除了手動按下馬上建置(Build Now)以外，還有許多方法能夠讓Jenkins觸發建置行為。
以觸發建置器上的選項來看，目前較常用的有：

- Build when a change is pushed on to TFS/Team Services
- 輪詢 SCM (Poll SCM)

由於第一個方法需要取得 TFS 的權限，因此對於無法輕易取得權限者較不易達成，故本章節將著重在使用輪詢SCM來達成定時檢查是否有新版本需要執行操作。

### Build when a change is pushed on to TFS/Team Services

在TFS的專案設定中，設定服務掛勾(Service Hooks)即可使用

### 輪詢SCM (Poll SCM)

標準Schedule寫法為類似cron的語法，每行5個欄位，使用空格或TAB分格開
```
* * * * *
```

`*` 代表任何符合規範的數字

| 欄位順序 | 意義                                 |
| -------- | ------------------------------------ |
| 1        | 分鐘，0~59                           |
| 2        | 小時，0~23                           |
| 3        | 該月天數，1~31                       |
| 4        | 月份，1~12                           |
| 5        | 星期中的日子，0~7，其中0和7皆為星期天 |

#### 範例

- `H/3 * * * *` - 每三分鐘執行一次
- `13 H/2 * * *` - 每兩個小時的13分執行一次
- `H(0-29)/10 * * * *` - 每10分鐘在每小時的前半小時執行一次(可能是 :04, :14, :24)
- `30 9-18/2 * * 1-5` - 在每個工作天從9點到18點每兩個小時的30分執行一次
- `H H 1,15 2-12 *` - 除了一月以外的每個月1號和15號一天一次

若有需要額外定義時區，須於第一行標註`TZ=Asia/Taipei`


## 建置後通知

建置完成後，通常我們會需要知道結果如何，是否成功。因此讓Jenkins自動在建置結束後發送通知，是最有效益的做法，通常會有以下幾種方法可以達成：

- 寄送E-mail
- Teams通知

### E-mail

1. 在專案設定(Configure)中，新增建置後動作
2. 選擇E-mail通知(E-mail Notification)
3. 填入E-mail信箱並儲存即完成

:::warning
由於防火牆的問題，因此可能會無法成功收發郵件
:::

### Teams

傳送到Teams的頻道通知需要藉由雙方的外掛程式來達成

#### Teams外掛

1. 在要設置通知的團隊頻道上點選右鍵，並選擇連接器
2. 在左上角篩選欄位輸入++Jenkins++即可找到Jenkins並新增
3. 進入設定後，先填入將來要顯示的名稱，並按下建立
4. 接著複製產生的**Webhook URL**，可參考下方說明設定Jenkins的連接器

#### Jenkins外掛

1. 進入管理外掛頁面，安裝[Office 365 Connector](https://plugins.jenkins.io/Office-365-Connector/)
2. 進入想要傳送通知的專案設定(Configure)頁面
3. 於Office 365 Connector按下**新增Webhook**
4. 於URL欄位貼上剛才複製的Webhook URL，並填入顯示名稱
5. 進入進階(Advanced)並勾選所有項目即可收到所有狀態的通知
6. 按下儲存即完成

## 錯誤清單

曾發生的錯誤

- > Querying for remote changeset at '...' as of '...' ...
  > Query returned no result!

  路徑不合法，可能包含URL encoded字元
- > FATAL: com.microsoft.tfs.core.exceptions.TECoreException: 伺服器無法處理要求。 ---> TF400367: 無法執行要求，因為主機類型不符。請檢查任何連接資訊並驗證資訊是否正確。要求是對 Deployment, Organization 執行。
  > com.microsoft.tfs.core.ws.runtime.exceptions.SOAPFault: 伺服器無法處理要求。 ---> TF400367: 無法執行要求，因為主機類型不符。請檢查任何連接資訊並驗證資訊是否正確。要求是對 Deployment, Organization 執行。
  
  TFS 路徑有誤
- > C:\\Program Files (x86)\\Jenkins\\workspace\\AsyncCoinMiner.csproj : error MSB4236: 找不到指定的 SDK 'Microsoft.NET.Sdk'。
  
  套件尚未被還原，建置參數加入`/t:restore`以還原套件
- > C:\\Program Files (x86)\\Jenkins\\workspace\\GithubTest\\samples\\helloworld\\helloworld.csproj(1,1): error MSB4041: 專案的預設 XML 命名空間必須是 MSBuild XML 命名空間。如果使用 MSBuild 2003 格式設計專案，請將 xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 加入至 <Project> 項目。如果是使用舊版的 1.0 或 1.2 格式設計專案，請將專案轉換為 MSBuild 2003 的格式。

  MSBuild版本太舊，無法處理新版 .net core框架，下載最新版本MSBuild以解決問題
  


[^1]: 撰文時間 2020/2/11
[^2]: 須注意不能為中文，或使用URL編碼
[^3]: 由於路徑名稱中有空格，若不加括號可能會造成建置時的指令錯誤

*[CI]: Continuous Integration
*[CD]: Continuous Deployment
*[TFS]: Team Foundation Service (Azure DevOps Server)
*[TFVC]: Team Foundation Version Control
*[SCM]: Software Configuration Management