iOS 基于 launchctl + fastlane + 钉钉机器人实现定时自动打包

前言

做为一个移动端程序员,每次 feature add 或者 bug fix 后常常要打包交付给 QA,之前传统的操做都是手动点击 Xcode -> Product -> Archive -> Organizer -> Distrubute App -> ipa 上传到第三方内测分发平台(蒲公英、fir)-> 手动填写更新日志 -> 发送安装连接到部门群(钉钉或者企业微信),看起来好像很机械和繁琐,又没啥技术含量是吧......ios

若是能把这部分工做给自动化了就行了,天天能够省一点时间出来发呆也挺好的。需求整理一下大概是这样:git

  1. 可以定时触发;
  2. 自动打包;
  3. 自动读取某个时间段内的 git commit messge 信息当作更新日志;
  4. 打包完成自动发送安装连接到部门群(钉钉或者企业微信);

实现

需求1、定时任务

调研了一下,Mac OS 能够基于 launchctl 来配置定时任务。能够配置到不一样级别的 LaunchAgents 下,几种的区别以下:程序员

~/Library/LaunchAgents 由用户本身定义的任务项
/Library/LaunchAgents 由管理员为用户定义的任务项
/Library/LaunchDaemons 由管理员定义的守护进程任务项
/System/Library/LaunchAgents 由Mac OS X为用户定义的任务项
/System/Library/LaunchDaemons 由Mac OS X定义的守护进程任务项
复制代码

咱们配置在用户目录下就行,也就是这个目录 ~/Library/LaunchAgents,按照固定的格式新建一个 Plist 文件就行,能够看到已经有一些第三方的任务在这里了:github

image-20200126210005856

个人配置文件是这样:shell

<plist version="1.0">
<dict>
  <!-- Label惟一的标识 -->
  <key>Label</key>
  <string>com.autoArchiveTask.plist</string>

  <key>Program</key>
  <string>/Users/username/Desktop/code/Project/run.sh</string>

  <!-- 指定要运行的脚本 -->
  <key>ProgramArguments</key>
  <array>
    <string>/Users/username/Desktop/code/Project/run.sh</string>
  </array>
  <!-- 指定要运行的时间 -->
  <key>StartCalendarInterval</key>
  <array>
    <dict>
        <key>Minute</key>
        <integer>00</integer>
        <key>Hour</key>
        <integer>11</integer>
    </dict>
    <dict>
        <key>Minute</key>
        <integer>00</integer>
        <key>Hour</key>
        <integer>16</integer>
    </dict>
  </array>

<!-- 标准输出文件 -->
<key>StandardOutPath</key>
<string>/Users/username/Desktop/code/Project/run.log</string>
<!-- 标准错误输出文件,错误日志 -->
<key>StandardErrorPath</key>
<string>/Users/username/Desktop/code/Project/run.error</string>
</dict>
</plist>
复制代码

相关字段的解释以下:macos

  1. Label:对应的须要保证全局惟一性;
  2. Program:要运行脚本;
  3. ProgramArguments:指定要运行的脚本;
  4. StartCalendarInterval:运行的时间,单个时间点使用 dict,多个时间点使用 array
  5. StartInterval:时间间隔,与 StartCalendarInterval 使用其一,单位为秒
  6. StandardInPath、StandardOutPath、StandardErrorPath:标准的输入、输出、错误文件

配置好了就能够加载了,加载后就生效了,相关的命令以下:json

# 加载任务, -w选项会将 plist 文件中无效的 key 覆盖掉,建议加上
launchctl load -w xxx.plist
 # 删除任务
launchctl unload -w xxx.plist
 # 查看任务列表, 使用 grep '任务部分名字' 过滤
launchctl list | grep 'xxx'
 # 当即执行一次任务,可用来测试
launchctl start xxx.plist
复制代码

需求2、自动打包

这个使用 fastlane 就行,很好很强大。相关的配置可参见官网,建议使用 brew 方式安装。配置安装文档就行,c#

因为我这个是多 target 工程,因此我这边的可能多一点配置,个人 Fastfile 文件配置以下:api

default_platform(:ios)
 # 网络请求依赖
