+86 135 410 16684Mon. - Fri. 10:00-22:00

使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成持續整合與持續交付的開發流程

使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成持續整合與持續交付的開發流程

使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成持續整合與持續交付的開發流程

DevOps:持續整合&持續交付(Docker、CircleCI、AWS)

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4b67777732504e5234526f2f5654704f4974746d6452492f41414141414141416b62772f78586c35317a477a6c36512f73313630302f636f7665722e706e6

這篇文章將一步一步介紹如何使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成持續整合持續交付的開發流程。

前言

什麼是持續整合&持續交付?

持續整合&持續交付(Continuous Integration & Continous Delivery),簡稱 CI & CD,具體介紹可以參考「山姆鍋對持續整合、持續部署、持續交付的定義」這篇文章。

簡單來說就是盡量減少手動人力,將一些日常工作交給自動化工具。例如:環境建置、單元測試、日誌紀錄、產品部署。

我使用了哪些工具?

看完這篇你可以學到什麼?

  • 瞭解 GiHub 的工作流程(GitHub Flow),利用 Pull Request 以及分支來完成代碼審查(Code Review)與環境配置,例如:開發版(development)、測試版(testing/QA)、上線產品(staging/production)。
  • 使用 Docker,統一開發者、測試人員、以及產品的執行環境。
  • 使用 EB CLI 將應用程式部署到 AWS Elastic Beanstalk 平台上。
  • 使用 CircleCI 將以上工作全部自動化。偵測 GitHub 分支上的程式碼,若有更新則觸發:建置 Docker 環境、單元測試、然後自動部署新版本到 AWS EB。
  • 使用 Slack,讓團隊成員能夠即時接收 GitHub 與 CircleCI 每一項動作的通知。

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d61794d50555969704159492f565470505754456c6a58492f41414141414141416b62382f767077352d77722d426a512f73313630302f73657175656e63652d6469616772616d2e706e6

內容大綱

Node.js

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d47567335784c4a783937632f56547051765544786244492f41414141414141416b63592f4d706c307775326e41366b2f73313630302f6e6f64652e706e6

安裝:

這篇文章以 Node.js 的應用程式作為範例,其他語言(Ruby on Rails、Python、PHP)也同樣適用此工作流程。

建立新專案

  1. 建立一個專案資料夾(這裡以 hello-ci-workflow 為例):
$ mkdir hello-ci-workflow
$ cd hello-ci-workflow

在本地端執行 Node.js

  1. 初始化 Node.js 的環境,填寫一些資料之後會在目錄下產生一個 package.json 的檔案:
$ npm init
  1. 安裝 Node.js 的 web framework,以 Express 為例:
$ npm install express --save

--save: 寫入 package.json 的 dependencies。

  1. 完成之後,package.json 大概會長這個樣子:
// package.json
{
  "name": "hello-ci-workflow",
  "main": "index.js",
  "dependencies": {
    "express": "^4.12.3"
  },
  "scripts": {
    "start": "node index.js"
  }
}
  1. index.js 裡寫一段簡單的 Hello World! 的程式:
// index.js
var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

var server = app.listen(3000, function () {

  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);

});
  1. 執行 npm startnode index.js
$ npm start
  1. 打開瀏覽器 http://localhost:3000 看結果:

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e6

在本地端測試 Node.js

  1. 安裝 Node.js 的單元測試,以 Mocha 為例:
$ npm install mocha --save-dev

--save-dev: 寫入 package.json 的 devDependencies,正式上線環境不會被安裝。

// package.json
{
  "name": "hello-ci-workflow",
  "main": "index.js",
  "dependencies": {
    "express": "^4.12.3"
  },
  "devDependencies": {
    "mocha": "^2.2.4"
  },
  "scripts": {
    "start": "node index.js"
  }
}
  1. 根目錄 test 資料夾,並新增一個測試腳本 test.js
