目錄
一棚壁、前言
一、環(huán)境搭建
二继榆、初始化項(xiàng)目
三巾表、打包apk
四汁掠、發(fā)布到蒲公英
五、釘釘通知相關(guān)人員
一集币、前言
項(xiàng)目中經(jīng)常會進(jìn)行打包分發(fā), 但是常規(guī)的打包過程不免會非常的乏味無聊, 重復(fù)性的勞動, 實(shí)在沒啥意思, 今天就來介紹fastlane工具進(jìn)行android自動打包, 上傳蒲公英(也可以firim)并進(jìn)行釘釘群組通知相關(guān)人員调塌。
Fastlane是一整套的客戶端CICD工具集合。Fastlane可以非郴菰常快速簡單的搭建一個(gè)自動化發(fā)布服務(wù)羔砾,并且支持Android,iOS偶妖,MacOS姜凄。
Fastlane命令執(zhí)行的底層并不是自己實(shí)現(xiàn)的,而是調(diào)用其他的插件或者工具執(zhí)行的趾访。比如說打包态秧,F(xiàn)astlane中的gym工具只是xcodebuild工具的一個(gè)封裝,調(diào)用的其實(shí)還是xcodebuild中的打包命令扼鞋。
Fastlane本身沒有一套特殊語法申鱼,使用的Ruby語言。
Fastlane的插件工具叫做action云头,每一個(gè)action都對應(yīng)一個(gè)具體的功能捐友。
一、 環(huán)境搭建
1溃槐、蘋果系統(tǒng)自帶有ruby
ruby -v
2匣砖、安裝今天的主角fastlane
sudo gem install fastlane -NV
通過修改用戶讀寫權(quán)限可以解決
sudo chmod -R 777 /usr/bin/
或者
sudo gem install -n /usr/local/bin fastlane
3、安裝蒲公英的 Fastlane 插件
fastlane add_plugin pgyer
如果遇到這種情況:Could not find action, lane or variable 'pgyer'.
可能是你安裝pgyer插件的時(shí)候昏滴,不是在項(xiàng)目fastlane文件夾下安裝的猴鲫,重新安裝一下就可以解決上面的錯(cuò)誤。
4谣殊、安裝獲取應(yīng)用版本的 Fastlane 插件
fastlane add_plugin android_versioning
如果出現(xiàn)類似pgyer的錯(cuò)誤拂共,同理在項(xiàng)目fastlane文件夾下重新安裝就可以避免找不到插件的命令錯(cuò)誤。
二姻几、初始化項(xiàng)目
在使用 Fastlane 之前宜狐,我們首先需要在項(xiàng)目中初始化 Fastlane。首先進(jìn)入 App 的開發(fā)目錄鲜棠,執(zhí)行以下命令來初始化 Fastlane:
fastlane init
三肌厨、打包apk
激動人心的時(shí)刻終于來了,開始打包豁陆。
gradle(
task: 'assemble',
build_type: 'Release',
properties: {
"android.injected.signing.store.file" => Dir.pwd + "/street.keystore",
"android.injected.signing.store.password" => "123456",
"android.injected.signing.key.alias" => "street",
"android.injected.signing.key.password" => "123456",
},
);
四柑爸、發(fā)布到蒲公英
pgyer(api_key: pgy_api_key, user_key: pgy_user_key)
五、釘釘通知相關(guān)人員
markdown = {
msgtype: "markdown",
markdown: {
title: "#{app_name}Android內(nèi)測更新",
text: ding_talk_update_text,
# picUrl: "#{app_icon}",
# messageUrl: "#{app_url}"
},
at: {
atMobiles: ["18*****38","13*****77","18*****93"],
isAtAll: false
}
}
ding_talk_url = "https://oapi.dingtalk.com/robot/send?access_token="
ding_talk_secret = ""
timestamp = DateTime.now.strftime('%Q') # "1384526946523" (milliseconds)
finaly_sign = ''
if ding_talk_secret
data = timestamp + "\n" + ding_talk_secret
digest = OpenSSL::Digest.new('SHA256')
sign_data = OpenSSL::HMAC.digest(digest, ding_talk_secret.force_encoding("UTF-8"), data.force_encoding("UTF-8"))
finaly_sign = Base64.encode64(sign_data).gsub("\n",'')
finaly_sign = CGI::escape(finaly_sign)
end
ding_talk_url = ding_talk_url + "×tamp=#{timestamp}&sign=#{finaly_sign}"
puts ding_talk_url
uri = URI.parse(ding_talk_url)
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request.add_field('Content-Type', 'application/json')
request.body = markdown.to_json
puts request.body
response = https.request(request)
lane :toPgy do
puts("開始打包Android APK!");
gradle(
task: 'assemble',
build_type: 'Release',
properties: {
"android.injected.signing.store.file" => Dir.pwd + "/street.keystore",
"android.injected.signing.store.password" => "skyinfor2016",
"android.injected.signing.key.alias" => "ZhongshanStreet",
"android.injected.signing.key.password" => "skyinfor2016",
},
);
puts("------打包后App信息:------")
#上傳到蒲公英
pgyer(api_key: "bfb444cc09c3be7695c845b32ec89d3a", user_key: "fb6d0c133cebfe401fc5ad8153612520")
#更新日志
update_log="更新后臺定位"
# 獲取Apk默認(rèn)輸出路徑
apk_file_path = lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH];
# 重新命名Fastlane默認(rèn)Apk文件盒音,并移動到/fastlane/packages目錄下
fastlane_directory = Dir.pwd
app_name="數(shù)字孿生"
# 獲取版本號
app_version = get_version_code(app_project_dir: './app');
formatted_file_size="未知"
time_now=Time.now.strftime(“%Y-%m-%d %H:%M:%S”)
pgy_qrcode="https://www.pgyer.com/app/qrcode/9pHS"
pgy_app_url="https://www.pgyer.com/9pHS"
contacts_format="@13024266977"
app_icon="https://www.pgyer.com/app/qrcode/9pHS"
app_url=""
ding_talk_update_text = <<-EOF
#### #{app_name}Android-應(yīng)用更新
> 版本信息:#{app_version}\n
> 應(yīng)用大斜眵ⅰ:#{formatted_file_size} \n
> 更新時(shí)間:#{time_now}\n
> 關(guān)鍵詞:天覆發(fā)版專用\n
> 更新內(nèi)容:#{update_log}\n
掃描二維碼下載:
![二維碼](#{pgy_qrcode})\n
[點(diǎn)我進(jìn)入主頁下載](#{pgy_app_url}) #{contacts_format}
EOF
markdown = {
msgtype: "markdown",
markdown: {
title: "#{app_name}Android內(nèi)測更新",
text: ding_talk_update_text,
# picUrl: "#{app_icon}",
# messageUrl: "#{app_url}"
},
at: {
atMobiles: ["18516666838","13024266977","18225819193"],
isAtAll: false
}
}
ding_talk_url = "https://oapi.dingtalk.com/robot/send?access_token=13b87d0200ce93b51d9d7c04075be8b31c5c17ae342e67cf5a76b2dc06490a63"
ding_talk_secret = "SECbb33329836b0421b8e6271b2a34f913575d7e41f9076ae9b636418e2a5c206c9"
timestamp = DateTime.now.strftime('%Q') # "1384526946523" (milliseconds)
finaly_sign = ''
if ding_talk_secret
data = timestamp + "\n" + ding_talk_secret
digest = OpenSSL::Digest.new('SHA256')
sign_data = OpenSSL::HMAC.digest(digest, ding_talk_secret.force_encoding("UTF-8"), data.force_encoding("UTF-8"))
finaly_sign = Base64.encode64(sign_data).gsub("\n",'')
finaly_sign = CGI::escape(finaly_sign)
end
ding_talk_url = ding_talk_url + "×tamp=#{timestamp}&sign=#{finaly_sign}"
puts ding_talk_url
uri = URI.parse(ding_talk_url)
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request.add_field('Content-Type', 'application/json')
request.body = markdown.to_json
puts request.body
response = https.request(request)
puts "------------------------------"
puts "Response #{response.code} #{response.message}: #{response.body}"
end