前端初探 Gitlab CI/CD

渴望做夢發表於2019-09-25

前言

縱觀人類歷史的發展以及三次工業革命,你會發現利用機器來替代部分人力勞動,將重複的工作自動化從而解放生產力都是發展的必然趨勢,在軟體工程領域也不例外,其中 CI/CD 就是其中一項,那麼什麼是 CI/CD 呢,網上的解釋不要太多,這裡我就直接放一幅 Gitlab 官網的工作流程圖好了:

前端初探 Gitlab CI/CD

準備條件

  1. Gitlab runner
  2. .gitlab-ci.yml

Gitlab runner

Gitlab runner 是整個 CI/CD 的執行器,它是執行你寫的 .gitlab-ci.yml 檔案的虛擬機器。
Gitlab runner 分為兩種:

  1. 特定的 runner:只能當前專案使用
  2. 共享的 runner:所有專案都可以使用

找到你的專案在 設定>Runners
你可以看到如下介面:

前端初探 Gitlab CI/CD
左側就是特定的 runners 右側就是共享的 runners,只要確保有其一就行。
關於 runner 的安裝我不想過多贅述,官網寫的很清楚,只要按照步驟一步一步搭建就好了。

.gitlab-ci.yml

當你有了 runner 就可以開始著手寫 .gitlab-ci.yml 檔案了,.gitlab-ci.yml 檔案是對於整個 CI/CD 流程的描述檔案,它告訴 runner 應該怎樣執行具體的操作。
在具體介紹配置之前,我想先明確整個 .gitlab-ci.yml 裡面的幾個重要名詞:

  1. job: job 是整個 CI/CD 的核心單元,它定義了在什麼條件下應該執行什麼任務,每個 job 都是相互隔離的。
  2. script: job 下的屬性,用於描述 job 要執行的任務。
  3. stages: 定義 job 的分組,不同 job 可以所屬於不同的階段,一共有三個階段可供選擇:test build deploy,stage 的執行是按順序的,但是 stage 下面的 job 是並行執行的,只有前一個 stage 執行成功才會執行下一個 stage,一旦上一個 stage 中任何一個 job 執行失敗都會導致整個流水線失敗。
  4. pipeline: 上面的整個流程就是一個流水線。

下面是我的一個前端專案的 .gitlab-ci.yml 檔案,以它來作為示例:

image: node:10.13
      
stages:
  - test
  - build
  - deploy
  
cache:
  paths:
    - node_modules/
    
before_script:
  ## set proxy
  - export http_proxy=http://10.2.3.63:3128/
  - export https_proxy=http://10.2.3.63:3128/

test:
  stage: test
  tags:
    - sams
  script:
    - npm install --no-optional --registry=https://registry.npm.taobao.org
    - npm run lint
  only:
    - master
    - dev

build:
  stage: build
  tags: 
    - sams
  script:
    - npm run build
  artifacts:
    paths:
      - $SOURCE_DIR
    expire_in: 2 mins
  only:
    - master

deploy:
  stage: deploy
  tags: 
    - sams
  before_script:
    ## set debian mirros
    - echo 'deb http://mirrors.aliyun.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list
    - echo 'deb-src http://mirrors.aliyun.com/debian/ stretch main non-free contrib' >> /etc/apt/sources.list
    - echo 'deb http://mirrors.aliyun.com/debian-security stretch/updates main' >> /etc/apt/sources.list
    - echo 'deb-src http://mirrors.aliyun.com/debian-security stretch/updates main' >> /etc/apt/sources.list
    - echo 'deb http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib' >> /etc/apt/sources.list
    - echo 'deb-src http://mirrors.aliyun.com/debian/ stretch-updates main non-free contrib' >> /etc/apt/sources.list
    - echo 'deb http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib' >> /etc/apt/sources.list
    - echo 'deb-src http://mirrors.aliyun.com/debian/ stretch-backports main non-free contrib' >> /etc/apt/sources.list
    ## Using SSH keys with GitLab CI/CD
    ## https://docs.gitlab.com/ee/ci/ssh_keys/README.html
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - scp -r $SOURCE_DIR $DEPLOY_SERVER_USER@$DEPLOY_SERVER_IP:$TARGET_DIR
  only:
    - master
  environment: test
複製程式碼