$ mkdir test
$ cd test
$ touch test.js
  1. 加入一筆錯誤的測試 assert.equal(1, [1,2,3].indexOf(0))
// test/test.js
var assert = require("assert")
describe('Array', function(){
  describe('#indexOf()', function(){
    it('should return -1 when the value is not present', function(){
      assert.equal(1, [1,2,3].indexOf(0));
    })
  })
})
  1. 執行 mocha 測試:
$ ./node_modules/.bin/mocha


  Array
    #indexOf()
      1) should return -1 when the value is not present


  0 passing (9ms)
  1 failing

結果顯示 1 failing,測試沒通過,因為 [1,2,3].indexOf(0) 回傳的值不等於 -1

  1. test.js 的測試修正:
// test/test.js
assert.equal(-1, [1,2,3].indexOf(0));
  1. 再次執行 mocha 測試:
$ ./node_modules/.bin/mocha


  Array
    #indexOf()
      ✓ should return -1 when the value is not present


  1 passing (6ms)

結果顯示 1 passing,通過測試。

GitHub

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736142616235336e3135772f56547051765149376636492f41414141414141416b63552f46703865346161467938452f73313630302f6769746875622e706e6

安裝:

帳號:

  1. 初始化 git 環境:
$ git init .
  1. 輸入 git status 會顯示目前哪些檔案有過更動:
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

  index.js
  node_modules/
  package.json
  test/
  1. node_modules 加到 .gitignore 黑名單,因為這個資料夾是由 npm install 自動產生的,不需要放到 GitHub 上:
# .gitignore

# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
  1. 將更動 commit:
$ git add .
$ git commit -m "first commit"
  1. 打開 GitHub,新增一個 repository:

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d2d4a2d36343130534e74342f5654705566423150452d492f41414141414141416b65732f4e5a4476386d436e6661342f73313630302f30322e706e6

  1. 輸入 repository 的名稱,以 hello-ci-workflow 為例:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4a7973694f3946663435492f56547055664166674532492f41414141414141416b65302f42465947614d5a394d55302f73313630302f30332e706e6

  1. 使用 git remote add 將新創建的 GitHub repository 加入到 remote:
$ git remote add origin https://github.com/<USER_NAME>/hello-ci-workflow.git

<USER_NAME> 改成自己的帳號。

  1. 使用 git push 將程式碼傳到 GitHub:
$ git push -u origin master

成功之後前往 https://github.com/<USER_NAME>/hello-ci-workflow 就可以看到剛才上傳的檔案:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4c6642586942516b654e632f56547055666c6e683367492f41414141414141416b65342f634b316c703537725a79632f73313630302f30342e706e6

CircleCI

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d555466506b66356b5171302f56547051753441425969492f41414141414141416b634d2f4d6a6577393739315a7a672f73313630302f636972636c6563692e706e6

帳號:

加入 GitHub repository

  1. 點選左邊欄的 Add Projects 按鈕:

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d37725766746e676c5f53632f56547055663743494b4c492f41414141414141416b66492f67326264753834777a65632f73313630302f30352e706e6

  1. 選擇自己的 GitHub 帳號:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d34376b685743594648766b2f56547055663636374249492f41414141414141416b66412f3230614c6d7a484d6f67512f73313630302f30362e706e6

  1. 搜尋要加入的 GitHub repository,然後點選 Build project 按鈕,以 hello-ci-workflow 為例:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d73444630306c78386361492f565470556e684e6c4739492f41414141414141416b686b2f50425669354952556676452f73313630302f30372e706e6

  1. 完成之後 CircleCI 就會自動執行第一次的建構,不過因為還沒加入測試腳本,所以建構結果會顯示 no test:

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d34364c78483678636f744d2f56547055677335734a56492f41414141414141416b664d2f396b3056394869476b35412f73313630302f30382e706e6

在 CircleCI 測試 Node.js

  1. 在專案根目錄底下建立一個 circle.yml,並加入 mocha test:
