窮人的持續集成與持續交付

jopen 8年前發布 | 29K 次閱讀 持續交付 持續集成 項目構建

基于免費服務的持續交付環境

本文將使用一些免費的服務來為你的項目搭建 持續交付 平臺,這些服務包括

  • 持續集成環境
  • 持續部署環境
  • 服務端應用托管

以及一些可以用于本地開發使用的開源工具如:

除此之外,我們在過程中編寫的腳本還可以用以本地構建,如果你的團隊中正好已經有CI工具/CD工具,將這些腳本集成進去也是一件非常容易的事情。

背景知識

軟件的度量

傳統的管理方法論,在軟件開發這個領域來說基本上是不工作的。軟件項目的不確定性使得人們畏懼,管理者希望通過一些數字,指標來讓自己感到某種虛幻的“掌控感”。軟件行數,測試覆蓋率,代碼故障率等數字的名聲基本上已經很糟了,經常有人拿來諷刺那些追求虛幻掌控感的“領導”。

但是有一個數字,即使最頑固的“自由主義者”也會認為是有意義的,那就是周期時間(cycle time)。簡而言之,就是一個需求從產生到最終上線所需要的時間。其中包括了需求分析,設計,編碼,測試,部署,運維等活動,可能還會包含后續的監控。

其實不論是瀑布模型,還是迭代開發的方式,或者其他的方法論,周期時間的縮短都是至關重要的。而具體到周期內,單純的開發時間變長或者測試時間變長都無關緊要。比如項目A的開發時間是測試時間的2倍,項目B則恰恰反過來,這并不能說A做的比B好,真正有意義的是A的周期時間是否比B更短。

單純改善項目過程中的某一個階段的時間,可能并不能達到預期的目的。局部優化并不一定會帶來全局的優化。換言之, 通過某些策略來提高軟件測試的效率未必能減少周期時間! 。

持續交付

傳統情況下,企業要進行軟件開發,從用戶研究到產品上線,其中會花費數月,甚至數年(我的一位印度同事給我聊起過,他的上家公司做產品,從版本啟動到版本上線需要整整兩年時間!)。而且一旦軟件需求發生變更,又有需要數月才能將變更發布上線。除了為變更提交代碼外,還有很多額外的回歸測試,發布計劃,運維部門的進度等等。而市場機會千變萬化,在特定的時間窗口中,企業的競爭者可能早已發布并占領了相當大的市場份額。

在軟件工程領域,人們提出了持續交付(continuous delivery)的概念,它旨在減少周期時間,強調在任何時刻軟件都處于可發布狀態。采用這種實踐,我們可以頻繁,快速,安全的將需求的變化發布出來,交由真實世界的用戶來使用,在為用戶帶來價值的同時,我們也可以快速,持續的得到反饋,并激勵新的變化產生(新的商業創新,新的模式等)。

持續交付包含了自動化構建,自動化測試以及自動化部署等過程,持續改進開發流程中的問題,并促進開發人員,測試人員,運維人員之間的協作,團隊可以在分鐘級別將變更發布上線。

持續交付相關技術及實踐

  • 版本控制(配置管理)
  • 持續集成CI
  • 自動化測試
  • 構建工具及構建腳本
  • 部署流水線

團隊通過版本控制來進行協作,所有的代碼會在持續集成環境中編譯,代碼靜態檢查/分析,自動化測試(還可能產生報告等)。除此之外,CI還還需要有自動化驗收測試,自動化回歸測試等。

持續交付則更進一步,它將環境準備,持續集成,自動化部署等放在了一起。通過全自動(有些過程可以設置為手動,比如發布到產品環境)的方式,使得軟件可以一鍵發布。如果上線后發現嚴重defect,還支持一鍵回滾的機制(其實就是將之前的一個穩定版本做一次發布,由于發布流程已經經過千錘百煉,所以發布本身就變得非常輕松,安全)

實例

我在 《前后端分離了,然后呢?》 這篇文章中,提到了一個叫做 bookmarks 的應用,這個應用是一個前后端分離的非常徹底的應用。

我們這里會再次使用這個應用作為實例,并采用不同的兩個免費服務( travis-cisnap-ci )來完成 持續部署 環境的搭建。

服務器端

bookmarks-server 是一個基于 spring-boot 的純粹的 API ,它可以被打包成一個 jar 包,然后通過命令行啟動運行。在本文中,我們我們將會將這個server部署到 heroku 平臺上。

首先需要定義一個 Procfile ,這個是我們應用的入口, heroku 根據這個文件來明確以何種方式來啟動我們的應用:

web: java -Dserver.port=$PORT -jar build/libs/bookmarks-server-0.1.0.jar --spring.profiles.active=staging

由于我們在本地使用的使用 mysql ,而 heroku 默認的是 postgres 數據庫,因此需要在 application.yml 中額外配置