全域性配置

  • image: 要使用的 docker 映象它會根據你寫的映象名從 docker hub 上面拉取映象,因為我們的專案是前端專案,所以這裡配置的映象是 node,最終你的 script 指定的指令碼會跑在 node 的 docker 環境下,這樣就保證你有了必要的環境依賴(node)
  • stages: 定義整個流水線的各個階段,這裡我三個階段都定義了,但是你可以根據你自己專案的實際情況定義,定義好後流水線將按照你定義的順序依次執行。
  • cache: 定義 job 之間要快取的檔案,通常我們都會把專案的安裝依賴作為快取,這樣下一個 job 就不用重新安裝依賴了
  • before_script: 定義所有 job script 執行前需要執行的指令碼,這裡我設定了代理。

job 的配置

  • stage: 定義該 job 所屬的 stage
  • tags: 指定該 job 使用的 runner
  • script: 該 job 需要執行的指令碼
  • only: 該 job 的約束條件,你可以指定該 job 在哪些情況下會觸發,比如只有 master 分支和 develop 分支才會執行 deploy 的 job,與此相對的還有一個 except 屬性表示什麼條件下不執行該 job
  • artifacts: 用於在不同 stage 之間傳遞結果,通用的做法是將 build 階段打包出來的檔案定義為 artifacts,這樣在 deploy 階段就可以直接使用了,這裡你可能會對 artifacts 和 cache 有些搞不清,這裡推薦看官方的說明
  • environment: 用於定義 job 部署的環境,這裡需要結合 Gitlab 專案的 UI 介面,比如這裡我設定的名稱叫 test,每次部署成功之後 test 環境下就會多一個部署條目,你可以重新部署甚至回滾到某個部署,如下圖所示:

前端初探 Gitlab CI/CD

另外 environment 下還有一個 url 屬性可以定義部署到的伺服器地址,這樣你可以在 UI 介面通過點選按鈕直接跳轉到專案,如果你的 Gitlab 低於 8.11 那隻能通過在 UI 介面(上圖)手動配置了。

ssh keys 實現免密登入

一般來講你部署專案的時候不可避免會用到 ssh 協議,但是 ssh 協議需要你手動輸入使用者名稱和密碼,這樣不就無法實現自動化部署了? 別急,Gitlab 已經幫我們想到了這一點,仔細閱讀官網上的 Using SSH keys with GitLab CI/CD 這篇文章你就能找到解決方案,或者參考我的例項程式碼:

## Using SSH keys with GitLab CI/CD
## https://docs.gitlab.com/ee/ci/ssh_keys/README.html
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
複製程式碼

這裡我還是要簡單說一下其實現原理,Gitlab 首先讓你生成一對 ssh 的公鑰和私鑰,在每次執行 CI/CD 時將私鑰(此時已新增到環境變數裡)通過 ssh-add 新增到 ssh-agent 裡面進行管理,並將設定好的 $SSH_KNOWN_HOSTS (裡面就包含了你要 shh 的主機) 也新增到 known_hosts 檔案中,這樣在執行 ssh 命令時遠端機器就能識別你的身份從而實現免密登入,本質上和你本地實現免密登入的道理是一樣的。

其它

環境變數

類似於程式設計中的變數,環境變數可以儲存一些要要變化的或是比較私密的資訊,環境變數配置好後可以通過 $ + 變數名 在 script 裡面進行呼叫

前端初探 Gitlab CI/CD

檢視流水線狀態

在 Gitlab 主頁找到流水線頁籤,開啟之後就能看到所有流水線的執行情況

前端初探 Gitlab CI/CD
點選進入具體的 stage 你可以看到其執行細節,如果失敗也可以重新執行
前端初探 Gitlab CI/CD

參考資料

docs.gitlab.com/ee/ci/READM…

總結

這次也是我初次嘗試使用 Gitlab CI/CD ,每次任務大概執行需要 8 分鐘,如果你像之前手動去做這些工作那你每次都至少需要花費 8 分鐘時間,不要小瞧這 8 分鐘,日積月累也是一筆不小的開支,更重要的是機器很少出錯的,但是人的話就沒法保證了,而且就像我在開篇所說簡單重複性的工作必然會被機器取代,這是不可避免的歷史規律,不管你用不用它,技術的潮流都會不斷向前推動,所以還不如提前擁抱它。
另外此次只介紹了整個 Gitlab CI/CD 功能的冰山一角,Gitlab 還提供很多優秀的功能,比如在 merge request 的時候進行 CI/CD,所以更多的功能還有待挖掘,如果你感興趣可以去官方文件上找尋,如果有什麼不對的地方還請您指正,最後感謝您的閱讀!

相關文章