基於GitLab CI搭建Golang自動構建環境

WilburXu發表於2019-06-19

基於GitLab CI搭建Golang自動構建環境

Golang釋出遇到的問題

對於golang的釋出,之前一直沒有一套規範的釋出流程,來看看之前釋出流程:

方案一

  • 開發者本地環境需要將環境變數檔案改為正式環境配置

  • 編譯成可執行檔案

  • 傳送給運維

  • (運維)將檔案覆蓋為線上

  • (運維)重啟程式

(可謂“又臭又長”)

方案二

  • 開發者講程式碼commit到gitlab上交給運維同學

  • (運維)pull程式碼

  • (運維)編譯成可執行檔案

  • (運維)覆蓋線上檔案

  • (運維)重啟程式

這種對於運維屬於重度依賴,而運維同學又需要去關心程式碼的編譯,增加了運維同學的工作了。

以上兩種方案都是之前專案中發生過的,對於發版來說可謂是一種“噩夢”,易出錯,流程長,運維要是不在根本無法操作。

解決方案

為了解決上面提到的兩種釋出問題,目前我們做了如下的設計方案:

  1. 開發者提交程式碼到GitLab伺服器

  2. 新增一個Tag觸發構建(.gitlab-ci.yml+makefile)

  3. 將構建後的檔案打包新增上版本號(1.0.0+)後推送到版本伺服器

  4. 在Jenkins選擇對應的版本號釋出到指定Web Server上

釋出時,開發只需要編寫“.gitlab-ci.yml”以及makefile對專案進行構建,而運維只需要配置jenkins,將檔案釋出到Web Server上即可,完成了開發和運維的解耦。

什麼是GitLab-CI

GitLab CIGitLab Continuous Integration (Gitlab 持續整合)的簡稱。從 GitLab 的 8.0 版本開始,GitLab 就全面整合了 Gitlab-CI,並且對所有專案預設開啟。只要在專案倉庫的根目錄新增 .gitlab-ci.yml 檔案,並且配置了 Runner(執行器),那麼每此新增新的tag都會觸發 CI pipeline

一些概念

在介紹 GitLab CI 之前,我們先看看一些持續整合相關的概念。

Pipeline

一次 Pipeline 其實相當於一次構建任務,裡面可以包含多個流程,如安裝依賴、執行測試、編譯、部署測試伺服器、部署生產伺服器等流程。 任何提交或者 Merge Request 的合併都可以觸發 Pipeline,如下圖所示:

+------------------+           +----------------+
|                  |  trigger  |                |
|   Commit / MR    +---------->+    Pipeline    |
|                  |           |                |
+------------------+           +----------------+

Stages

Stages 表示構建階段,說白了就是上面提到的流程。 我們可以在一次 Pipeline 中定義多個 Stages,這些 Stages 會有以下特點:

  • 所有 Stages 會按照順序執行,即當一個 Stage 完成後,下一個 Stage 才會開始

  • 只有當所有 Stages 完成後,該構建任務 (Pipeline) 才會成功

  • 如果任何一個 Stage 失敗,那麼後面的 Stages 不會執行,該構建任務 (Pipeline) 失敗

因此,Stages 和 Pipeline 的關係就是:

+--------------------------------------------------------+
|                                                        |
|  Pipeline                                              |
|                                                        |
|  +-----------+     +------------+      +------------+  |
|  |  Stage 1  |---->|   Stage 2  |----->|   Stage 3  |  |
|  +-----------+     +------------+      +------------+  |
|                                                        |
+--------------------------------------------------------+

Jobs

Jobs 表示構建工作,表示某個 Stage 裡面執行的工作。 我們可以在 Stages 裡面定義多個 Jobs,這些 Jobs 會有以下特點:

  • 相同 Stage 中的 Jobs 會並行執行

  • 相同 Stage 中的 Jobs 都執行成功時,該 Stage 才會成功

  • 如果任何一個 Job 失敗,那麼該 Stage 失敗,即該構建任務 (Pipeline) 失敗

所以,Jobs 和 Stage 的關係圖就是:

+------------------------------------------+
|                                          |
|  Stage 1                                 |
|                                          |
|  +---------+  +---------+  +---------+   |
|  |  Job 1  |  |  Job 2  |  |  Job 3  |   |
|  +---------+  +---------+  +---------+   |
|                                          |
+------------------------------------------+

 

什麼是MakeFile

Makefile檔案的作用是告訴make工具需要如何去編譯和連結程式,在需要編譯工程時只需要一個make命令即可,避免了每次編譯都要重新輸入完整命令的麻煩,大大提高了效率,也減少了出錯率。

基本介紹

我們平常很多時候都是直接在命令列輸入go build進行編譯的:

go build .

或者測試使用go run執行專案:

go run main.go

我看有很多大型開源專案都是如下方式 :

make build
# 或者
make install

我們打包執行這個過程,還有一個更加貼切的詞語叫做構建專案。

案例

我們先建立一個新的工程,目錄如下:

  • main.go

  • Makefile

make.go原始碼:

package main
​
import "fmt"
​
func main() {
   fmt.Println("hi, pang pang.")
}

就多了一個Makefile檔案,如果要使用Makefile去構建你專案,就需要在你的專案裡面新建這個Makefile檔案。

這裡我貼一個簡單的Makefile檔案的原始碼:

BINARY_NAME=hello
build:
    go build -o $(BINARY_NAME) -v
    ./$(BINARY_NAME)