# circle.yml
machine:
  node:
    version: 0.10

test:
  override:
    - ./node_modules/.bin/mocha
  1. 完成之後將檔案 push 上 GitHub:
$ git add circle.yml
$ git cimmit "add circle.yml"
$ git push
  1. Push 成功之後,CircleCI 會自動觸發建構和測試:

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d47674d44483277596f5f672f56547055673877733434492f41414141414141416b66552f7a5431686f346c76546d382f73313630302f30392e706e6

  1. 測試通過,建置成功:

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d456c4d57747638537534492f565470556845325f4c4d492f41414141414141416b66592f51346b5a6c3544377172672f73313630302f31302e706e6

代碼審查(Code Review)with GitHub Flow

目前開發中比較常用的 workflow 有 Git flowGitHub flow 兩種,可以參考以下幾篇文章:

Git flow:

GitHub flow:

這裡我們使用 GitHub flow,它的核心精神是:

  • 所有在 master 分支上的程式都一定要是通過測試,可以部署的產品版本。
  • 要開發功能、修復 Bug、做任何事情,都要從 master 開一條新的分支。
  • 隨時 commit 和 push 你的程式碼到 GitHub 上,與大家討論。
  • 功能完成時,使用 pull request 讓大家作 code review。
  • 確認沒問題之後才可以 merge 回 master,並且部屬新版本到線上。

建立一條分支

  1. 為了確保 master 這條主線上的程式碼都是穩定的,所以建議開發者依照不同的功能、建立不同的分支,這裡以 test-github-flow 為例,使用 git branch 新增分支、然後 git checkout 切換分支:
$ git branch test-github-flow
$ git checkout test-github-flow

加入 commits

  1. test.js 裡加入一行錯誤的測試 assert.equal(3, [1,2,3].indexOf(5))
// test/test.js
// ...
assert.equal(3, [1,2,3].indexOf(5));
$ git add test/test.js
$ git commit -m "add a error test case"

新增一個 Pull Request

  1. Push 到 GitHub 的 test-github-flow 分支:
$ git push -u origin test-github-flow
  1. 打開 GitHub 之後,會出現 test-github-flow 分支的 push commits,點選旁邊的 Compare & pull request 按鈕:

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d3358664e484e4a485f76382f56547055694f727a456f492f41414141414141416b66302f6a385665765951437944672f73313630302f31332e706e6

  1. 點選之後會進入 Open a pull request 的填寫頁面,選擇想要 merge 的分支、輸入描述之後,點選 Create pull request 按鈕:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736645574f6e4f665747592f5654705569515a763571492f41414141414141416b66342f65387772416871544736512f73313630302f31342e706e6

檢視&討論你的程式碼

  1. 新增一個 pull request 之後,其他人就會在 GitHub 上出現通知:

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d4f393436777849474c696b2f5654705569393557376e492f41414141414141416b67452f454a354543344f677464732f73313630302f31352e706e6

  1. 點進去之後可以看見相關的 commits 與留言,但是下面有一個紅紅大大的叉叉;因為每次 GitHub 只要有新的 push,就會觸發 CircleCI 的自動建置和測試,並且顯示結果在 GitHub 上:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d76337677694a59344759342f565470556a44714c6777492f41414141414141416b67492f57627850704769395069342f73313630302f31382e706e6

  1. 點選叉叉,前往 CircleCI 查看錯誤原因:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6172664e434532504e6a492f565470556a744b7a7042492f41414141414141416b67512f4a55396f6a63342d5630452f73313630302f31392e706e6

  1. 就會發現剛剛 push 到 test-github-flow 的測試沒通過:

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d432d71756474766c6a556b2f565470556872504b6d6c492f41414141414141416b666f2f664c52495566694b615a772f73313630302f31322e706e6

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d2d49783939655738646e412f56547055687253714a41492f41414141414141416b666b2f30617048456a33685a30632f73313630302f31312e706e6

