---
title: 'Jenkins 自動化部署'
tags: Jenkins
disqus: hackmd
---
# Jenkins 自動化部署
[TOC]
持續整合、持續交付 (CI/CD) 的觀念在近幾年來越來越被開發人員所重視。透過 CI/CD 概念的實踐,我們可以針對每一次產品的修改,或是週期性地對產品進行各種單元 (unit testing) 或整合測試 (integration testing)。若產品發生狀況,我們可以藉此在第一時間內找出發生問題的最接近位置。同時,我們也可以透過持續整合的工具替我們建置 (build) 服務,並在建置完成後產生報表分析或做自動通知等其他的動作。
而Jenkins就是就是被廣泛使用的工具之一,他同時能提供不同插件來支援不同的專案開發。
此篇是以ios(Xcode)以及gitlab為主。
## 安裝Jenkins
安裝jenkins有兩種方式:
1. 到[Jenkins](https://www.jenkins.io/)官網下載mac版本的jenkins安裝包並安裝
2. 
- 由於jenkins是依賴在Java上,所以需先確保作業系統上是否有安裝Java環境,若無則到[Java環境](https://www.oracle.com/java/technologies/downloads/)下載

安裝完畢後,在terminal輸入來啟動jenkins.
如果是使用 brew install jenkins 則使用以下指令來啟動
```shell=
brew services start jenkins
```
## Jenkins控制台
當terminal中的jenkins啟動後,即可到預設的[區網](http://localhost:8080)(http://localhost:8080)進入控制控制中心
並照著步驟一步一步進行安裝:
▼

▼

之後應該會進入到這個畫面,但先不用理他。

我們先從Dashbaord進入***控制頁*** -> ***管理Jenkins*** -> ***系統設定*** -> ***Jenkins位置***去更變我們的host網址(我目前用本機的ip**http://172.28.15.34:8080/**)
▼

▼

▼

完成後之後進入Jenkins控制台的預設網址就是剛剛設定的網址。
<span style="color:red">如果使用brew安裝的話,可以改port號,但需要多改一個地方</span>
到以下路徑去變更
```shell=
/usr/local/Cellar/jenkins/2.325/homebrew.mxcl.jenkins.plist
```

變更完後記得 restart
``` shell=
brew services restart jenkins
```
## Jenkins外掛套件
Jenkins提供很多不同工具程式的套用(git, gitlab, ruby, xcode等等),因此我們需要去安裝我們專案需要用到的外掛
從***管理Jenkins*** -> ***管理外掛程式*** -> ***可用的去新增***:
▼

▼

▼

1. ***xcode integration***
2. ***gitlab*** 相關全部安裝
3. ***keychains and provisioning profiles management***
4. ***Slack Notification Plugin***
進行安裝,(安裝過後可能會需要重新啟動jenkins,這時只需要把預設網址後面加上/restart便會重啟)
## 自動化作業
的以上作業都順利完成後,你便可以開始建立屬於每個專案的自動化作業:
1. 到Dashbaord選擇新增作業

2. 接著輸入的想要的名稱(做好以專案為主要的名稱,以防混亂)並選擇free-style專案

- 這裡有兩個選擇(free-style & pipeline),兩種都能實現自動化部屬,但因為在測試的過程中發現Xcode在產生ipa檔案時需要一個名為***ExportOptions.plist***的檔案,裡面包括target的設定、certificates 跟 provisioning profile的資料,而pipe在產出的時候並不會自動生產***ExportOptions.plist***供後續使用,必須要先手動新增或archive才行
- 而free-style則沒這個問題,因為他有更多的設定(proviosioning profile, bitcode, symbols等等),所以在執行的過程就會替整個專案產出一份***ExportOpritons.plist***
3. 接著會進入作業的設置頁面
▼

描述舊照自己的意思去填寫
▼

原始碼管理則將專案網址貼上去
Credentials一開始是沒有的所以必須新增:
- 點擊Add
- 點Jenkins後會進到這個畫面
確認一下Kind的位置是"Username with password"
接著在username 跟 password的位置輸入gitlab的帳號密碼
完成後按Add就可以了
- 回的控制頁面,Branches to build則輸入你要build版的Branch(jenkins會依照這條線去拉專案來build),ex: Develop之類的(圖片為測試用先亂填)
- 建制觸發程序為notification通知jenkins進行作業的地方,這裏照圖片進行選擇:
在這層的下面有一個"進階",點開後有兩個地方要設定。
- ***Allowed branches***這邊是要過濾只有哪些branch需要執行jenkins(這邊會有黃色的警告是正常的,不用理會他,他會正常執行。)
- ***Secret token***按"Generate",jenkins便會產生一個token出來,先記著,之後會用到。
- 接著直接到***Build*** -> ***Xcode*** -> ***General build settings*** -> 右下角有個Setting展開 -> 下移到Configuration的區域後:
- ***Scheme***的位置填入xcode專案的scheme名稱
- ***.ipa filename pattern***則輸入希望產出的ipa檔案名稱,其餘照填。
▼打開Code signing & OS X keychain options的 code signing settings:

- 選擇manual signing
- 填入專案使用的provisioning profile的ID以及UUID

- 將"unclock keychain"勾起來並填入
- 密碼為user密碼
▼打開advanced Xcode build options的advanced build settings:

- ***Custom xcodebuild arguments***
- m1環境要特別設定destination

```shell=
-allowProvisioningUpdates
-destination "generic/platform=iOS"
```
## Shell Scripts
以上動作都完成後,接下來就是最重要的部分 - 自動化的scripts
1. ```shell=
xcodebuild -project waninLive.xcodeproj -scheme "waninLive" -sdk iphoneos -configuration Release archive -archivePath "${HOME}/.jenkins/workspace/WaninLive/build/waninLive.xcarchive"
```
- 這段script的作用在透過xcodebuild將project編譯並生產出.xarchive包
- archivePath是目標位置
2. ```shell=
xcodebuild -exportArchive -archivePath "${HOME}/.jenkins/workspace/WaninLive/build/waninLive.xcarchive" -exportPath "${HOME}/.jenkins/workspace/WaninLive" -exportOptionsPlist "${HOME}/.jenkins/workspace/WaninLive/ipa/ExportOptions.plist"
```
- 而這段是讓xcodebuild幫我們導出.ipa文件
3. ```shell=
xcrun altool --upload-app --type ios -f "${HOME}/.jenkins/workspace/WaninLive/ipa/waninLive.ipa" -u "pacify.triplefeet@gmail.com" -p "yvoq-tmzi-lxoj-lzqd"
```
- 這段則是讓xcode幫我們自動上傳.ipa到testflight上面
- 這裏你會發現後面會有類似帳號密碼的東西,沒錯,-u 後面的參數是apple id,但是後面的 -p 則是一個名叫"app 專用密碼"的東西,他可以讓你再透過apple id使用第三方app時,能夠安全的登入帳號,至於如何生產出這組密碼,請參考[apple 專用密碼](https://support.apple.com/zh-tw/HT204397)
## 設定gitlab trigger
當所有的設置都完成後,便是要跟gitlab做一個綁定,這裏的要求是當主線merge request成功後,jenkins便會觸發自動化部屬:
- 先到gitlab的專案頁 -> ***Settings*** -> ***Integrations***

- 將jenkins 剛剛提供的webhook url還有secret token複製貼到integrations 裡的url 跟 secret token的位置
▼

▼

- 接著選擇你要讓gitlab觸發trigger的條件
這裏是要監聽merge request所以我就勾merge request events
最後在點擊add webhook就成功做綁定了。
---
## 綁定Slack通知
上面有提到Jenkins有很多額外的外掛功能可以使用,那我們就來實作一個跟slack同步的外掛,目的是當jenkins部屬成功後,會通知slack做一個訊息發布到群組,這樣就可以讓開發者知道部署的進度是否已經完成。
- 首先我們先去Jenkins CI 下載相關的套件: 我們從slack左邊的列表進去**應用程式**

接著去搜尋**Jenkins CI**並安裝

安裝完畢後輸入目的群組或用戶後點擊***Add Jenkins CI Integrtion***

- 然後你會進入***slack app directory***的設定台

***Post to Channel***的選選擇你要發布的頻道,接著下面有一個token,將他複製起來,之後需要這組token

- 再來,我們一樣到***管理Jenkins*** -> ***管理外掛程式*** -> ***可用的***搜尋**Slack Notification Plugin**並安裝

- 接著回到你的作業的**組態**
你便會回到上面提到的作業列表
- 往下滑你會看到***建置後動作***
並點選***新增建置後動作***
- 這時會有一大堆的選項,請慢慢找到**Slack Notification**並選擇他
- 再來你的列表就會出現slack的相關設定
這裏就依照個人需求去做設定,但有必須將Workspace和Credential設定好。
- 
將團隊子網域複製到下方圖片的Workspace。
- 
- 
這裏你需要創建一個項目為***Secret text***的credential,這是會跟jenkins CI做連線的設定

Secret的地方就將剛剛從**slack app directory**複製下來的token放進去並儲存
- 再來是***Channel/memebr id***,這裏就填入你的slack通知要通知的群組或是用戶

這樣slack notifcation的設定基本上就是完成了~
---
參考文件:
1. [slack notifcation](https://dotblogs.com.tw/stanley14/2018/05/28/jenkins_slack)
2. [slack 控制台](https://newtalk-workspace.slack.com/apps)
3. [jenkins設定](https://www.jianshu.com/p/3b38582d1a59)
4. [shell scripts指令](https://www.jianshu.com/p/88d9f2e57004)