前兩個(gè)月給公司搭建了一套持續(xù)集成媚送,用的是阿里云的「云效」中燥,「云效」有免費(fèi)一個(gè)月的試用版,有興趣的朋友可以玩一玩塘偎,開(kāi)闊一下知識(shí)范圍疗涉。開(kāi)始之前你需要簡(jiǎn)單了解一下 云效文檔哦
概念
持續(xù)集成指的是拿霉,頻繁地(一天多次)將代碼集成到主干。它的好處主要有兩個(gè)咱扣。
- 快速發(fā)現(xiàn)錯(cuò)誤绽淘。每完成一點(diǎn)更新沪铭,就集成到主干偏瓤,可以快速發(fā)現(xiàn)錯(cuò)誤厅克,定位錯(cuò)誤也比較容易证舟。
- 防止分支大幅偏離主干漆枚。如果不是經(jīng)常集成墙基,主干又在不斷更新碘橘,會(huì)導(dǎo)致以后集成的難度變大,甚至難以集成氮墨。
持續(xù)集成大致流程
提交
流程的第一步规揪,是開(kāi)發(fā)者向代碼倉(cāng)庫(kù)提交代碼猛铅。所有后面的步驟都始于本地代碼的一次提交(commit)奸忽。
構(gòu)建
所謂構(gòu)建,指的是將源碼轉(zhuǎn)換為可以運(yùn)行的實(shí)際代碼欠雌,比如安裝依賴富俄,配置各種資源(樣式表霍比、JS腳本、圖片)等等馍驯。
測(cè)試
全面測(cè)試汰瘫,單元測(cè)試和集成測(cè)試都要跑,有條件的話趴乡,也要做端對(duì)端測(cè)試晾捏。所有測(cè)試以自動(dòng)化為主惦辛,少數(shù)無(wú)法自動(dòng)化的測(cè)試用例胖齐,就要人工跑呀伙。
部署
通過(guò)了第二輪測(cè)試剿另,當(dāng)前代碼就是一個(gè)可以直接部署的版本(artifact)谚攒。將這個(gè)版本的所有文件打包( tar filename.tar * )存檔五鲫,發(fā)到生產(chǎn)服務(wù)器位喂。
生產(chǎn)服務(wù)器將打包文件塑崖,解包成本地的一個(gè)目錄规婆,再將運(yùn)行路徑的符號(hào)鏈接(symlink)指向這個(gè)目錄抒蚜,然后重新啟動(dòng)應(yīng)用。這方面的部署工具有 Ansible收津,Chef撞秋,Puppet 等吻贿。
回滾
一旦當(dāng)前版本發(fā)生問(wèn)題奉芦,就要回滾到上一個(gè)版本的構(gòu)建結(jié)果剧蹂。最簡(jiǎn)單的做法就是修改一下符號(hào)鏈接宠叼,指向上一個(gè)版本的目錄冒冬。
更詳細(xì)的說(shuō)明:http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html
云效持續(xù)集成操作流程
在云效后臺(tái)中剂邮,首先為項(xiàng)目注冊(cè)應(yīng)用横侦,并且關(guān)聯(lián)代碼庫(kù):
新建項(xiàng)目之后引瀑,選擇當(dāng)前創(chuàng)建的項(xiàng)目:
流水線配置
點(diǎn)擊左側(cè)流水線欄目,注冊(cè)一條項(xiàng)目流水線
將流水線關(guān)聯(lián)到當(dāng)前項(xiàng)目的代碼庫(kù)之中翼虫,并且選擇代碼推送后觸發(fā)流水線的分支
點(diǎn)擊流水線第一個(gè)階段掸宛,一般為名稱設(shè)為「構(gòu)建」旁涤,選項(xiàng)解釋如下:
- 分支名稱:這里的分支名稱是在阿里云虛擬主機(jī)中構(gòu)建時(shí)拉取的分支劈愚,請(qǐng)根據(jù)當(dāng)前部署環(huán)境選擇對(duì)應(yīng)的分支
- 構(gòu)建配置:有時(shí)我們需要構(gòu)建產(chǎn)生不同內(nèi)容的包菌羽,用于不同的運(yùn)行環(huán)境(比如集成測(cè)試環(huán)境和生產(chǎn)環(huán)境)云效流水線上的構(gòu)建任務(wù)根據(jù)指定 Git 庫(kù)源代碼根目錄下的
<應(yīng)用名稱>.release
文件注祖,進(jìn)行構(gòu)建打包工作是晨,以便隨后流水線上的部署任務(wù)進(jìn)行部署 release 所有配置選項(xiàng)罩缴。
在下面的高級(jí)配置之中有個(gè)「包」的概念箫章,其意思就是構(gòu)建的時(shí)候根據(jù)你配置的包生成多個(gè)環(huán)境终抽,如配圖中會(huì)生成「Testing 測(cè)試環(huán)境」「Staging 預(yù)發(fā)布環(huán)境」
包標(biāo)簽中的參數(shù)會(huì)在阿里云虛擬主機(jī)構(gòu)建的時(shí)候生成系統(tǒng)環(huán)境變量昼伴,然后 Shell 獲取
PS:構(gòu)建成功之后亩码,阿里云虛擬主機(jī)會(huì)把項(xiàng)目壓縮打包成 tgz 格式描沟,然后上傳到一個(gè)資源空間之中吏廉,以便部署階段下載壓縮包
下一個(gè)階段為部署階段席覆,當(dāng)然你可以在流水線中新增其他階段如「測(cè)試階段」佩伤,在部署階段選擇對(duì)應(yīng)的包標(biāo)簽配置生巡、應(yīng)用见妒、環(huán)境即可
至此流水線配置結(jié)束 流水線幫助文檔
部署環(huán)境配置
點(diǎn)擊部署環(huán)境
在部署配置之中我們需要做如下事情,「部署流程將按照下面排序進(jìn)行」
- 下載路徑:設(shè)置下載路徑疯汁,其意是將資源空間之中的壓縮包下載到你企業(yè)關(guān)聯(lián)的服務(wù)器上
- Stop:此項(xiàng)設(shè)置一個(gè) Shell 或其他操作腳本涛目,一般需要把老項(xiàng)目清理掉
- 解壓目錄:將下載后的項(xiàng)目壓縮包解壓到指定的目錄
- Start:此項(xiàng)設(shè)置一個(gè) Shell 或其他操作腳本,一般情況是在阿里云服務(wù)器上面初始化項(xiàng)目,如「數(shù)據(jù)遷移」
- 執(zhí)行用戶:在阿里云服務(wù)器的最大權(quán)限用戶一般為:root
私密配置項(xiàng)沫换,有時(shí)候涉及一些私密信息讯赏,不適合放在代碼庫(kù)中如數(shù)據(jù)庫(kù)配置,以包標(biāo)簽前綴區(qū)分環(huán)境配置 私密配置概念
至此云效后臺(tái)配置完成
代碼庫(kù)中構(gòu)建配置腳本
構(gòu)建的時(shí)候阿里云虛擬機(jī)磕谅,會(huì)以 <應(yīng)用名>.release 文件執(zhí)行構(gòu)建方式「這個(gè)文件會(huì)放到項(xiàng)目根目錄」
- code.language 是阿里云虛擬機(jī)需要的環(huán)境配置,配圖中為 php 7.0
- build.command 為構(gòu)建時(shí)自定義的 Shell 命令放刨,配圖中執(zhí)行了一個(gè) Shell 腳本
Build Shell 腳本进统,在此腳本中將倉(cāng)庫(kù)代碼構(gòu)建成一個(gè)完整可運(yùn)行的項(xiàng)目
- 在此次可獲取「包標(biāo)簽」中自定義的環(huán)境變量
- 獲取包標(biāo)簽環(huán)境表里為「PACKAGE_LABEL」
- 私密配置項(xiàng)的內(nèi)容會(huì)在構(gòu)建時(shí)生成一個(gè)文件其名稱固定為「rdc_security_config.properties」放在項(xiàng)目根目錄下螟碎,可讀取文件中的配置來(lái)填入 .env 中
- 注意 Shell 腳本一定要添加可執(zhí)行權(quán)限
#!/bin/bash
echo "開(kāi)始構(gòu)建 ${PACKAGE_LABEL} 環(huán)境"
# Git 構(gòu)建
git pull origin ${ENV_BRANCH}
git submodule init
git submodule update
echo "結(jié)束構(gòu)建 ${ENV_BRANCH}"
# 安裝依賴
echo "開(kāi)始安裝依賴"
composer config -g repo.packagist composer https://packagist.phpcomposer.com
composer install
echo "結(jié)束安裝依賴"
# 設(shè)置配置
echo "開(kāi)始配置項(xiàng)目"
cp .env.example.${PACKAGE_LABEL} .env
S_DB_PASSWORD=`./find.sh ${PACKAGE_LABEL}_DB_PASSWORD`
S_DB_USERNAME=`./find.sh ${PACKAGE_LABEL}_DB_USERNAME`
S_DB_DATABASE=`./find.sh ${PACKAGE_LABEL}_DB_DATABASE`
S_DB_HOST=`./find.sh ${PACKAGE_LABEL}_DB_HOST`
echo "數(shù)據(jù)庫(kù)配置讀取成功......"
sed -i -e "s/DB_HOST=127.0.0.1/DB_HOST=${S_DB_HOST}/g" .env
sed -i -e "s/DB_DATABASE=homestead/DB_DATABASE=${S_DB_DATABASE}/g" .env
sed -i -e "s/DB_USERNAME=homestead/DB_USERNAME=${S_DB_USERNAME}/g" .env
sed -i -e "s/DB_PASSWORD=secret/DB_PASSWORD=${S_DB_PASSWORD}/g" .env
echo "數(shù)據(jù)庫(kù)配置 Done"
# 正式服務(wù)器 Redis 配置
if [ "${PACKAGE_LABEL}" == 'production' ];
then
sed -i -e "s/REDIS_HOST=127.0.0.1/REDIS_HOST=${ENV_REDIS_HOST}/g" .env
sed -i -e "s/REDIS_PASSWORD=null/REDIS_PASSWORD=${ENV_REDIS_PASSWORD}/g" .env
echo "Redis 服務(wù)配置完成"
fi
# 百度地圖配置
sed -i -e "s/Baidu_Map_API_KEY=/Baidu_Map_API_KEY=${ENV_BAIDU_MAP_API_KEY}/g" .env
echo "百度地圖配置完成"
sed -i -e "s/WECHAT_PAYMENT_APPID=/WECHAT_PAYMENT_APPID=${ENV_WECHAT_PAYMENT_APPID}/g" .env
sed -i -e "s/WECHAT_PAYMENT_MCH_ID=/WECHAT_PAYMENT_MCH_ID=${ENV_WECHAT_PAYMENT_MCH_ID}/g" .env
sed -i -e "s/WECHAT_PAYMENT_KEY=/WECHAT_PAYMENT_KEY=${ENV_WECHAT_PAYMENT_KEY}/g" .env
echo "微信配置 Done"
sed -i -e "s/WECHAT_OPEN_PLATFORM_APPID=/WECHAT_OPEN_PLATFORM_APPID=${ENV_WECHAT_OPEN_PLATFORM_APPID}/g" .env
sed -i -e "s/WECHAT_OPEN_PLATFORM_SECRET=/WECHAT_OPEN_PLATFORM_SECRET=${ENV_WECHAT_OPEN_PLATFORM_SECRET}/g" .env
sed -i -e "s/WECHAT_OPEN_PLATFORM_TOKEN=/WECHAT_OPEN_PLATFORM_TOKEN=${ENV_WECHAT_OPEN_PLATFORM_TOKEN}/g" .env
sed -i -e "s/WECHAT_OPEN_PLATFORM_AES_KEY=/WECHAT_OPEN_PLATFORM_AES_KEY=${ENV_WECHAT_OPEN_PLATFORM_AES_KEY}/g" .env
echo "微信開(kāi)放平臺(tái)配置 Done"
sed -i -e "s/OSS_ID=/OSS_ID=${ENV_OSS_ID}/g" .env
sed -i -e "s/OSS_KEY=/OSS_KEY=${ENV_OSS_KEY}/g" .env
sed -i -e "s/OSS_BUCKET=/OSS_BUCKET=${ENV_OSS_BUCKET}/g" .env
sed -i -e "s/OSS_ENDPOINT=/OSS_ENDPOINT=${ENV_OSS_ENDPOINT}/g" .env
sed -i -e "s/OSS_SSL=/OSS_SSL=${ENV_OSS_SSL}/g" .env
sed -i -e "s/OSS_IS_CNAME=/OSS_IS_CNAME=${ENV_OSS_IS_CNAME}/g" .env
echo "OSS 配置 Done"
sed -i -e "s/APP_ENV=local/APP_ENV=${PACKAGE_LABEL}/g" .env
php artisan key:generate
composer du
chmod -R 777 storage
chmod -R 777 bootstrap
echo "${PACKAGE_LABEL} 環(huán)境構(gòu)建成功!"
這里有個(gè)小技巧迈螟,有可能不同環(huán)境的 .env 的配置項(xiàng) KEY 不一樣,如:測(cè)試服務(wù)器中用 QINIU 正式服務(wù)器中用 OSS褥民,那么可以把 .env.example
修改為對(duì)應(yīng)環(huán)境的 .env.example.testing
平夜,之后就可以獲取不同環(huán)境的 .env 文件
cp .env.example.${PACKAGE_LABEL} .env
服務(wù)器中部署配置腳本
就是我們?cè)诓渴瓠h(huán)境中指定的腳本
項(xiàng)目中這兩個(gè)腳本分別做了如下操作
clear_old.sh
#!/bin/bash
rm -rf /var/www/CI/yydy-rms
echo 'old project clear !'
init.sh
#!/bin/bash
cd /var/www/CI/yydy-rms
php artisan migrate
composer du
echo 'project is ready!'
當(dāng)然上面只是一個(gè)簡(jiǎn)單的刪除老項(xiàng)目拷貝新項(xiàng)目倡勇,你們可以根據(jù)自己項(xiàng)目實(shí)際需求初始化項(xiàng)目妻熊。
PS
現(xiàn)在推送流水線設(shè)置的分支會(huì)自動(dòng)觸發(fā)「流水線工作」扔役,如果流水線某個(gè)階段工作失敗可到后臺(tái)查看失敗原因方便排除錯(cuò)誤
最后附上一張公司實(shí)際流水線圖
Good Job Done !