回到 GitHub,因為測試沒通過,所以審查者不能讓這筆 pull request 被 merge 回 master。

  1. 找到剛剛 commit 的那段程式碼,留言告知請開發者修正錯誤之後,再重新 commit push 上來:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4d466a385073454a2d68672f565470556a3644386c78492f41414141414141416b67592f347a644a76316a417945492f73313630302f32312e706e6

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d7253585f7a6d4c3542386b2f565470556b595f343662492f41414141414141416b67632f6632303541376a445043452f73313630302f32322e706e6

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a5154654271794e446d552f565470556b713566424b492f41414141414141416b676b2f36653653435453784474672f73313630302f32332e706e6

  1. 修正 test.js 的測試腳本:
// test/test.js
// ...
assert.equal(-1, [1,2,3].indexOf(5));
  1. 再次 commit & push:
$ git add test/test.js
$ git commit -m "fix error test case"
$ git push
  1. 回到 GitHub 的 pull request 頁面,可以看到最新一筆的 commit 成功通過 CircleCI 的測試了:

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d773856576934434d51424d2f565470556c5164655878492f41414141414141416b67342f65794f736b3254314e68302f73313630302f32362e706e6

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4b2d71506431356d7049772f565470556b324b6e7356492f41414141414141416b676f2f33744c6b74485a494778772f73313630302f32342e706e6

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d7874335859616c446d6a512f565470556c4a61797749492f41414141414141416b67302f6c306f44385969454b5a592f73313630302f32352e706e6

Merge&部署

  1. 審查之後,確定沒有問題,就可以點選 Merge pull request 的按鈕,將 test-github-flow 的程式碼 merge 回主線 master

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d695a7353466776494b58772f565470556c796e715877492f41414141414141416b68412f4f73723949657778657a492f73313630302f32372e706e6

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d70326731666a5a66416c492f565470556d5070523652492f41414141414141416b68452f3063642d506b63544c30592f73313630302f32382e706e6

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d726a7a37474a7a665a6c412f565470556d6149617a68492f41414141414141416b684d2f744f655937536f325964732f73313630302f32392e706e6

Docker

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a426a6f4a4c4c6a7255302f56547051753752433841492f41414141414141416b63492f6b324e45733437595f4d492f73313630302f646f636b65722e706e6

安裝:

什麼是 Docker?為什麼要用它?

因為 Docker 最近很火,所以網路上不缺關於介紹它的文章,原諒我這裡只稍微提一下:

以往開發人員面對開發環境不同的問題,常常出現「明明在我的電腦上可以跑」的囧境,所以為了解決這類問題,通常會使用虛擬機器(VM)搭配一些工具(VagrantChef)來協助統一開發人員、測試人員、上線產品的執行環境。

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d3564735356592d492d4e512f5654706263466c47564e492f41414141414141416b6b732f4546596f546a6774786d512f73313630302f766d2d76732d646f636b65722e706e6

Docker 也是類似的解決方案,不同於 VM 的是,Docker 運行起來更輕巧、可攜度更高。配置好一份設定之後,就可以讓大家馬上進入開發狀況,減少不必要的環境問題,提升效率。

在 Docker 執行 Node.js

  1. 在專案根目錄底下建立一個 Dockerfile
# Dockerfile

# 從 [Docker Hub](https://hub.docker.com/) 安裝 Node.js image。
FROM node:0.10

# 設定 container 的預設目錄位置
WORKDIR /hello-ci-workflow

# 將專案根目錄的檔案加入至 container
# 安裝 npm package
ADD . /hello-ci-workflow
RUN npm install

# 開放 container 的 3000 port
EXPOSE 3000
CMD npm start
  1. 使用 docker build 建構您的 image:
$ docker build -t hello-ci-workflow .

-t hello-ci-workflow 是 image 名稱。

  1. 使用 docker run 執行您的 image:
$ docker run -p 3000:3000 -d hello-ci-workflow

