前言
Gitlab代碼管理:這里測試案例直接將項目放到官方提供的gitlab 個人賬號下拧烦,公司/團隊可在自身服務(wù)器上搭建一套GitLab代碼管理會更加安全(可將需求拋給運維同學(xué),稍具規(guī)模的公司都會搭建屬于自己的git/svn)。
CICD官網(wǎng)簡介https://docs.gitlab.com/ee/ci/README.html
一钝计、基本概念
1.1. CI/CD
CI恋博,Continuous Integration,為持續(xù)集成私恬。即在代碼構(gòu)建過程中持續(xù)地進行代碼的集成债沮、構(gòu)建、以及自動化測試等本鸣;有了 CI 工具疫衩,我們可以在代碼提交的過程中通過單元測試等盡早地發(fā)現(xiàn)引入的錯誤;
CD荣德,Continuous Deployment闷煤,為持續(xù)交付。在代碼構(gòu)建完畢后涮瞻,可以方便地將新版本部署上線鲤拿,這樣有利于快速迭代并交付產(chǎn)品。
1.2. GitLab CI/CD
GitLab CI/CD(后簡稱 GitLab CI)是一套基于 GitLab 的 CI/CD 系統(tǒng)署咽,可以讓開發(fā)人員通過 .gitlab-ci.yml 在項目中配置 CI/CD 流程近顷,在提交后,系統(tǒng)可以自動/手動地執(zhí)行任務(wù)宁否,完成 CI/CD 操作窒升。而且,它的配置非常簡單慕匠,CI Runner 由 Go 語言編寫饱须,最終打包成單文件,所以只需要一個 Runner 程序台谊、以及一個用于運行 jobs 的執(zhí)行平臺(如裸機+SSH冤寿,Docker 或 Kubernetes 等,我推薦用 Docker青伤,因為搭建相當(dāng)容易)即可運行一套完整的 CI/CD 系統(tǒng)。
Job
job 為任務(wù)殴瘦,是 GitLab CI 系統(tǒng)中可以獨立控制并運行的最小單位狠角。 在提交代碼后,開發(fā)者可以針對特定的 commit
完成一個或多個 job蚪腋,從而進行 CI/CD 操作丰歌。
Pipeline
Pipeline 即流水線姨蟋,可以像流水線一樣執(zhí)行多個 Job. 在代碼提交或 MR 被合并時,GitLab 可以在最新生成的 commit
上建立一個 pipeline立帖,在同一個 pipeline 上產(chǎn)生的多個任務(wù)中眼溶,所用到的代碼版本是一致的。
Stage
一般的流水線通常會分為幾段晓勇;在 pipeline中堂飞,可以將多個任務(wù)劃分在多個階段中,只有當(dāng)前一階段的所有任務(wù)都執(zhí)行成功后绑咱,下一階段的任務(wù)才可被執(zhí)行绰筛。
注:如果某一階段的任務(wù)均被設(shè)定為“允許失敗”,那這個階段的任務(wù)執(zhí)行情況描融,不會影響到下一階段的執(zhí)行铝噩。
上圖整條流水線從左向右依次執(zhí)行,每一列均為一個階段窿克,而列中的每個可操控元素均為任務(wù)骏庸。 這里五個階段的任務(wù)是自動執(zhí)行的任務(wù),在commit或request merge(根據(jù)gitlab-ci Job條件) 提交后即可自動開始運行年叮,執(zhí)行成功或失敗后具被,可以點擊任務(wù)右邊的按鈕重試;如果需要手動觸發(fā)執(zhí)行任務(wù)需要在.gitlab-ci.yml任務(wù)里添加when:manual表示該操作只允許手動觸發(fā)谋右。
一個Pipeline對應(yīng)多個Stage,每一個Stage可分成多個Job
二硬猫、Gitlab-Runner安裝/注冊
2.1. 安裝
官方安裝文檔https://docs.gitlab.com/runner/install/
針對iOS項目,準備一臺空閑(團隊使用)Mac OS電腦當(dāng)做服務(wù)器改执,內(nèi)網(wǎng)服務(wù)器能訪問外網(wǎng)即可啸蜜,在此服務(wù)器上安裝Runner,后續(xù)ci/cd相關(guān)腳本亦在此運行
# MacOS
sudo brew install gitlab-ci-multi-runner
# For Debian/Ubuntu/Mint
sudo apt-get install gitlab-ci-multi-runner
# For RHEL/CentOS/Fedora
sudo yum install gitlab-ci-multi-runner
2.2.注冊
打開gitlab項目 -> Settings -> CI/CD -> Runners
這里創(chuàng)建Group辈挂,Group下Runner衬横,可共享其下的項目使用
- 在安裝Runner的服務(wù)器上運行注冊
sudo gitlab-runner register
- 輸入你的GitLab URL,這里copy上圖https://gitlab.com/
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com):
https://gitlab.com/
- 輸入 注冊令牌 來注冊 Runner,這里copy上圖token
Please enter the gitlab-ci token for this runner:
wfjVq8G..我是馬賽克..LoZ
- 輸入 Runner 說明
Please enter the gitlab-ci description for this runner:
iOSTeamRunner
- 輸入 Runner 的 tags
Please enter the gitlab-ci tags for this runner (comma separated):
iOSTeamRunner
- 輸入 Runner 執(zhí)行方式
Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
shell
如下:
三、CI/CD 在iOS工程中的應(yīng)用
下列使用到的.gitlab-ci.yml终蒂、project_build_check.sh衍锚、qiyewechat_sendMsg_api.sh等文件下載參考
3.1. 需求
需求:非項目負責(zé)人不允許對master主分支進行push、merge等修改代碼相關(guān)操作碍遍,收回相關(guān)權(quán)限渐裂。開發(fā)者只能通過master分支創(chuàng)建一個開發(fā)分支進行項目迭代,一旦迭代完成霉翔,只能發(fā)起merge request讓相關(guān)項目負責(zé)人將開發(fā)分支merge(合并)到master分支睁蕾,為了保證合并之前開發(fā)分支代碼是編譯通過且打包無異常,需進行校驗工作,讓項目負責(zé)人清晰知道代碼編譯是正常的子眶。所以引入了 Gitlab 下 CI/CD機制瀑凝。
上圖"CD:版本發(fā)布流程" 我們使用了jenkins進行自動化打包發(fā)布(當(dāng)然也可以使用Gitlab來實現(xiàn)),這里就不多描述
這里主要關(guān)注上圖"CI:代碼編譯校驗"相關(guān)的.gitlab-ci.yml文件的編寫臭杰。
3.2. 環(huán)境
- gitlab代碼管理粤咪,可以使用官網(wǎng),亦可自行搭建gitlab代碼管理服務(wù)器
- 需要在一臺電腦或服務(wù)器安裝Runner,如何安裝Runner請看上方“二渴杆、Gitlab-Runner安裝/注冊 ”
- 在安裝Runner的設(shè)備上安裝Xcode寥枝,因為我們的項目是iOS項目,編譯打包工作需要此環(huán)境
- 設(shè)置Pipeline(流水線)成功才可merge
3.3. .gitlab-ci.yml文件
給工程項目添加gitlab-ci.yml文件
這里執(zhí)行渠道(Pipeline)分成5個階段(stage)
#GIT_STRATEGY: none
#GIT策略将塑,定義拉取代碼的方式脉顿,有3種:clone/fetch/none,默認為clone点寥,速度最慢艾疟,每步j(luò)ob都會重新clone一次代碼。我們一般將它設(shè)置為none敢辩,在具體任務(wù)里設(shè)置為fetch就可以滿足需求蔽莱,畢竟不是每步都需要新代碼,那也不符合我們測試的流程
#在job中可以用${GIT_STRATEGY}來使用這個變量戚长。常用的預(yù)定義變量有CI_COMMIT_REF_NAME(項目所在的分支或標(biāo)簽名稱)盗冷,CI_JOB_NAME(任務(wù)名稱),CI_JOB_STAGE(任務(wù)階段)
before_script:
- |
ifconfig | grep "inet "
pwd
# export LANG="en_US.UTF-8"
# export
# 全局變量同廉,保證不同stage不會每次重置代碼
# 某些步驟需要可以在Job中添加(如結(jié)果回調(diào)中)
#after_script:
# - |
# pwd
stages:
- 1.輸出環(huán)境變量
- 2.設(shè)置編譯前腳本
- 3.pod install
- 4.編譯檢查
- 5.結(jié)果處理
#1.輸出環(huán)境變量
#gitlab系統(tǒng)自帶環(huán)境變量:http://gitlab.code.mob.com/help/ci/variables/predefined_variables.md
print_env:
stage: 1.輸出環(huán)境變量
script:
- export LANG="en_US.UTF-8"
- export
#- echo "==================================================="
#- echo "project_name:${O2Space_ProjectName}"
#- echo "project_workspace:${O2Space_WorkSpace}"
#- echo "sdk_schemes:${O2Space_SDKSchemes}"
#- echo "ipa_scheme:${O2Space_IPAScheme}"
#- echo "==================================================="
only:
- merge_requests
tags:
- iOSTeamRunner
variables:
GIT_STRATEGY: none
#2.設(shè)置編譯前腳本
# 開啟自身clone項目 及 clone/fetch 相關(guān)封裝shell腳本
setup_script:
stage: 2.設(shè)置編譯前腳本
script:
- |
if [ -d ToolScript ]; then
#企業(yè)微信獲取token存儲時文件創(chuàng)建需要權(quán)限
chmod u+w ToolScript
builtin cd ToolScript
git fetch
git reset --hard origin/master
chmod +x ./project_build_check.sh
chmod +x ./qiyewechat_sendMsg_api.sh
builtin cd ..
else
#添加ssh,否則git clone將無權(quán)限
username="wukx"
ssh_PATH="/Users/wkx/Documents/Develop/.ssh/${username}_rsa"
eval $(ssh-agent)
ssh-add $ssh_PATH
#將shell腳本放到ToolScript項目里便于管理
git clone git@gitlab.com:O2Space/ToolScript.git
ssh-agent -k
fi
#當(dāng)前Gitlab賬號
users=${GITLAB_USER_LOGIN}
eventContent=""
if [ ${CI_PIPELINE_SOURCE} = "merge_request_event" ]; then
eventContent="您發(fā)起了merge請求仪糖,正在為您進行代碼校驗 \n項目:${CI_PROJECT_PATH},\n發(fā)起分支:${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}迫肖,\n目標(biāo)分支:${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}"
fi
#發(fā)送企業(yè)微信消息锅劝,通知發(fā)起者,開始編譯校驗
type=1
builtin cd ToolScript
source qiyewechat_sendMsg_api.sh -u "${users}" -c "${eventContent}" -y "${type}"
builtin cd ..
only:
- merge_requests
tags:
- iOSTeamRunner
variables:
GIT_STRATEGY: clone
#3.pod install
pod_install:
stage: 3.pod install
script:
- |
pwd
echo "此項目無需通過Pod集成第三方SDK"
# source pod install
only:
- merge_requests
tags:
- iOSTeamRunner
variables:
GIT_STRATEGY: none
#4.編譯檢查
bulid_script:
stage: 4.編譯檢查
script:
- |
project_dir=`pwd`
project_name=${O2Space_ProjectName}
project_workspace=${O2Space_WorkSpace}
sdk_schemes=${O2Space_SDKSchemes}
ipa_scheme=${O2Space_IPAScheme}
echo $project_dir
echo "project_name:${project_name}"
echo "project_workspace:${project_workspace}"
echo "sdk_schemes:${sdk_schemes}"
echo "ipa_scheme:${ipa_scheme}"
chmod +x ToolScript/project_build_check.sh
source ToolScript/project_build_check.sh "${project_dir}" "${project_name}" "${project_workspace}" "${sdk_schemes}" "${ipa_scheme}"
only:
- merge_requests
tags:
- iOSTeamRunner
variables:
GIT_STRATEGY: none
#5.結(jié)果處理
fail_script:
stage: 5.結(jié)果處理
script:
- |
echo "校驗失敗"
users=${GITLAB_USER_LOGIN}
timeStr=$(date "+%Y-%m-%d %H:%M:%S")
title="Gitlab操作:代碼編譯校驗結(jié)果通知"
branchInfo=${CI_BUILD_REF_NAME}
eventContent=""
weblink=""
if [ ${CI_PIPELINE_SOURCE} = "merge_request_event" ]; then
branchInfo=${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}→${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
eventContent=${CI_MERGE_REQUEST_TITLE}
weblink=${CI_MERGE_REQUEST_PROJECT_URL}/merge_requests/${CI_MERGE_REQUEST_IID}
fi
description="<div class='gray'>${timeStr}</div>
<div class='normal'>項目:${CI_PROJECT_PATH}</div>
<div class='normal'>事件:${CI_PIPELINE_SOURCE}</div>
<div class='normal'>涉及分支:${branchInfo}</div>
<div class='normal'>事件內(nèi)容:${eventContent}</div>
<div class='normal'>pipeline:${CI_PIPELINE_ID}</div>
<div class='highlight'>校驗結(jié)果:失敗</div>"
type=2
builtin cd ToolScript
source qiyewechat_sendMsg_api.sh -u "${users}" -t "${title}" -d "${description}" -l "${weblink}" -y "${type}"
builtin cd ..
when: on_failure
only:
- merge_requests
tags:
- iOSTeamRunner
variables:
GIT_STRATEGY: none
#5.結(jié)果處理
success_script:
stage: 5.結(jié)果處理
script:
- |
echo "校驗成功"
users=${GITLAB_USER_LOGIN}
resultStr=""
if [ ! -n "$O2Space_MergeOwner" ]; then
echo "O2Space_MergeOwner is null"
else
users=${users},${O2Space_MergeOwner}
resultStr="蟆湖,請相關(guān)人員:${O2Space_MergeOwner}故爵,進行merge操作"
fi
timeStr=$(date "+%Y-%m-%d %H:%M:%S")
title="Gitlab操作:代碼編譯校驗結(jié)果通知"
branchInfo=${CI_BUILD_REF_NAME}
eventContent=""
weblink=""
if [ ${CI_PIPELINE_SOURCE} = "merge_request_event" ]; then
branchInfo=${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}→${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
eventContent=${CI_MERGE_REQUEST_TITLE}
weblink=${CI_MERGE_REQUEST_PROJECT_URL}/merge_requests/${CI_MERGE_REQUEST_IID}
fi
description="<div class='gray'>${timeStr}</div>
<div class='normal'>項目:${CI_PROJECT_PATH}</div>
<div class='normal'>事件:${CI_PIPELINE_SOURCE}</div>
<div class='normal'>涉及分支:${branchInfo}</div>
<div class='normal'>事件內(nèi)容:${eventContent}</div>
<div class='normal'>pipeline:${CI_PIPELINE_ID}</div>
<div class='blue'>校驗結(jié)果:成功${resultStr}</div>"
type=2
builtin cd ToolScript
source qiyewechat_sendMsg_api.sh -u "${users}" -t "${title}" -d "${description}" -l "${weblink}" -y "${type}"
builtin cd ..
when: on_success
only:
- merge_requests
tags:
- iOSTeamRunner
variables:
GIT_STRATEGY: none
gitlab系統(tǒng)自帶環(huán)境變量、自定義的變量隅津。
自定義變量配置:
通知:
通過企業(yè)微信Api接口發(fā)送通知到開發(fā)者微信上诬垂,這里通知功能封裝在qiyewechat_sendMsg_api.sh的shell文件里,此文件在項目“ToolScripts”里伦仍,所以腳本任務(wù)中執(zhí)行g(shù)it clone項目
qiyewechat_sendMsg_api.sh文件:
#!/bin/bash
#用法提示
usage() {
echo "Usage:"
echo " qiyewechat_sendMsg_api.sh [-u USER] [-t TITLE] [-c CONTENT] [-d DETAIL] [-p PICTURE] [-l LINK] [-y TYPE]"
echo "Description:"
echo " USER, 用戶."
echo " TITLE, 標(biāo)題."
echo " CONTENT, 內(nèi)容."
echo " DETAIL, 細節(jié)."
echo " PICTURE, 圖片."
echo " LINK, 鏈接."
echo " TYPE, 內(nèi)容類型."
exit -1
}
# 獲取腳本執(zhí)行時的選項
while getopts u:t:c:d:p:l:y: option
do
case "${option}" in
u) USER=${OPTARG};;
t) TITLE=${OPTARG};;
c) CONTENT=${OPTARG};;
d) DETAIL=${OPTARG};;
p) PICTURE=${OPTARG};;
l) LINK=${OPTARG};;
y) TYPE=${OPTARG};;
h) usage;;
?) usage;;
esac
echo $option
echo $OPTARG
done
#gitlab用戶 匹配 企業(yè)微信通訊錄用戶賬號
function getQiyewechatUserId(){
local str=(`cat ./user_table.txt | awk -F ' ' '{print $1}'`)
local userid=""
local params=$@
for i in ${!str[@]}
do
arr=(${str[i]//:/ })
if [ ${arr[0]} == ${params[0]} ]; then
echo ${arr[1]}
fi
done
echo ${userid}
}
function getQiyewechatUserIds(){
local params=$@
local userids=""
arr=(${params//,/ })
for i in ${!arr[@]}
do
tmp_str=$(getQiyewechatUserId ${arr[i]})
if [[ $i != 0 ]]; then
tmp_str=\|${tmp_str}
fi
userids=${userids}${tmp_str}
done
echo ${userids}
}
userids=$(getQiyewechatUserIds $USER)
echo userids:${userids}
# exit 0
#api的相關(guān)參數(shù)
#企業(yè)id
corpid='ww93f2060b7af1b265'
#企業(yè)下創(chuàng)建應(yīng)用id
agentId=1000002
corpsecret='kaoVjgw1Qi2lnvqjBJbbxAl3mTkYCKq7sk7eOZyFA7Y'
#RESTFUL API 接口相關(guān)參數(shù)
HOST=https://qyapi.weixin.qq.com
#獲取token
wechat_api_token=${HOST}/cgi-bin/gettoken
#例子:
#GET:https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=""&corpsecret=""
#返回內(nèi)容:
#{
# "errcode":0
# "errmsg": ok
# "access_token":"",
# "expires_in": 7200,
#}
#發(fā)送消息
wechat_api_sendText=${HOST}/cgi-bin/message/send
#例子:
#POST: https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN
#文本消息:
#{
# "touser" : "UserID1|UserID2|UserID3"
# "toparty" : "PartyID1|PartyID2",
# "totag" : "TagID1 | TagID2",
# "msgtype" : "text",
# "agentid" : 1,
# "text" : {
# "content" : "你的快遞已到结窘,請攜帶工卡前往郵件中心領(lǐng)取。\n出發(fā)前可查看<a href=\"http://work.weixin.qq.com\">郵件中心視頻實況</a>充蓝,聰明避開排隊晦鞋。"
# },
# "safe":0,
# "enable_id_trans": 0
#}
#
#文本卡片消息:
#{
# "touser" : "UserID1|UserID2|UserID3",
# "toparty" : "PartyID1 | PartyID2",
# "totag" : "TagID1 | TagID2",
# "msgtype" : "textcard",
# "agentid" : 1,
# "textcard" : {
# "title" : "領(lǐng)獎通知",
# "description" : "<div class=\"gray\">2016年9月26日</div> <div class=\"normal\">恭喜你抽中iPhone 7一臺,領(lǐng)獎碼:xxxx</div><div class=\"highlight\">請于2016年10月10日前聯(lián)系行政同事領(lǐng)取</div>",
# "url" : "URL",
# "btntxt":"更多"
# },
# "enable_id_trans": 0
#}
#
#圖文消息:
# {
# "touser" : "UserID1|UserID2|UserID3",
# "toparty" : "PartyID1 | PartyID2",
# "totag" : "TagID1 | TagID2",
# "msgtype" : "news",
# "agentid" : 1,
# "news" : {
# "articles" : [
# {
# "title" : "中秋節(jié)禮品領(lǐng)取",
# "description" : "今年中秋節(jié)公司有豪禮相送",
# "url" : "URL",
# "picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"
# }
# ]
# },
# "enable_id_trans": 0
# }
#返回內(nèi)容:
#{
# "errcode" : 0,
# "errmsg" : "ok",
# "invaliduser" : "userid1|userid2", // 不區(qū)分大小寫,返回的列表都統(tǒng)一轉(zhuǎn)為小寫
# "invalidparty" : "partyid1|partyid2",
# "invalidtag": "tagid1|tagid2"
# }
# 獲取token
function getAccessToken {
token_url="${wechat_api_token}?corpid=${corpid}&corpsecret=${corpsecret}"
curl -d "" -X GET $token_url > token.json
token=$(cat token.json | python -c "import sys, json; print(json.load(sys.stdin)['access_token'])")
echo $token
}
token=$(getAccessToken)
echo token:$token
send_content=""
if [ $TYPE -eq 1 ]
then
send_content="{
\"touser\":\"$userids\",
\"agentid\":\"$agentId\",
\"msgtype\":\"text\",
\"text\":{\"content\":\"$CONTENT\"},
\"safe\":0,
\"enable_id_trans\":0
}"
elif [ $TYPE -eq 2 ]
then
send_content="{
\"touser\":\"$userids\",
\"agentid\":\"$agentId\",
\"msgtype\":\"textcard\",
\"textcard\":{
\"title\":\"$TITLE\",
\"description\":\"$DETAIL\",
\"url\":\"$LINK\",
\"btntxt\":\"更多\"
},
\"enable_id_trans\":0
}"
elif [ $TYPE -eq 3 ]
then
send_content="{
\"touser\":\"$userids\",
\"agentid\":\"$agentId\",
\"msgtype\":\"news\",
\"news\":{
\"articles\":[{
\"title\":\"$TITLE\",
\"description\":\"$DETAIL\",
\"url\":\"$LINK\",
\"picurl\":\"$PICTURE\"
}]
},
\"enable_id_trans\":0
}"
fi
echo -e $send_content > "send_content.json"
send_url="${wechat_api_sendText}?access_token=${token}"
echo $send_url
curl --write-out %{http_code} -d '@send_content.json' -X POST ${send_url} > sendResult.json
用戶對應(yīng)企業(yè)微信賬號,user_table.txt文件:
gitlab賬號:企業(yè)微信賬號
wukexiu:WuKeXiu
這里才是正在的編譯校驗任務(wù)悠垛,當(dāng)然真正校驗的實現(xiàn)在project_build_check.sh中(里面有對xcode的項目進行編譯,打包)
project_build_check.sh文件:
##!/bin/sh
######################
#此shell用于項目編譯校驗#
######################
#in other shell, source project_build_check.sh 在同一個shell下執(zhí)行共享參數(shù)
echo "PROJECTNAME:${O2Space_ProjectName}"
echo "WORKSPACE:${O2Space_WorkSpace}"
echo "SDK_SCHEMES:${O2Space_SDKSchemes}"
echo "IPA_SCHEME:${O2Space_IPAScheme}"
# 第一步
echo "第一步 變量配置"
pwd
project_path=$1
project_name=$2
# workspace名
project_workspace=$3
#多個Scheme名用“,”分割
sdk_schemes=$4
ipa_scheme=$5
if [ -z "$ipa_scheme" ]; then
ipa_scheme=$project_name
fi
# archive_path eg:$project_path/$project_name.xcarchive
archive_path=$project_path/$ipa_scheme.xcarchive
# ipa文件存放路徑 eg:$project_path/$project_name.ipa
export_ipa_path=$project_path/$ipa_scheme.ipa
# exportOptions plist eg:$project_path/ExportOptions.plist
# 打包導(dǎo)出ipa的時候會生成記錄了這次導(dǎo)出時的證書及關(guān)鍵配置
export_options_plist=$project_path/ExportOptions.plist
# 編譯模式
build_type=Release
# 第二步
echo "第二步 清理工程-打包-導(dǎo)出"
#echo "選擇Xcode版本" | sudo -S xcode-select -s /Applications/Xcode10.1.app
if [ -n "$sdk_schemes" ]; then
sdk_scheme_array=(${sdk_schemes//,/ })
echo "http:///-----------"
echo "http:/// 正在打包SDK"
echo "http:///-----------"
for scheme in ${sdk_scheme_array[@]}
do
echo "http:///------------------------"
echo "http:/// 正在編譯$scheme"
echo "http:///------------------------"
# 安裝xcpretty 可以讓編譯輸出格式化
#xcodebuild clean -project ${project_name}.xcodeproj -scheme $scheme | xcpretty
#-derivedDataPath build,編譯路徑為當(dāng)前build文件
xcodebuild -workspace ${project_workspace}.xcworkspace -scheme $scheme -configuration $build_type -derivedDataPath build build -quiet || exit
done
fi
if [ -z "$ipa_scheme" ]; then
echo "打包ipa的scheme為nil"
exit 1
fi
echo "http:///---------------"
echo "http:/// 正在清理Demo工程"
echo "http:///---------------"
xcodebuild clean -workspace ${project_workspace}.xcworkspace -scheme $ipa_scheme -configuration $build_type -quiet || exit
## 打IPA方式一: xcodebuild archive + xcodebuild -exportArchive,需要exportOptionsPlist娜谊,(可以手動打包一次确买,將exportOptionsPlist拷貝一份)
# echo "http:///------------------------"
# echo "http:/// 正在編譯Demo工程: Release"
# echo "http:///------------------------"
# xcodebuild archive -workspace ${project_workspace}.xcworkspace -scheme ${ipa_scheme} -configuration Debug -archivePath $archive_path -quiet || exit
# echo "http:///-------------------------------"
# echo "http:/// 開始導(dǎo)出ipa: ${export_ipa_path}"
# echo "http:///-------------------------------"
# export_options_plist這個需要手動打包一次將ExportOptions.plist拷貝出來
# xcodebuild -exportArchive -archivePath $archive_path -exportPath ${export_ipa_path} -exportOptionsPlist ${export_options_plist} -quiet || exit
# 打IPA方式二: xcodebuild build + xcrun
xcodebuild -workspace ${project_workspace}.xcworkspace -scheme $ipa_scheme -configuration $build_type -derivedDataPath build build -quiet || exit
#Xcode升級到8.3后 用命令進行打包 提示下面這個錯誤
#xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH
#新版的Xcode少了這個PackageApplication
#從舊版copy一份到“/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/”下
xcrun -sdk iphoneos PackageApplication -v build/Build/Products/Release-iphoneos/$ipa_scheme.app -o $export_ipa_path || exit
if [[ -e $export_ipa_path ]]; then
echo "http:///-----------"
echo "http:/// ipa包已導(dǎo)出"
echo "http:///-----------"
#open $export_ipa_path
fi
# echo "第三步 發(fā)布到蒲公英或app store"
# echo "http:///--------------------"
# echo "http:/// 開始發(fā)布到 app store"
# echo "http:///--------------------"
# altoolPath=/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool
# "$altoolPath" --validate-app -f $export_ipa_path\
# -u <你的開發(fā)者賬號> -p <你的開發(fā)者賬號密碼>\
# --output-format xml
# "$altoolPath" --upload-app -f $export_ipa_path\
# -u <你的開發(fā)者賬號> -p <你的開發(fā)者賬號密碼>\
# --output-format xml
# echo "http:///--------------------"
# echo "http:/// 開始上傳ipa包到蒲公英"
# echo "http:///--------------------"
# curl -F "file=@${export_ipa_path}"\
# -F "_api_key=5f36a500df15a2b22a195c1583cb8421" https://www.pgyer.com/apiv2/app/upload
# echo "http:///--------------------"
# echo "http:/// 開始上傳ipa包到Fir"
# echo "http:///--------------------"
# fir login -T <你的token>
# fir publish $export_ipa_path
# 成功退出
exit 0
流程中任務(wù)發(fā)起和執(zhí)行失敗都會通過企業(yè)微信通知到發(fā)起者,全部執(zhí)行成功通知發(fā)起者和Merge權(quán)限擁有者
3.4. 相關(guān)效果圖
-
圖一:發(fā)起merge request
-
圖二:觸發(fā)CI,執(zhí)行.gitlab-ci.yml中相關(guān)merge_request任務(wù)
-
圖三:任務(wù)執(zhí)行完結(jié)果
-
圖四:查看Pipeline
圖五:微信通知信息
通過“企業(yè)微信”api發(fā)送通知到用戶的“企業(yè)微信應(yīng)用”纱皆,如何讓微信也能接收呢湾趾?用微信關(guān)注對應(yīng)的“企業(yè)微信”
微信內(nèi)收到關(guān)注該“企業(yè)微信”的消息