解釋下上面各行的意思:

  • 第一行,宣告瞭一個變數BINARY_NAME他的值是hello,方便後面使用

  • 第二行,宣告一個 target,其實你可以理解成一個對外的方法

  • 第三行,這就是這個target被呼叫時執行的指令碼,這行就是build這個專案,編譯後的二進位制檔案放在當前工程目錄下,名字是變數BINARY_NAME的值

  • 第四行,這一行就是直接執行當前目錄下的二進位制檔案

構建

我們開啟我們的終端,直接執行:

make build

將生成一個可執行檔案hello,這就是對Makefile的簡單介紹,具體命令推薦 阮一鋒的Makefile教程

 

部署流程

前面大致介紹了構建自動化構建的用到的一些概念和工具,那麼我們就可以開始我們的部署了。

GitLab Runner

瞭解上面了基本的概念後,那由何人來執行這些任務呢?那就是 GitLab Runner(執行器)

安裝

安裝 GitLab Runner 太簡單了,按照著 官方文件 的教程來就好拉! 下面是 Debian/Ubuntu/CentOS 的安裝方法,其他系統去參考官方文件:

# For Debian/Ubuntu
$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash
$ sudo apt-get install gitlab-ci-multi-runner
​
# For CentOS
$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash
$ sudo yum install gitlab-ci-multi-runner

註冊 Runner

安裝好 GitLab Runner 之後,我們只要啟動 Runner 然後和 CI 繫結就可以了:

  • 開啟你 GitLab 中的專案頁面,在專案設定中找到 runners

  • 執行 sudo gitlab-ci-multi-runner register

  • 輸入 CI URL

  • 輸入 Token

  • 輸入 Runner 的名字

  • 選擇 Runner 的型別,簡單起見還是選 Shell 吧

  • 完成

當註冊好 Runner 之後,可以用 sudo gitlab-ci-multi-runner list 命令來檢視各個 Runner 的狀態:

$ sudo gitlab-runner list
Listing configured runners          ConfigFile=/etc/gitlab-runner/config.toml
my-runner                           Executor=shell Token=cd1cd7cf243afb47094677855aacd3 URL=http://mygitlab.com/ci

.gitlab-ci.yml編寫

before_script:
  - export GOPATH=$GOPATH:/usr/local/${CI_PROJECT_NAME}
  - export # 引入環境變數
  - cd /usr/local/${CI_PROJECT_NAME}/src/${CI_PROJECT_NAME}
  - export VERSION=`echo ${CI_COMMIT_TAG} | awk -F"_" '{print $1}'`
​
# stages
stages:
  - build
  - deploy
# jobs
build-tags:
  stage: build
  script:
    ## 執行makefile檔案
    - make ENV="prod" VERSION=${VERSION}
    - if [ ! -d "/data/code/project_name/tags/${VERSION}" ]; then
      mkdir -p "/data/code/project_name/tags/${VERSION}/";
      fi
    - cd compiler/
    - mv -f project_name.tar.gz /data/code/project_name/tags/${VERSION}/
  only:
    - tags
deploy-tags:
  stage: deploy
  script:
    - cd /data/code/project_name/tags/
    - svn add ${VERSION}
    - svn commit -m "add ${CI_COMMIT_TAG}"
  only:
    - tags

Makefile編寫

export VERSION=1.0.0
export ENV=prod
export PROJECT=project_name
​
TOPDIR=$(shell pwd)
OBJ_DIR=$(OUTPUT)/$(PROJECT)
SOURCE_BINARY_DIR=$(TOPDIR)/bin
SOURCE_BINARY_FILE=$(SOURCE_BINARY_DIR)/$(PROJECT)
SOURCE_MAIN_FILE=main.go
​
BUILD_TIME=`date +%Y%m%d%H%M%S`
BUILD_FLAG=-ldflags "-X main.version=$(VERSION) -X main.buildTime=$(BUILD_TIME)"
​
OBJTAR=$(OBJ_DIR).tar.gz
​
all: build pack
   @echo "\n\rALL DONE"
   @echo "Program:       "  $(PROJECT)
   @echo "Version:       "  $(VERSION)
   @echo "Env:          "  $(ENV)
​
build:
   @echo "start go build...."
   @rm -rf $(SOURCE_BINARY_DIR)/*
   @go build $(BUILD_FLAG) -o $(SOURCE_BINARY_FILE) $(SOURCE_MAIN_FILE)
​
pack:
   @echo "\n\rpacking...."
   @tar czvf $(OBJTAR) -C $(OBJ_DIR) .

執行

完成的部署流程(其實很簡單),然後每次要構建只需要執行:

git commit -a -m "我準備打tag測試啦"
git push
​
## 打tag
git tag -a "1.0.0" -m"1.0.0"
git push origin 1.0.0

那麼在GitLab就會看到:

大功告成,以上!~

 

總結

其實發布流程有無數種,每一個團隊都有合適自己的釋出流程,如果專案小,團隊小,也許手動釋出就足夠了,而對於專案有一定規模的團隊,或許需要更加規範的釋出流程來保障專案的穩定發版。

但是對於專案的發版,每個人都應該要有根據團隊目前現狀去選擇和制定最合適的方案的能力,除此之外,上面提到的工具和語言也是不錯的工具噢!~

 

原文地址

https://github.com/WilburXu/blog/blob/master/other/%E5%9F%BA%E4%BA%8EGitLab%20CI%E6%90%AD%E5%BB%BAGolang%E8%87%AA%E5%8A%A8%E6%9E%84%E5%BB%BA%E7%8E%AF%E5%A2%83.md

相關文章