-d 在背景執行 node,可以使用 docker logs 看執行結果。

  1. 打開瀏覽器 http://localhost:3000 看結果:

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e67

其實每一次都要 buildrun 還蠻麻煩的,推薦可以試試 Docker Compose,用起來有點像 Vagrant

在 CircleCI 測試 Docker

  1. 修改 circle.yml
# circle.yml
machine:
  # 環境改成 docker
  services:
    - docker

dependencies:
  override:
    # 建構方式使用 docker build
    - docker build -t hello-ci-workflow .

test:
  override:
    - ./node_modules/.bin/mocha
    # 使用 curl 測試 docker 是否有順利執行 node
    - docker run -d -p 3000:3000 hello-ci-workflow; sleep 10
    - curl --retry 10 --retry-delay 5 -v http://localhost:3000
  1. Push 更新到 GitHub:
$ git add Dockerfile circle.yml
$ git commit -m "add Docker"
$ git push
  1. 查看 CircleCI 建構&測試結果:

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d694264624c33546b4d624d2f565470556d6d4e4a6d31492f41414141414141416b68552f7473514d642d696b61776f2f73313630302f33302e706e6

AWS Elastic Beanstalk

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d784375514a6233395a32732f56547054317871345a5a492f41414141414141416b656b2f7452452d545f306d7950452f73313630302f6265616e7374616c6b2e706e6

帳號:

安裝:

最後要將程式上線啦!現在 PaaS 雲端平台的選擇非常多(HerokuGoogle App EngineAzureOpenShiftLinode),這裡我選擇 Amazon 推出的 Elastic Beanstalk 當作範例,以下是它的特色:

  • 支援的開發環境多(Java、.NET、PHP、Node.js、Python、Ruby、GO),重點是有支援 Docker!
  • 只需要上傳程式碼,Elastic Beanstalk 即可幫你完成從容量配置、負載均衡(load balancing)、自動擴展(auto scaling)到應用程式的運行狀況監控的部署。

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d455658386f4c4c753958772f565470634c776f385776492f41414141414141416b6b302f487a7555433277365562592f73313630302f6177732d65622e706e6

  1. 初始化 EB 環境:
$ eb init -p docker

-p 可以指定 EB 的應用平台,例如 php 之類;這裡使用 docker。

該命令將提示您配置各種設置。 按 Enter 鍵接受預設值。

如果你已經存有一組 AWS EB 權限的憑證,該命令會自動使用它。 否則,它會提示您輸入 Access key IDSecret access key,必須前往 AWS IAM 建立一組。

  1. 初始化成功之後,可以使用 eb create 快速建立各種不同的環境,例如:development, staging, production;這裡我們以 env-development 為例:
$ eb create env-development

等待 Elastic Beanstalk 完成環境的建立。 當它完成之後,您的應用已經備有負載均衡(load-balancing)與自動擴展(autoscaling)的功能了。

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d555743795f7342635776342f565470556d3276355946492f41414141414141416b68632f727362472d4d5f4958466f2f73313630302f33312e706e6

  1. 使用 eb open 前往目前版本的執行結果:
$ eb open env-development

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d334631586d454e575230732f565470556e587a4e5835492f41414141414141416b68672f4b745671356a6e546c31512f73313630302f33322e706e6

在本地端部署 AWS

  1. 稍微修改 index.js
// index.js
// ...
app.get('/', function (req, res) {
  res.send('Hello env-development!');
});
// ...
  1. 執行 eb deploy 部署新版本到 AWS Elastic Beanstalk:
$ eb deploy env-development

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4f42364d644d6b6c7072672f5654705576712d597963492f41414141414141416b6b4d2f52426973343739336274632f73313630302f33342e706e6

  1. 部署完成之後,執行 eb open 打開網頁:
$ eb open env-development

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d69636e30397167564961512f565470556e7a696a7364492f41414141414141416b68732f664b5541305048435a7a672f73313630302f33332e706e6

