這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Github和Travis CI的聯(lián)動(dòng)實(shí)現(xiàn)和使用代碼觸發(fā)CI/CD,以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
首先介紹下在本文出現(xiàn)的幾個(gè)比較重要的概念:
函數(shù)計(jì)算(Function Compute):函數(shù)計(jì)算是一個(gè)事件驅(qū)動(dòng)的服務(wù),通過(guò)函數(shù)計(jì)算,用戶無(wú)需管理服務(wù)器等運(yùn)行情況,只需編寫代碼并上傳。函數(shù)計(jì)算準(zhǔn)備計(jì)算資源,并以彈性伸縮的方式運(yùn)行用戶代碼,而用戶只需根據(jù)實(shí)際代碼運(yùn)行所消耗的資源進(jìn)行付費(fèi)。函數(shù)計(jì)算更多信息參考。
Funcraft:Funcraft 是一個(gè)用于支持 Serverless 應(yīng)用部署的工具,能幫助您便捷地管理函數(shù)計(jì)算、API 網(wǎng)關(guān)、日志服務(wù)等資源。它通過(guò)一個(gè)資源配置文件(template.yml),協(xié)助您進(jìn)行開發(fā)、構(gòu)建、部署操作。Fun 的更多文檔參考。
OSS: 對(duì)象存儲(chǔ)。海量、安全、低成本、高可靠的云存儲(chǔ)服務(wù),提供99.9999999999%的數(shù)據(jù)可靠性。使用RESTful API 可以在互聯(lián)網(wǎng)任何位置存儲(chǔ)和訪問(wèn),容量和處理能力彈性擴(kuò)展,多種存儲(chǔ)類型供選擇全面優(yōu)化存儲(chǔ)成本。
ROS:資源編排(ROS)是一種簡(jiǎn)單易用的云計(jì)算資源管理和自動(dòng)化運(yùn)維服務(wù)。用戶通過(guò)模板描述多個(gè)云計(jì)算資源的依賴關(guān)系、配置等,并自動(dòng)完成所有資源的創(chuàng)建和配置,以達(dá)到自動(dòng)化部署、運(yùn)維等目的。編排模板同時(shí)也是一種標(biāo)準(zhǔn)化的資源和應(yīng)用交付方式,并且可以隨時(shí)編輯修改,使基礎(chǔ)設(shè)施即代碼(Infrastructure as Code)成為可能。
CI/CD: CI/CD 是一種通過(guò)在應(yīng)用開發(fā)階段引入自動(dòng)化來(lái)頻繁向客戶交付應(yīng)用的方法。CI/CD 的核心概念是持續(xù)集成、持續(xù)交付和持續(xù)部署。
本文打算以一個(gè)簡(jiǎn)單的函數(shù)計(jì)算項(xiàng)目為例,在此基礎(chǔ)上編寫測(cè)試用例,進(jìn)行配置,讓其支持 CI/CD 工作流程。實(shí)現(xiàn)如下四個(gè)小目標(biāo):
這里以大家熟悉的 Github 倉(cāng)庫(kù)為例,并結(jié)合 Travis CI 。當(dāng)用戶往示例項(xiàng)目 push 或者 PR(Pull Request)時(shí),會(huì)自動(dòng)觸發(fā) Travis CI 的工作任務(wù),進(jìn)行單元測(cè)試、構(gòu)建打包和部署發(fā)布。
示例項(xiàng)目地址為:https://github.com/vangie/tz-time ,該項(xiàng)目是基于 FC Http trigger 實(shí)現(xiàn)的簡(jiǎn)單 web 函數(shù),訪問(wèn)放函數(shù)是會(huì)返回指定時(shí)區(qū)的當(dāng)前時(shí)間。項(xiàng)目目錄結(jié)構(gòu)如下
tz-time
├── .funignore
├── .travis.yml
├── Makefile
├── bin
│ ├── delRosStack.sh
│ ├── deployE2EStack.sh
│ └── waitForServer.sh
├── deploy.log
├── index.e2e-test.js
├── index.integration-test.js
├── index.js
├── index.test.js
├── jest.config.e2e.js
├── jest.config.integration.js
├── package-lock.json
├── package.json
└── template.yml
部分文件作用介紹:
.funignore
- Funcraft 部署時(shí)忽然的文件清單.travis.yml
- Travis CI 配置文件index.js
- 函數(shù)入口文件測(cè)試通常非常如下三類:?jiǎn)卧獪y(cè)試、集成測(cè)試和 E2E 測(cè)試。在函數(shù)計(jì)算場(chǎng)景下,這三類測(cè)試可以通過(guò)如下方法實(shí)現(xiàn)。
fun local invoke/start
模擬運(yùn)行函數(shù)本例子只實(shí)現(xiàn)了單元測(cè)試,集成測(cè)試和 E2E 測(cè)試對(duì)于 travis 示例來(lái)說(shuō)觸發(fā)方法類似,實(shí)現(xiàn)方法可以參見上面的方法提示進(jìn)行配置。
FC 函數(shù)的單元測(cè)試和普通的函數(shù)并無(wú)二致。采用熟悉的單元測(cè)試框架即可,本例中使用了 jest 進(jìn)行測(cè)試。下面看看一個(gè)測(cè)試用例的代碼片段
jest.mock('moment-timezone');
const { tz } = require('moment-timezone');
const { handler } = require('./index');
const EXPECTED_DATE = '2018-10-01 00:00:00';
const TIMEZONE = 'America/New_York';
describe('when call handle', () => {
it('Should return the expected date if the provied timezone exists', () => {
const mockReq = {
queries: {
tz: TIMEZONE
}
}
const mockResp = {
setHeader: jest.fn(),
send: jest.fn()
}
tz.names = () => [TIMEZONE];
tz.mockImplementation(() => {
return {
format: () => EXPECTED_DATE
}
})
handler(mockReq, mockResp, null);
expect(mockResp.setHeader.mock.calls.length).toBe(1);
expect(mockResp.setHeader.mock.calls[0][0]).toBe('content-type');
expect(mockResp.setHeader.mock.calls[0][1]).toBe('application/json');
expect(mockResp.send.mock.calls.length).toBe(1);
expect(mockResp.send.mock.calls[0][0]).toBe(JSON.stringify({
statusCode: '200',
message: `The time in ${TIMEZONE} is: ${EXPECTED_DATE}`
}, null, ' '));
});
});
通過(guò) jest.mock 對(duì) moment-timezone 進(jìn)行 mock,讓 tz 被調(diào)用的時(shí)候返回預(yù)先設(shè)定好的值,而不是一個(gè)動(dòng)態(tài)變化的時(shí)間。
通常該類單元測(cè)試分為三步:
如果依賴包不存在原生依賴(依賴 linux 下的可執(zhí)行文件或者 so 庫(kù)文件)的使用 npm test 觸發(fā)測(cè)試即可,如果有原生依賴,那測(cè)試需要跑在 fun 提供的 sbox 模擬環(huán)境里,使用如下命令觸發(fā)
fun install sbox -f tz-time --cmd 'npm install'
本例子中的集成測(cè)試會(huì)借助 fun local start 命令把函數(shù)在本地啟動(dòng)起來(lái),由于函數(shù)配置了 http trigger,所以可以通過(guò) http 請(qǐng)求調(diào)用函數(shù)。
集成測(cè)試我們還是才是 jest 框架進(jìn)行編寫,為了區(qū)別于單元測(cè)試文件 *.test.js
,集成測(cè)試文件使用 .integration-test.js
文件后綴。為了讓 jest 命令獨(dú)立的跑集成測(cè)試用例而不是和單元測(cè)試混和在一起,需要編撰如下文件 jest.config.integration.js
module.exports = {
testMatch: ["**/?(*.)integration-test.js"]
};
然后在 package.json 中配置 scripts
"scripts": {
"integration:test": "jest -c jest.config.integration.js"
}
于是可以通過(guò)執(zhí)行 npm run integration:test 來(lái)執(zhí)行集成測(cè)試。
然后在此基礎(chǔ)上在 Makefile 中添加 integration-test 目標(biāo):
funlocal.PID:
fun local start & echo $$! > $@
integration-test: funlocal.PID
bin/waitForServer.sh http://localhost:8000/2016-08-15/proxy/tz-time/tz-time/
npm run integration:test
kill -2 `cat $<` && rm $<
integration-test 目標(biāo)依賴 funlocal.PID 目標(biāo),后者負(fù)責(zé)啟動(dòng)一個(gè) fun local 進(jìn)程,該進(jìn)程會(huì)在本地啟動(dòng) 8000 端口。解讀一下上面的 Makefile 代碼
fun local start & echo $$! > $@
啟動(dòng) fun local 進(jìn)程,并將進(jìn)程 PID 寫入到目標(biāo)同名文件 funlocal.PIDbin/waitForServer.sh http://localhost:8000/2016-08-15/proxy/tz-time/tz-time/
通過(guò)一個(gè) url 測(cè)試 fun local 進(jìn)程是否啟動(dòng)完成。kill -2 `cat $<` && rm $<
測(cè)試完成以后銷毀 fun local 進(jìn)程。npm run integration:test
會(huì)啟動(dòng)若干的測(cè)試用例,其中一個(gè)測(cè)試用例如下:
const request = require('request');
const url = 'http://localhost:8000/2016-08-15/proxy/tz-time/tz-time/';
describe('request url', () => {
it('without tz', (done) => {
request(url, (error, response, data) => {
if (error) {
fail(error);
} else {
const resData = JSON.parse(data);
expect(resData.statusCode).toBe(200);
expect(resData.message).toContain('Asia/Shanghai');
}
done();
});
});
});
端對(duì)端測(cè)試和集成測(cè)試的測(cè)試用例非常的類似,區(qū)別在于測(cè)試的服務(wù)端,端對(duì)端測(cè)試部署一套真實(shí)的環(huán)境,集成測(cè)試通過(guò) fun local 本地模擬。
本例中借助 fun deploy --use-ros
部署一套環(huán)境,環(huán)境名稱為 tz-e2e-
前綴帶上時(shí)間戳,這樣每次測(cè)試都會(huì)部署一套新的環(huán)境,不同環(huán)境之間相互不會(huì)影響。測(cè)試完成再通過(guò) aliyun-cli 工具把 ROS 的 stack 刪除即可。
下面端對(duì)端測(cè)試的 Makefile 目標(biāo):
stack_name := tz-e2e-$(shell date +%s)
e2e-test:
# deploy e2e
bin/deployE2EStack.sh $(stack_name)
# run test
npm run e2e:test
# cleanup
bin/delRosStack.sh $(stack_name)
bin/deployE2EStack.sh $(stack_name)
負(fù)責(zé)部署一個(gè)新的 ROS stack。部署之前需要使用 fun package 構(gòu)建交付物,具體如何構(gòu)建交付物可以參考下一小節(jié)。npm run e2e:test
運(yùn)行端對(duì)端測(cè)試bin/delRosStack.sh $(stack_name)
測(cè)試完成之后,清理部署的 ROS stack,會(huì)釋放掉響應(yīng)的云資源。fun package
命令可被用于構(gòu)建交付物,fun package
需要指定一個(gè) OSS 的 bucket。fun package 命令會(huì)完成如下步驟:
生成的 template.packaged.yml 文件就是最終交付物,可以通過(guò) fun deploy 命名進(jìn)行部署。
當(dāng)構(gòu)建環(huán)節(jié)生成了交付物以后,就可以通過(guò) fun deploy 進(jìn)行部署了。持續(xù)部署需要解決如下兩個(gè)問(wèn)題:
fun deploy
借助于 ROS,可以輕松的解決上述問(wèn)題。
fun deploy --use-ros --stack-name tz-staging --assume-yes
其中:
--use-ros
表示借助于 ROS 進(jìn)行部署,其工作機(jī)制是將 template.yml 推送到 ROS 服務(wù),由 ROS 服務(wù)執(zhí)行每個(gè)服務(wù)的新建和更新操作。如果沒(méi)有該參數(shù),fun 就會(huì)在本地解析 template.yml,調(diào)用 API 進(jìn)行資源創(chuàng)建。ROS 有個(gè)額外的好處是可以進(jìn)行部署的回滾,失敗的時(shí)候能自動(dòng)進(jìn)行回滾。--stack-name
指定一個(gè) stack 的名稱,stack 是 ROS 的概念,可以理解為一套環(huán)境。--assume-yes
用于無(wú)人值守模式,跳過(guò)確認(rèn)提示。注意,此處如果不指定參數(shù) --use-ros
,fun deploy 會(huì)采用直接調(diào)用云資源 API 進(jìn)行部署, 這是 fun deploy 的默認(rèn)部署方式,雖然也基本實(shí)現(xiàn)了冪等部署,但是僅支持部署有限的云資源(FC、OTS、API Gateway等),遠(yuǎn)不及 ROS 豐富,而且也沒(méi)法做到 ROS 已支持的回滾和一鍵刪除,所以此處不推薦。
以上便是Github和Travis CI的聯(lián)動(dòng)實(shí)現(xiàn)和使用代碼觸發(fā)CI/CD,雖然從篇幅上看很復(fù)雜,但是示例代碼非常詳細(xì)且容易理解,如果想了解更多相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
名稱欄目:Github和TravisCI的聯(lián)動(dòng)實(shí)現(xiàn)和使用代碼觸發(fā)CI/CD-創(chuàng)新互聯(lián)
路徑分享:http://chinadenli.net/article18/ejddp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、全網(wǎng)營(yíng)銷推廣、標(biāo)簽優(yōu)化、手機(jī)網(wǎng)站建設(shè)、電子商務(wù)、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容