spring:
  profiles: staging

  datasource:
    driverClassName: org.postgresql.Driver
    url: ${JDBC_DATABASE_URL}
    username: ${DATABASE_USER}
    password: ${DATABASE_PASS}

  jpa:
    database_platform: org.hibernate.dialect.PostgreSQLDialect
    hibernate:
      ddl-auto: update

有了這些配置后,我們需要創建一個 heroku 應用:

$ heroku create
Created http://quiet-atoll-8237.herokuapp.com/ | git@heroku.com:quiet-atoll-8237.git

創建之后,我們可以在界面上對這個應用進行一些配置(當然,也可以通過命令行,具體參看 heroku help )。為了支持數據庫,需要為我們的應用添加一個 postgres 的AddOn。添加之后, heroku 會為我們提供一個 postgres 的連接地址,格式大概是這樣:

postgres://username:password@host:port/database

然后我們需要在 Heroku 的配置界面中配置一些環境變量:

這樣,當應用部署到 Heroku 上之后,我們的應用就可以讀到這些配置了(注意 application.yml 中的環境變量 JDBC_DATABASE_URL )。

搭建持續集成環境

持續集成環境,這里我們選用最簡單的 travis-ci ,它可以很容易的與 github 集成。

  • 在項目X中定義一個 .travis.yml 的文件
  • 將你的代碼push到github上
  • 綁定github帳號到 travis
  • 在 travis 中啟用項目X

這個 .travis.yml 因項目而異,我們這里的項目是 spring-boot ,所以只需要指定 java 即可:

language: java

如果是 java 項目,并且項目中有 build.gradle , travis-ci 會自動執行 gradle check 任務。

自動化部署

當CI運行成功之后,我們需要 travis-ci 幫我們將應用程序發布到 heroku 上,這時候需要做一些修改。最簡單的方式是直接安裝 travis-ci 的命令行工具到本地:

$ gem install travis -v 1.8.0 --no-rdoc --no-ri

然后通過 heroku 的 auth:token 命令獲得 heroku 的token,在加密并寫入 .travis.yml :

$ heroku auth:token
00xxxxxxxxxxxxx55d11dbd0cxxxxxxxxxxfe067

$ travis encrypt 00xxxxxxxxxxxxx55d11dbd0cxxxxxxxxxxfe067 --add

當然可以合并為一條命令:

$ travis encrypt $(heroku auth:token) --add

將加密過的token存入 .travis.yml 文件。最后的結果大致如下:

language: java
deploy:
  provider: heroku
  api_key:
    secure: ...
  app: quiet-atoll-8237

注意此處的 app ,正是我們的App的名字。另外,還需要給 build.gradle 添加一個名叫 stage 的task, travis 在deploy時需要這個 task :

task stage {
    dependsOn build
}

這樣,我們只需要在本地的一個提交,一切都會自動化起來:

  • travis會執行 gradle check
  • gradle check 會編譯并運行自動化測試
  • travis 會部署應用到 heroku 上
  • heroku 會自動重啟服務

我們可以在本地進行簡單的測試(注意此處我們的 staging 環境的URL):

$ curl https://quiet-atoll-8237.herokuapp.com/api/feeds -s | jq .
[
  {
    "id": 1,
    "url": "http://icodeit.org/2016/01/how-to-summarize-privious-project/",
    "title": "如何持久化你的項目經歷",
    "author": "icodit.org",
    "summary": "通常來說,下項目總是一件比較高興的事(大部分團隊還會一起吃個飯慶祝一下)。",
    "publishDate": "2016-01-07"
  },
  {
    "id": 2,
    "url": "http://icodeit.org/2015/11/get-started-with-reflux/",
    "title": "你為什么應該試一試Reflux?",
    "author": "icodit.org",
    "summary": "React在設計之初就只關注在View本身上,其余部分如數據的獲取,事件處理等,全然不在考慮之內。",
    "publishDate": "2016-01-09"
  }
]

完整的 代碼在這里

其他

CI monitor

node-build-monitor 是一個非常容易配置,使用的CI monitor,我們只需要進行簡單地配置,就可以將 travis 的狀態可視化出來

{
  "monitor": {
    "interval": 2000,
    "numberOfBuilds": 12,
    "debug": true
  },
  "services": [
    {
      "name": "Travis",
      "configuration": {
        "slug": "abruzzi/bookmarks-server"
      }
    }
  ]
}

不過這個工具會在有網絡異常時自動終止,我們可以通過一個簡單的腳本來在它終止時自動重啟:

#!/bin/bash

until node app/app.js
do
    echo "restarting..."
done

小結

通過 travis 和 heroku 這樣的免費服務,我們就可以輕松的將自己的項目做到持續集成+持續交付。我們后端的服務相對來說是比較容易的,但是涉及到一個前后端分離的架構,如何做到靜態內容的托管,打包,部署,并和后端API集成起來,我會在下一篇文章中詳細解釋。

來自: http://icodeit.org/2016/01/a-poor-mans-cd-part1/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!