env-development 上的應用程式更新完成。

在 CircleCI 部署 AWS

  1. git checkout 將分支切換回主線 master:
$ git checkout master
  1. eb create 新增一組新的環境,作為產品上線用,命名為 env-production
$ eb create env-production
$ eb open env-production

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d636e4f4e667977414d54512f565470556f664a36656a492f41414141414141416b68772f6d304173684841356e524d2f73313630302f33352e706e6

這樣就成功啟動第二組機器了,目前我們有 env-developmentenv-production 兩組環境。

前往 AWS IAM 新增一組帳號給 CircleCI 使用:

  1. Dashboard > Users
  2. Create New Users
  3. Enter User Names: CircleCI > Create
  4. Download Credentials
  5. Dashboard > Users > CircleCI
  6. Attach Pollcy
  7. AWSElasticBeanstalkFullAccess > Attach Pollcy

前往 CircleCI,設定您的 AWS 權限:

  1. Project Settings
  2. Permissions > AWS Permissions
  3. 打開剛才下載的 credentials.csv,輸入 Access Key ID & Secret Access Key
  4. Save AWS keys
  5. .elasticbeanstalk 目錄底下,建立 config.global.yml
# .elasticbeanstalk/config.global.yml
global:
  application_name: hello-ci-workflow
  default_region: us-west-2 # EB 所在的 region,預設是 us-west-2
  1. 修改 circle.yml
# circle.yml
machine:
  # 安裝 eb 需要 python
  python:
    version: 2.7
  services:
    - docker

dependencies:
  pre:
    # 安裝 eb
    - sudo pip install awsebcli
  override:
    - docker build -t hello-ci-workflow .

test:
  override:
    - npm test
    - docker run -d -p 3000:3000 hello-ci-workflow; sleep 10
    - curl --retry 10 --retry-delay 5 -v http://localhost:3000

# 新增一筆部署腳本
deployment:
  production:
    branch: master
    commands:
      - eb deploy env-production

這樣就能在 GitHub 的 master 支線有更新時,觸發 CircleCI 的自動建置、測試、然後部署。

  1. 接下來馬上來試試看流程,修改 index.js
// index.js
// ...
app.get('/', function (req, res) {
  res.send('Hello env-production!');
});
// ...
  1. Commit & Push:
$ git add .
$ git cimmit "test deploy production"
$ git push
  1. 前往 CircleCI 看結果:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d333156596e4b726e5a5f672f565470556f6879575442492f41414141414141416b68342f70696f43374162314765732f73313630302f33362e706e6

  1. 部署成功,eb open 打開瀏覽器來看看結果:
$ eb open env-production

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d456f705179646e757872552f565470556f2d72597873492f41414141414141416b68382f584137736b506b744151412f73313630302f33372e706e6

Slack

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d61367938543547665330492f5654705176365370615f492f41414141414141416b63672f567242693661527a366a632f73313630302f736c61636b2e706e6

帳號:

到這邊其實已經差不多結束了,最後來講講 Slack 吧。

Slack 是一款給團隊使用的即時溝通工具,類似的產品還有 GitterHipChat

至於跟 Skype、Lync 這些軟體有什麼不一樣的地方呢?