require 'net/http'
require 'uri'
require 'json'


 platform :ios do
		
   desc "发布app到 App Store 或者 Fir.im "
   lane :customer_hoc do
     # add actions here: https://docs.fastlane.tools/actions
     sh "fastlane adhoc --env Customer"
   end

   desc "发布app到 App Store 或者 Fir.im "
   lane :driver_hoc do
     # add actions here: https://docs.fastlane.tools/actions
     sh "fastlane adhoc --env Driver"
   end
		 


   desc "发布指定Target到 Fir.im"
   lane :adhoc do
   gym(
     clean:true, #打包前clean项目
     workspace: "Hedgehog.xcworkspace",
     export_method: "ad-hoc", #导出方式
     scheme: ENV['SCHEME_NAME'], #scheme
     output_name: ENV['SCHEME_NAME']+".ipa", # ipa 文件名
     output_directory: "./ipa", #ipa的存放目录
     export_options: {
         provisioningProfiles: {
             "cn.ccmore.hedgehog.customer"=>"CustomerAdhoc", 
             "cn.ccmore.hedgehog.driver"=>"DricerAdhoc"
         }
     }
   )
 # 前往fir.im获取 api token, 将鼠标放置右上角帐号上面, 在下拉窗选择API token
 # 若使用的蒲公英, 请前往 https://www.pgyer.com/ 查看上传方法
 # 若是使用Firimfile, 此处为 firim 便可
   firim(firim_api_token:'xxxx')

  
 # 钉钉机器人
  app_patch   = "ipa/" + ENV['SCHEME_NAME']+".ipa"
  app_version = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleShortVersionString")
  app_build_version = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleVersion")
  app_name    = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleDisplayName")

 # 根据 SCHEME_NAME 区分下载连接
  app_url = "https://fir.im/6udv"

  if ENV['SCHEME_NAME'] == "Driver" then
    app_url = "https://fir.im/sa4q"
  end
  
  app_icon = "./Hedgehog/ipa/icons/57.png"
  dingTalk_url = "https://oapi.dingtalk.com/robot/send?access_token=xxx"
  
  markdown = 
  {
    msgtype: "link", 
    link: {
        text: "iOS #{ENV['SCHEME_NAME']} 更新了!!!", 
        title: "iOS #{ENV['SCHEME_NAME']} #{app_version} (#{app_build_version}) 内测版", 
        picUrl: "#{app_icon}", 
        messageUrl: "#{app_url}"
    }
 }

  uri = URI.parse(dingTalk_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

  response = https.request(request)
  puts "------------------------------"
  puts "Response #{response.code} #{response.message}: #{response.body}"
  end

 end
复制代码

上传到第三方内测平台(蒲公英、fir等)Fastlane 也有相关的插件,一行代码搞定,如 Fir 就是:安全

# 前往fir.im获取 api token, 将鼠标放置右上角帐号上面, 在下拉窗选择API token
# 若使用的蒲公英, 请前往 https://www.pgyer.com/ 查看上传方法
# 若是使用Firimfile, 此处为 firim 便可
firim(firim_api_token:'xxxx') 
复制代码

需求3、读取 git commit messge

TODO: 等待实现。

需求4、自动发送安装消息

我这边目前使用的钉钉进行协做,能够在相关工做群使用钉钉机器人自动发送消息。找钉钉群管理员添加一下获取 token 就行。能够向这个地址 https://oapi.dingtalk.com/robot/send?access_token=Your Token 发送纯文本、图文、markdown 等格式的消息,还能够填写须要 @ 的测试妹子们。

image-20200126212339968

其余企业微信好像也是能够的,能够自行去查看文档。

踩坑

1、定时脚本执行 /bin/sh: xxx/run.sh: Operation not permitted

缘由:
image-20200126201353427

首先我配置的定时脚本路径在 /Users/username/Desktop/code/Project/run.sh,没有和定时任务的 Plist 配置文件在一个目录下,而配置的定时脚本声明的是 #!/bin/sh,意思是使用 /bin/sh 来解释执行,可是却没有给彻底磁盘访问的权限。

解决方案:

给足访问权限就行。系统偏好设置 -> 安全性与隐私-> 彻底磁盘访问权限,查看是否有勾选☑️ 在定时脚本中声明的解释执行的 shell 的路径,就是**#!/bin/** 后面接的,有 bash 、sh、 zsh 等,个人是 sh。没有的话就添加进去。

2、在定时脚本中直接执行 fastlane 打包命令出错: /Users/username/Desktop/code/Project/run.sh : fastlane: command not found

缘由:

虽然 cd 到了当前项目目录,但仍是报 fastlane 找不到

解决方案:

使用全路径 fastlane 执行命令

/Users/username/.fastlane/bin/fastlane lane
复制代码

总结

总共折腾了一两天时间,流程基本都跑通了,还剩抓取指定时间段内的 git commit message 当作更新日志的 TODO,整体上仍是很愉悦和有成就感的,之后就能够专心干其余的事情了,打包几乎无感,也不用怕忘记。nice!

效果以下:

image-20200126205435079

相关配置文件已经上传到 GitHub 仓库,地址点击这里

参考连接

  1. Mac上,执行定时任务:launchctl

  2. Operation not permitted

  3. Fastlane

  4. 钉钉开发文档


分享我的技术学习记录和跑步马拉松训练比赛、读书笔记等内容,感兴趣的朋友能够关注个人公众号「by在水一方」。

by在水一方
相关文章
相关标签/搜索