它們整合了許多開發工具(GitHub、CircleCI)的服務,例如 GitHub 有新的 push、pull request、issue;CircleCI 的單元測試沒有通過之類的通知,會即時出現在你的團隊的 Slack 上面,既然我們已經將大部分的工作自動化,勢必需要讓相關人員知道這些工具發生了哪些事情,所以使用 Slack 是必要的。

  1. 登入 Slack 頁面
  2. 點選 Configure Integrations > CircleCI

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d64555f5549556e757231412f56547055705245614c4c492f41414141414141416b69492f67613447547853786b36512f73313630302f33382e706e6

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d3148714b4a69353056514d2f565470557056335f504d492f41414141414141416b694d2f665a706d35567a48396f4d2f73313630302f33392e706e6

  1. 選擇要接收 CircleCI 通知的 channel
  2. 點選 Add CircleCI Integration 按鈕
  3. 複製畫面上的 webhook URL

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d764f74756f31593048346b2f5654705571466e7a5177492f41414141414141416b69552f7478366739686f4a6778732f73313630302f34302e706e6

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d63567852614c2d76434f672f5654705572666e4a3354492f41414141414141416b69772f5a796f324762307a79306f2f73313630302f34342e706e6

  1. 返回 CircleCI
  2. 點選 Project settings > Chat Notifications
  3. 貼上將複製的 Webhook URL > Save

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4d34304773505f696b39512f56547055714f41516c67492f41414141414141416b69592f31556f54417573534279342f73313630302f34312e706e6

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d70416e74524e30694252632f565470557171504a6479492f41414141414141416b69732f496e517278586c4a436d302f73313630302f34322e706e6

687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d76337161332d786b3341512f565470557139364f6952492f41414141414141416b696b2f635139436759396c3058772f73313630302f34332e706e6

  1. 類似的步驟,將 GitHub 的通知加入 Slack:

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d5a426d55686a595535586f2f565470557277546e3758492f41414141414141416b6a452f6b617837544264465668412f73313630302f34352e706e6

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6f79475a51765442484c382f56547055723879697935492f41414141414141416b69382f6d595f525561547266706b2f73313630302f34362e706e6

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d706a6d686a6347656268512f5654705573556f547877492f41414141414141416b6a492f30516f6671664e6b5566342f73313630302f34372e706e6

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d315451324558564556764d2f56547055733254327576492f41414141414141416b6a512f526e3561567359665553412f73313630302f34382e706e6

  1. 測試 Slack 通知,是否能夠順利運作,新增一條 test-slack 分支:
$ git branch test-slack
$ git checkout test-slack
  1. 修改 index.js
// index.js
// ...
app.get('/', function (req, res) {
  res.send('Hello Slack!');
});
// ...
  1. Commit & Push:
$ git add index.js
$ git commit -m "index.js: update to test slack"
$ git push -u origin test-slack
  1. CircleCI 通過測試,開啟一個 Pull Request
  2. test-slack merge 回 master,觸發 CircleCI 自動部署

687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d795a376f566f6854426f452f56547055745a6936506e492f41414141414141416b6a672f47345f4464567465444b672f73313630302f35302e706e6

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d43376b5051362d5a376b6f2f56547055743855494d46492f41414141414141416b6a6f2f4a66724a4232554c45486f2f73313630302f35312e706e6

That’s it! On your next build, you’ll start seeing CircleCI build notifications in your Slack chatroom.

結束!可以看見 Slack channel 會顯示每一個步驟的通知過程:

687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4e71796a57466f317245452f56547055744578583343492f41414141414141416b6a592f47537943665037777735732f73313630302f34392e706e6

eb open 打開瀏覽器查看結果,成功自動部署新版本:

$ eb open env-production

687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d654a7367563843654430342f565470557544466c7237492f41414141414141416b6a732f666131785759656b7849732f73313630302f35322e706e6

結語

「書山有路勤為徑,學海無涯苦作舟。」——韓愈

DevOps 的開發流程與工具每天都在不斷推陳出新,請站在巨人的肩膀上、保持一顆「活到老、學到老」的心。

我將這個範例的程式碼放在 GitHub 上,有興趣的人可以參考看看。

文章若有需要改進的地方,還請不吝指教,感激不盡。

參考

北京 上海 天津 重庆 河北 山东 辽宁 黑龙江 吉林 甘肃 青海 河南 江苏 湖北 湖南 江西 浙江 广东 云南 福建 海南 山西 四川 陕西 贵州 安徽 广西 内蒙古 西藏 新疆 宁夏 澳门 香港 台湾