fir-cli 2.0.9 → 2.0.14

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bdd7fc7cd378d98beff907cd71e92b014c8f2123088fbd15d092694040513d23
4
- data.tar.gz: e589b79ef22e771c660af8ec3f1eadd47aff73bf67247e296f8dc1f820588b2c
3
+ metadata.gz: 1ce0252e1ffcd6e9a73ce64fa5359fa06ce77416c93ffd394c6829481956a878
4
+ data.tar.gz: 5e8443ef24cc7d39aded9bdc1044dd9d8a11452bb081e1023dc9719aed9df0c4
5
5
  SHA512:
6
- metadata.gz: ea1824c70e3ba0aa2e25ffcf9f803b93e804efc66d8da142cce125bebb0b03084470e355f2b78e6e7629fc5366b9fec2c543518eafcd67e973ffe5b9354f16a9
7
- data.tar.gz: affbceef191ddbe5afc05fa22040c0f8d249183eee92e68644fa2ab43107e890c43df409b030df047646ff78f5fc9e28686d54a22157333a0daf6b0e7142c2fe
6
+ metadata.gz: 19439af4cd18638db3838e157db517e3c2b92045d2c27e269c75ef9eda3dc98b0c79d1d776d72f05ceca466241faefdf8cd242b4a438090019f3420fa9645aa5
7
+ data.tar.gz: 4c45e66b869e58df20966aae25780612d2c7abd7c5a287547bbe68a09dc1c6773fe4316df00c421d66bd58a08eb87fec985d5aad34a2084d8990da23b5cd5482
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  rvm:
2
- - 2.4
2
+ - 3.0
3
3
  env:
4
4
  matrix:
5
5
  - USE_OFFICIAL_GEM_SOURCE=true
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM ruby:2.6.1
1
+ FROM ruby:2.7.1
2
2
  RUN gem install bundler
3
3
  ENV LANG=C.UTF-8
4
4
  ENV WORKDIR=/fir-cli
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ✈ fir.im-cli
2
- ----
2
+ ----
3
3
 
4
4
  ![Build Status Images](https://travis-ci.org/FIRHQ/fir-cli.svg)
5
5
  [![Code Climate](https://codeclimate.com/github/FIRHQ/fir-cli/badges/gpa.svg)](https://codeclimate.com/github/FIRHQ/fir-cli)
@@ -13,11 +13,15 @@ fir.im-cli 可以通过指令查看, 上传, iOS/Android 应用.
13
13
  ![fir-cli](http://7rf35s.com1.z0.glb.clouddn.com/fir-cli-new.gif)
14
14
 
15
15
  # 重大提醒
16
- - fir.im 更换域名后, 需要升级至 `fir-cli` >= `2.0.4` 有部分用户反馈 2.0.2 无法直接使用 `gem update fir-cli` 升级到 2.0.4, 则可以尝试卸载后重新安装, 即 `gem uninstall fir-cli` 后 `gem install fir-cli`
17
- - 深信服 的 上网行为管理AC 的域名黑名单误将 fir-cli version 2.0.4 版本使用的 api.bq04.com 加入了黑名单, 我们已经联系了 深信服, 他们的回答是 `收到!已反馈!预计在3月17日左右的规则库更新,辛苦当时暂时需要使用的话先临时放通下,等规则库更新及时使用设备联网更新最新的规则库,有什么疑问您在及时反馈,感谢您的支持。
18
- 当然还有种解决办法是 更新 `fir-cli` 至 `2.0.5`, 这个版本换到了备用域名
16
+ - fir.im 更换域名至 betaqr.com 后, 需要升级至 `fir-cli` >= `2.0.4` 有部分用户反馈 2.0.2 无法直接使用 `gem update fir-cli` 升级到 2.0.4, 则可以尝试卸载后重新安装, 即 `gem uninstall fir-cli` 后 `gem install fir-cli`
17
+
19
18
 
20
19
  # 最近更新
20
+ - (2.0.14) 第三方通知加入了 app 类型, 第三方报错将忽略异常继续运行
21
+ - (2.0.13) 修正了企业微信通知的bug
22
+ - (2.0.12) 修复因为钉钉机器人不再支持base64导致无法显示二维码,另外开始支持钉钉加签方式的鉴权, 参数为 --dingtalk_secret
23
+ - (2.0.11) 兼容了 ruby 3.0
24
+ - (2.0.10) 飞书支持了 V2 版本的机器人推送
21
25
  - (2.0.9) publish 支持了 企业微信通知 可以使用 --wxwork_access_token 或 --wxwork_webhook, 增加了回调超时时间至20秒
22
26
  - (2.0.8) publish 支持 飞书通知, 可使用 `feishu_access_token` 和 `feishu_custom_message`, 详情见 `fir publish --help`
23
27
  - (2.0.7) 修复了提示 token 错误的问题
@@ -47,24 +51,49 @@ fir.im-cli 可以通过指令查看, 上传, iOS/Android 应用.
47
51
 
48
52
  ## 热门问题
49
53
 
50
- ### 如何配合 jenkins 使用?
54
+ ### 啥是 钉钉 / 企业微信 / 飞书 的 `access_token` ?
55
+
56
+ 就是回调地址中的长得最像 access_token 的东西
57
+
58
+ ```
59
+ 钉钉: https://oapi.dingtalk.com/robot/send?access_token=xxxxx
60
+ 就是 xxx 那部分
61
+
62
+ 企业微信: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx-xxxx-xxxx-xxxx-xxxxx
63
+ 就是 xxxxx-xxxx-xxxx-xxxx-xxxxx 那部分
64
+
65
+ https://open.feishu.cn/open-apis/bot/hook/xxxxxxxxxxxxxxxxxxx
66
+
67
+ 就是 xxxxxxxxxxxxxxxx 那部分
68
+
69
+ ```
70
+
71
+
72
+
73
+
74
+
75
+ ### 如何配合 jenkins 使用?
51
76
 
52
77
  参见 blog [http://blog.betaqr.com/use-fir-cli-in-jenkins/](http://blog.betaqr.com/use-fir-cli-in-jenkins/)
53
78
 
54
- ### Circle CI, Travis CI 或 Github Actions 等境外服务上, 有概率超时, 能否解决?
79
+ 这里有个快速检查脚本, 可以在 jenkins 中新建一个 脚本, 进行检查
55
80
 
56
- 2.0.3 版本 及其以上, 可以申请海外加速内测资格, 开启后可以使用海外加速上传
81
+ ```
82
+ #!/bin/bash --login
57
83
 
84
+ rvm list # 确保 rvm 正确安装, 如果直接通过系统安装ruby, 可以注释此行
85
+ ruby -v # 查看 ruby 的版本, 请确保大于 2.4.0
86
+ gem install fir-cli # 现场安装fir-cli , 如果安装过, 则会略过
87
+ fir -v # 查看 fir-cli 的版本
58
88
 
59
- 由于监管要求, 我们必须将服务于存储放置在境内. 由于众所周知的原因, 国内外连通性的表现不太好, 虽然我们的存储服务商 阿里云 提供了 OSS 境外加速服务, 但是高达 1.25 元/GB 的传输成本确实我们也没办法负担.
89
+ # 在这里执行 fir publish xxxxx
90
+ ```
60
91
 
61
92
 
93
+ ### 在 Circle CI, Travis CI 或 Github Actions 等境外服务上, 有概率超时, 能否解决?
62
94
 
63
- 目前我们提供三种临时解决方案来缓解问题(2.0.2以下版本):
95
+ 2.0.3 版本 及其以上, 可以申请海外加速内测资格, 开启后可以使用海外加速上传 `--oversea_turbo`
64
96
 
65
- 1. 设置较长的超时时间 如 `FIR_TIMEOUT=300 fir publish xxxx`, 则可将超时时间设置为 300 秒.
66
- 2. 如果fir-cli 版本 >= 2.0.0, 也可在出现超时后, 使用 `--switch-to-qiniu` 来切换到我们的另外一条存储线路. 如 `fir publish xxxx.apk --switch-to-qiniu`, 多一条线路备选.
67
- 3. 如果确实对这方面服务要求很高, 则可购买我们的私有部署服务. 我们可以在 aws 上部署一套专供您使用, 具体情况可以与客服或者加我微信进行沟通.
68
97
 
69
98
  更多细节请参考 [https://github.com/FIRHQ/fir-cli/issues/260](https://github.com/FIRHQ/fir-cli/issues/260)
70
99
 
@@ -93,13 +122,13 @@ fir-cli 提供对 aab 文件有限程度支持的上传与下载. 在使用 fir-
93
122
 
94
123
  ### 我想将 我上传的版本展示在下载的页面上
95
124
 
96
- 可以在 publish 的时候使用 --force_pin_history 这样 这个上传的版本即成为 "历史版本", 会在下载页面里一直显示. 当有新的版本上传后, 这个版本会作为 "历史版本" 在下载页面中展示.
125
+ 可以在 publish 的时候使用 --force_pin_history 这样 这个上传的版本即成为 "历史版本", 会在下载页面里一直显示. 当有新的版本上传后, 这个版本会作为 "历史版本" 在下载页面中展示.
97
126
 
98
127
  当版本设置为历史版本后, 用户可以直接下载指定的版本, 由于因成本原因, 一个 app 最多的 "历史版本" 为 30 个, 如果有用户有特殊需求, 可以与我们取得联系进行单独修改
99
128
 
100
129
  当达到上限后, 如果继续标记 force_pin_history, 则历史版本的最老版本(以上传时间为准)会被移出历史版本列表
101
130
 
102
- ### 境外上传老出现 stream closed
131
+ ### 境外上传老出现 stream closed
103
132
 
104
133
  因为网络时延问题, 可传入环境变量 `FIR_TIMEOUT=xxx` 进行超时时间设置
105
134
 
@@ -114,22 +143,22 @@ fir-cli 提供对 aab 文件有限程度支持的上传与下载. 在使用 fir-
114
143
  - [fir publish 发布应用到 fir.im](https://github.com/FIRHQ/fir-cli/blob/master/doc/publish.md)
115
144
  - [fir upgrade 升级相关](https://github.com/FIRHQ/fir-cli/blob/master/doc/upgrade.md)
116
145
 
117
- ## Docker 运行 fir-cli
146
+ ## Docker 运行 fir-cli
118
147
 
119
148
  ### 准备工作
120
149
  1. 将自己需要的文件挂载到 docker 中, 之后即可直接运行
121
- 2. 将自己的 API_TOKEN 以环境变量的形式传入container
150
+ 2. 将自己的 API_TOKEN 以环境变量的形式传入container
122
151
 
123
152
  ### 如何运行
124
153
 
125
- 假设 我需要上传桌面的 1.apk
154
+ 假设 我需要上传桌面的 1.apk
126
155
 
127
156
  ```
128
- docker run -e API_TOKEN=您的token -v 您的上传文件的目录的绝对路径:/tmp firhq/fir-cli:latest publish /tmp/你的文件
157
+ docker run -e API_TOKEN=您的token -v 您的上传文件的目录的绝对路径:/tmp firhq/fir-cli:latest publish /tmp/你的文件
129
158
 
130
159
  # 如 `docker run -e API_TOKEN=xxxxxxxe -v /Users/atpking/Desktop:/tmp firhq/fir-cli:latest publish /tmp/1.apk`
131
160
 
132
- # 实际含义是把我的桌面挂载到 docker 里的 /tmp 目录 之后上传 docker 文件里的 /tmp/1.apk
161
+ # 实际含义是把我的桌面挂载到 docker 里的 /tmp 目录 之后上传 docker 文件里的 /tmp/1.apk
133
162
  # 也可以修改为其他目录
134
163
  ```
135
164
 
@@ -137,13 +166,13 @@ docker run -e API_TOKEN=您的token -v 您的上传文件的目录的绝对路
137
166
 
138
167
  - 联系微信 `atpking`, 请注明 "fir-cli 交流"
139
168
 
140
- - 使用 Github 的 [Issue](https://github.com/FIRHQ/fir-cli/issues)
169
+ - 使用 Github 的 [Issue](https://github.com/FIRHQ/fir-cli/issues)
141
170
 
142
- ## 特别感谢
171
+ ## 特别感谢
143
172
 
144
173
  - 感谢 sparkrico 提供修正的 https://github.com/sparkrico/ruby_apk 解决了 android 解析的问题
145
- - 感谢 fabcz 同学对企业微信的通知的支持 https://github.com/FIRHQ/fir-cli/pull/277
174
+ - 感谢 fabcz 同学对企业微信的通知的支持 https://github.com/FIRHQ/fir-cli/pull/277
146
175
 
147
176
  ## 鼓励维护
148
177
 
149
- 挂了好久没都人鼓励维护, 想想算了吧
178
+ hia~ hia~ hia~
data/doc/publish.md CHANGED
@@ -3,33 +3,56 @@
3
3
  `fir publish` 命令用于可以发布应用到 fir.im, 支持 ipa 和 apk 文件.
4
4
 
5
5
  ```sh
6
- $ fir publish --help
7
6
  Usage:
8
7
  fir publish APP_FILE_PATH
9
8
 
10
9
  Options:
11
- -s, [--short=SHORT] # Set custom short link
12
- -c, [--changelog=CHANGELOG] # Set changelog
13
- -Q, [--qrcode], [--no-qrcode] # Generate qrcode
14
- [--open], [--no-open] # true/false if open for everyone
15
- [--password=PASSWORD] # Set password for app
16
- -T, [--token=TOKEN] # User's API Token at fir.im
17
- -L, [--logfile=LOGFILE] # Path to writable logfile
18
- -R, [--need_release_id] # show release_id in download_url
19
- -D, [--dingtalk_accesss_token=DINGTALK_ACCESS_TOKEN] # dingtalk notification
20
- -V, [--verbose], [--no-verbose] # Show verbose
21
- # Default: true
22
- -q, [--quiet], [--no-quiet] # Silence commands
23
- -h, [--help], [--no-help] # Show this help message and quit
10
+ -s, [--short=SHORT] # 设置short
11
+ -c, [--changelog=CHANGELOG] # 设置更新内容, 可是文件地址也可直接是内容
12
+ -Q, [--qrcode], [--no-qrcode] # 生成二维码图片在当前目录
13
+ [--need-ansi-qrcode], [--no-need-ansi-qrcode] #
14
+ -R, [--need-release-id], [--no-need-release-id] # 在下载地址中包含具体版本(警告, 每个app 最多保留30个版本, 超过后会失效最老的版本)
15
+ -H, [--force-pin-history], [--no-force-pin-history] # 将版本留在下载页(即在新版本上传后, 下面仍然有旧版本的二维码可以引导)
16
+ -S, [--skip-update-icon], [--no-skip-update-icon] # 跳过更新图标
17
+ [--specify-icon-file=SPECIFY_ICON_FILE] # 指定更新图标
18
+ [--skip-fir-cli-feedback], [--no-skip-fir-cli-feedback] # 跳过 用来做统计fir-cli的反馈(用于改进fir-cli)
19
+ [--specify-app-display-name=SPECIFY_APP_DISPLAY_NAME] # 指定app 名称
20
+ -N, [--switch-to-qiniu], [--no-switch-to-qiniu] # 切换到七牛线路上传(当上传较慢时, 可试试这个)
21
+ [--oversea-turbo], [--no-oversea-turbo] # 海外加速(需联系微信 atpking 开通)
22
+ -m, [--mappingfile=MAPPINGFILE] # mappingfile
23
+ -D, [--dingtalk-access-token=DINGTALK_ACCESS_TOKEN] # 上传完毕后 若发送至钉钉, 则填写钉钉的webhook 的access_token
24
+ [--dingtalk-custom-message=DINGTALK_CUSTOM_MESSAGE] # 自定义钉钉消息 (针对钉钉新版webhook 需要校验的时候, 可以做关键字)
25
+ [--dingtalk-at-phones=DINGTALK_AT_PHONES] # 钉钉 at 某人手机号
26
+ [--dingtalk-at-all], [--no-dingtalk-at-all]
27
+ [--feishu-access-token=FEISHU_ACCESS_TOKEN] # 飞书的webhook 的access_token
28
+ [--feishu-custom-message=FEISHU_CUSTOM_MESSAGE] # 自定义飞书消息
29
+ [--wxwork-webhook=WXWORK_WEBHOOK] # 企业微信的 webhook 地址 (注意这里与 access_token 只需要填写一个参数即可)
30
+ [--wxwork-access-token=WXWORK_ACCESS_TOKEN] # 企业微信的 webhook access_token (注意这里与 access_token 只需要填写一个参数即可)
31
+ [--wxwork-custom-message=WXWORK_CUSTOM_MESSAGE] # 企业微信 的自定义消息
32
+ [--wxwork-pic-url=WXWORK_PIC_URL] # 企业微信的图片链接, best size is 1068x455
33
+ [--open], [--no-open] # 是否下载可见, 默认open
34
+ [--password=PASSWORD] # 下载页面密码, 默认为空
35
+ [--bundletool-jar-path=BUNDLETOOL_JAR_PATH] # (beta) 上传AAB 文件的特殊指令: upload aab file command: to specify bundletool.jar if command bundletool can not run directly
36
+ [--auto-download-bundletool-jar], [--no-auto-download-bundletool-jar] # (beta) 上传AAB 文件的特殊指令: upload aab file command: would download bundletool when invoke bundletool failure
37
+ -T, [--token=TOKEN] # betaqr.com(fir.im) 账户的 API_TOKEN
38
+ -L, [--logfile=LOGFILE] # Path to writable logfile
39
+ -V, [--verbose], [--no-verbose] # Show verbose
40
+ # Default: true
41
+ -q, [--quiet], [--no-quiet] # Silence commands
42
+ -h, [--help], [--no-help] # Show this help message and quit
43
+
44
+ Description:
45
+ `publish` command will publish your app file to fir.im, also the command support to publish app's short & changelog.
46
+
47
+ Example:
48
+
49
+ $ fir p <app file path> [-c <changelog> -s <custom short link> -Q -T <your api token>]
50
+
51
+ $ fir p <app file path> [-c <changelog> -s <custom short link> --password=123456 --open=false -Q -T <your api token>]
52
+
53
+ $ fir p <app file path> [-c <changelog> -s <custom short link> -m <mapping file path> -P <bughd project id> -Q -T <your
54
+ api token>]
24
55
  ```
25
56
 
26
- 相关参数详解:
27
57
 
28
- - `-s` 参数, 自定义发布后的短链接地址.
29
- - `-c` 参数, 自定义发布时的 changelog, 支持字符串与文件两种方式, 即 `--changelog='this is changelog'` 和 `--changelog='/Users/fir-cli/changelog'`.
30
- - `-Q` 参数, 是否生成发布后二维码, 默认为不生成, 加上 `-Q` 参数后会在当前目录生成一张二维码图片, 扫描该图片即可下载该应用.
31
- - `-R` 参数, 显示具体版本, 会在发布结束后的下载地址中生成指定的版本
32
- - `-D` 参数, 钉钉机器人的access_token, 填写后当上传完毕, 会发送至钉钉机器人
33
- - `--open` 参数, 设置发布后的应用是否开放给所有人下载, 关闭开放使用 `--no-open` 参数.
34
- - `--password` 参数, 设置发布后的应用密码
35
58
 
data/fir-cli.gemspec CHANGED
@@ -27,6 +27,11 @@ Gem::Specification.new do |spec|
27
27
  /_/ /___/_/ |_| \____/_____/___/
28
28
 
29
29
  ## 更新记录
30
+ - (2.0.14) 第三方通知加入了 app 类型, 第三方报错将不再直接报出异常
31
+ - (2.0.13) 修复了无法跳过企业微信通知逻辑的bug
32
+ - (2.0.12) 修复因为钉钉机器人不再支持base64导致无法显示二维码,另外开始支持钉钉加签方式的鉴权, 参数为 --dingtalk_secret
33
+ - (2.0.11) 兼容了 ruby 3.0 版本, 增加了环境变量FEISHU_TIMEOUT,可以多给飞书一些超时时间
34
+ - (2.0.10) 飞书支持了 V2 版本的机器人推送
30
35
  - (2.0.9) publish 支持了 企业微信通知 可以使用 --wxwork_access_token 或 --wxwork_webhook, 增加了回调超时时间至20秒
31
36
  - (2.0.8) publish 支持 飞书通知, 可使用 `feishu_access_token` 和 `feishu_custom_message`, 详情见 `fir publish --help`
32
37
  - (2.0.7) 修复了提示 token 有问题的错误
@@ -51,12 +56,13 @@ Gem::Specification.new do |spec|
51
56
  # spec.add_development_dependency 'byebug'
52
57
  spec.add_development_dependency 'minitest', '~> 5.7'
53
58
  spec.add_development_dependency 'pry', '~> 0.10'
54
-
59
+
55
60
  spec.add_dependency 'admqr_knife', '~> 0.1.5'
56
61
  spec.add_dependency 'thor', '~> 0.19'
57
62
  spec.add_dependency 'rest-client', '~> 2.0'
58
63
  spec.add_dependency 'ruby_android_apk', '~> 0.7.7.1'
59
64
  spec.add_dependency 'rqrcode', '~> 0.7'
65
+ spec.add_dependency 'rexml'
60
66
  spec.add_dependency 'CFPropertyList'
61
- spec.add_dependency 'api_tools', '~> 0.1.0'
67
+ spec.add_dependency 'api_tools', '~> 0.1.1'
62
68
  end
data/lib/fir.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # require 'byebug'
3
4
  require 'thor'
4
5
  require 'logger'
5
6
  require 'yaml'
data/lib/fir/api.yml CHANGED
@@ -2,6 +2,7 @@ fir:
2
2
  domain: 'http://www.betaqr.com'
3
3
  base_url: 'http://fir-api.admqr.com'
4
4
  user_url: 'http://fir-api.admqr.com/user'
5
+ user_feishu_access_token: 'http://fir-api.admqr.com/user/fetch_feishu_v3_token'
5
6
  app_url: 'http://fir-api.admqr.com/apps'
6
7
  udids_url: 'http://fir-api.admqr.com/devices/multi_udid'
7
8
 
data/lib/fir/cli.rb CHANGED
@@ -125,7 +125,8 @@ module FIR
125
125
  method_option :dingtalk_access_token, type: :string, aliases: '-D', desc: 'Send msg to dingtalk, only need access_token, not whole url'
126
126
  method_option :dingtalk_custom_message, type: :string, desc: 'add custom message to dingtalk'
127
127
  method_option :dingtalk_at_phones, type: :string, desc: 'at some phones, split by , eg: 13111111111,13111111112'
128
- method_option :dingtalk_at_all, type: :boolean, default: false
128
+ method_option :dingtalk_at_all, type: :boolean, default: false
129
+ method_option :dingtalk_secret, type: :string, desc: 'dingtalk bot secret code (eg: SEC********)'
129
130
 
130
131
  method_option :feishu_access_token, type: :string, desc: 'Send msg to feishu, need access_token, not whole url'
131
132
  method_option :feishu_custom_message, type: :string, desc: 'add custom message to feishu'
@@ -0,0 +1,67 @@
1
+ require 'json'
2
+ require 'openssl'
3
+ require 'base64'
4
+ require 'cgi'
5
+ # require 'byebug'
6
+ class DingtalkHelper
7
+ attr_accessor :app_info, :options, :access_token, :qrcode_path, :image_key, :download_url, :title
8
+ include FIR::Config
9
+
10
+ def initialize(app_info, options, qrcode_path, download_url)
11
+ @app_info = app_info
12
+ @options = options
13
+ @access_token = @options[:dingtalk_access_token]
14
+ @secret = @options[:dingtalk_secret]
15
+ @qrcode_path = qrcode_path
16
+ @download_url = download_url
17
+ end
18
+
19
+ def send_msg
20
+ return if options[:dingtalk_access_token].blank?
21
+
22
+ api_domain = @app_info[:api_url]
23
+ title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]}) #{@app_info[:type]}"
24
+ payload = {
25
+ "msgtype": 'markdown',
26
+ "markdown": {
27
+ "title": "#{title} uploaded",
28
+ "text": "#### #{title}\n\n>uploaded at #{Time.now}\n\nurl: #{download_url}\n\n#{options[:dingtalk_custom_message]}\n\n ![](#{api_domain}/welcome/qrcode?url=#{download_url})"
29
+ }
30
+ }
31
+ build_dingtalk_at_info(payload)
32
+ url = "https://oapi.dingtalk.com/robot/send?access_token=#{options[:dingtalk_access_token]}"
33
+ if options[:dingtalk_secret]
34
+ info = secret_cal(options[:dingtalk_secret])
35
+ url = "#{url}&timestamp=#{info[:timestamp]}&sign=#{info[:sign]}"
36
+ end
37
+
38
+ x = DefaultRest.post(url, payload)
39
+ rescue StandardError => e
40
+ end
41
+
42
+ def build_dingtalk_at_info(payload)
43
+ answer = {}
44
+ answer[:isAtAll] = options[:dingtalk_at_all]
45
+
46
+ unless options[:dingtalk_at_phones].blank?
47
+ answer[:atMobiles] = options[:dingtalk_at_phones].split(',')
48
+ payload[:markdown][:text] += options[:dingtalk_at_phones].split(',').map { |x| "@#{x}" }.join(',')
49
+ end
50
+
51
+ payload[:at] = answer
52
+ end
53
+
54
+ def secret_cal(secret)
55
+ timestamp = Time.now.to_i * 1000
56
+ secret_enc = secret.encode('utf-8')
57
+ str = "#{timestamp}\n#{secret}"
58
+ string_to_sign_enc = str.encode('utf-8')
59
+
60
+ hmac = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret_enc, string_to_sign_enc)
61
+ {
62
+ timestamp: timestamp,
63
+ sign: CGI.escape(Base64.encode64(hmac).strip)
64
+ }
65
+
66
+ end
67
+ end
@@ -0,0 +1,96 @@
1
+ require 'json'
2
+ # require 'byebug'
3
+ class FeishuHelper
4
+ attr_accessor :app_info, :options, :feishu_access_token, :qrcode_path, :image_key, :download_url, :title
5
+ include FIR::Config
6
+
7
+ def initialize(app_info, options, qrcode_path, download_url)
8
+ @app_info = app_info
9
+ @options = options
10
+ @feishu_access_token = @options[:feishu_access_token]
11
+ @qrcode_path = qrcode_path
12
+ @download_url = download_url
13
+
14
+ @title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]}) #{@app_info[:type]}"
15
+ end
16
+
17
+ def send_msg
18
+ return if feishu_access_token.blank?
19
+
20
+ answer = v2_request
21
+ v1_request if answer.dig('ok') == 'false'
22
+ end
23
+
24
+ def v2_request
25
+ url = "https://open.feishu.cn/open-apis/bot/v2/hook/#{feishu_access_token}"
26
+ x = build_v2_info
27
+ # byebug
28
+ DefaultRest.post(url, x, {timeout: ENV['FEISHU_TIMEOUT'] ? ENV['FEISHU_TIMEOUT'].to_i : 30 })
29
+ end
30
+
31
+ def v1_request
32
+ url = "https://open.feishu.cn/open-apis/bot/hook/#{feishu_access_token}"
33
+ payload = {
34
+ "title": "#{title} uploaded",
35
+ "text": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:feishu_custom_message]}\n"
36
+ }
37
+ DefaultRest.post(url, payload, {timeout: ENV['FEISHU_TIMEOUT'] ? ENV['FEISHU_TIMEOUT'].to_i : 30 })
38
+ end
39
+
40
+ private
41
+
42
+ def build_v2_info
43
+ {
44
+ msg_type: 'post',
45
+ content: {
46
+ post: {
47
+ zh_cn: {
48
+ title: title,
49
+ content: [build_info_tags, [build_image_tag]]
50
+ }
51
+ }
52
+ }
53
+ }
54
+ end
55
+
56
+ def build_info_tags
57
+ text = "#{title} uploaded at #{Time.now}\n#{options[:feishu_custom_message]}\n"
58
+ [
59
+ {
60
+ "tag": 'text',
61
+ "text": text
62
+ },
63
+ {
64
+ "tag": 'a',
65
+ "text": download_url,
66
+ "href": download_url
67
+ }
68
+ ]
69
+ end
70
+
71
+ def build_image_tag
72
+ {
73
+ "tag": 'img',
74
+ "image_key": upload_qr_code,
75
+ "width": 300,
76
+ "height": 300
77
+ }
78
+ end
79
+
80
+ def fetch_image_access_token
81
+ answer = DefaultRest.post(fir_api[:fetch_feishu_v3_token] || 'http://fir-api.admqr.com/user/fetch_feishu_v3_token', {})
82
+ answer[:feishu_v3_token]
83
+ end
84
+
85
+ def upload_qr_code
86
+ answer = RestClient.post('https://open.feishu.cn/open-apis/image/v4/put/', {
87
+ image_type: 'message',
88
+ image: File.new(qrcode_path, 'rb')
89
+ }, {
90
+ 'Authorization' => "Bearer #{fetch_image_access_token}"
91
+ })
92
+
93
+ json = JSON.parse(answer)
94
+ json.dig('data', 'image_key')
95
+ end
96
+ end
@@ -1,16 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # require 'byebug'
4
+
5
+ require_relative './third_notifier_module'
4
6
  require_relative './qiniu_uploader'
5
7
  require_relative './ali_uploader'
8
+ require_relative '../util/feishu_helper'
9
+ require_relative '../util/dingtalk_helper'
6
10
 
7
11
  module FIR
8
12
  module Publish
13
+ include FIR::ThirdNotifierModule
9
14
  def publish(*args, options)
10
15
  initialize_publish_options(args, options)
11
16
  logger_info_publishing_message
12
17
 
13
18
  logger.info 'begin to upload ...'
19
+ logger.info "fir-cli version #{FIR::VERSION} (#{RUBY_VERSION} @ #{RUBY_PLATFORM})"
14
20
  received_app_info = upload_app
15
21
 
16
22
  short = received_app_info[:short]
@@ -25,10 +31,8 @@ module FIR
25
31
  logger.info "Published succeed: #{download_url}"
26
32
 
27
33
  qrcode_path = build_qrcode download_url
28
-
29
- dingtalk_notifier(download_url, qrcode_path)
30
- feishu_notifier(download_url)
31
- wxwork_notifier(download_url)
34
+
35
+ notify_to_thirds(download_url, qrcode_path)
32
36
 
33
37
  upload_mapping_file_with_publish
34
38
 
@@ -92,9 +96,7 @@ module FIR
92
96
  app_info_dict
93
97
  rescue StandardError => e
94
98
  puts e.message
95
- if e.respond_to?(e.response) && e.respond_to?(e.response.body)
96
- puts e.response.body
97
- end
99
+ puts e.response.body if e.respond_to?(e.response) && e.respond_to?(e.response.body)
98
100
  raise e
99
101
  end
100
102
 
@@ -193,59 +195,6 @@ module FIR
193
195
  api_token: @token
194
196
  end
195
197
 
196
- def dingtalk_notifier(download_url, qrcode_path)
197
- return if options[:dingtalk_access_token].blank?
198
-
199
- title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]})"
200
- payload = {
201
- "msgtype": 'markdown',
202
- "markdown": {
203
- "title": "#{title} uploaded",
204
- "text": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:dingtalk_custom_message]}\n![app二维码](data:image/png;base64,#{Base64.strict_encode64(File.read(open(qrcode_path)))})"
205
- # "text": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:dingtalk_custom_message]}\n"
206
- }
207
- }
208
- build_dingtalk_at_info(payload)
209
- url = "https://oapi.dingtalk.com/robot/send?access_token=#{options[:dingtalk_access_token]}"
210
-
211
- # 用完了二维码, 就删了
212
- File.delete(qrcode_path) unless @export_qrcode
213
-
214
- DefaultRest.post(url, payload)
215
- rescue StandardError => e
216
- logger.warn "Dingtalk send error #{e.message}"
217
- end
218
-
219
- def feishu_notifier(download_url)
220
- return if options[:feishu_access_token].blank?
221
- title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]})"
222
- url = "https://open.feishu.cn/open-apis/bot/hook/#{options[:feishu_access_token]}"
223
- payload = {
224
- "title": "#{title} uploaded",
225
- "text": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:feishu_custom_message]}\n"
226
- }
227
- DefaultRest.post(url, payload)
228
- end
229
-
230
- def wxwork_notifier(download_url)
231
- webhook_url = options[:wxwork_webhook]
232
- webhook_url ||= "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=#{options[:wxwork_access_token]}"
233
- return if webhook_url.blank?
234
-
235
- title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]})"
236
- payload = {
237
- "msgtype": "news",
238
- "news": {
239
- "articles": [{
240
- "title": "#{title} uploaded",
241
- "description": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:wxwork_custom_message]}\n",
242
- "url": download_url,
243
- "picurl": options[:wxwork_pic_url]
244
- }],
245
- },
246
- }
247
- DefaultRest.post(webhook_url, payload)
248
- end
249
198
 
250
199
  def initialize_publish_options(args, options)
251
200
  @options = options
@@ -254,10 +203,10 @@ module FIR
254
203
 
255
204
  check_file_exist(@file_path)
256
205
  check_supported_file(@file_path)
257
-
206
+
258
207
  @token = options[:token] || current_token
259
208
  check_token_cannot_be_blank(@token)
260
-
209
+
261
210
  @changelog = read_changelog(options[:changelog]).to_s.to_utf8
262
211
  @short = options[:short].to_s
263
212
  @passwd = options[:password].to_s
@@ -269,7 +218,10 @@ module FIR
269
218
  @app_id = @uploading_info[:id]
270
219
 
271
220
  @skip_update_icon = options[:skip_update_icon]
221
+
272
222
  @force_pin_history = options[:force_pin_history]
223
+
224
+ @app_info[:api_url] = fir_api[:base_url]
273
225
  unless options[:specify_icon_file].blank?
274
226
  @specify_icon_file_path = File.absolute_path(options[:specify_icon_file])
275
227
  end
@@ -280,19 +232,5 @@ module FIR
280
232
 
281
233
  File.exist?(changelog) ? File.read(changelog) : changelog
282
234
  end
283
-
284
-
285
-
286
- def build_dingtalk_at_info(payload)
287
- answer = {}
288
- answer[:isAtAll] = options[:dingtalk_at_all]
289
-
290
- unless options[:dingtalk_at_phones].blank?
291
- answer[:atMobiles] = options[:dingtalk_at_phones].split(',')
292
- payload[:markdown][:text] += options[:dingtalk_at_phones].split(',').map { |x| "@#{x}" }.join(',')
293
- end
294
-
295
- payload[:at] = answer
296
- end
297
235
  end
298
236
  end
@@ -0,0 +1,40 @@
1
+ module FIR
2
+ module ThirdNotifierModule
3
+ def notify_to_thirds(download_url, qrcode_path)
4
+ dingtalk_notifier(download_url, qrcode_path)
5
+ feishu_notifier(download_url, qrcode_path)
6
+ wxwork_notifier(download_url)
7
+ rescue => e
8
+ logger.warn "third notifiers error #{e.message}"
9
+ end
10
+
11
+ def dingtalk_notifier(download_url, qrcode_path)
12
+ DingtalkHelper.new(@app_info, options, qrcode_path, download_url).send_msg
13
+ end
14
+
15
+ def feishu_notifier(download_url, qrcode_path)
16
+ FeishuHelper.new(@app_info, options, qrcode_path, download_url).send_msg
17
+ end
18
+
19
+ def wxwork_notifier(download_url)
20
+ return if options[:wxwork_webhook].blank? && options[:wxwork_access_token].blank?
21
+
22
+ webhook_url = options[:wxwork_webhook]
23
+ webhook_url ||= "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=#{options[:wxwork_access_token]}"
24
+
25
+ title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]}) #{@app_info[:type]}"
26
+ payload = {
27
+ "msgtype": 'news',
28
+ "news": {
29
+ "articles": [{
30
+ "title": "#{title} uploaded",
31
+ "description": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:wxwork_custom_message]}\n",
32
+ "url": download_url,
33
+ "picurl": options[:wxwork_pic_url]
34
+ }]
35
+ }
36
+ }
37
+ DefaultRest.post(webhook_url, payload)
38
+ end
39
+ end
40
+ end
data/lib/fir/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module FIR
4
- VERSION = '2.0.9'
4
+ VERSION = '2.0.14'
5
5
  end
data/test/test_helper.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  # CodeClimate::TestReporter.start
4
- require 'codeclimate-test-reporter'
5
- require 'simplecov'
6
- SimpleCov.start
7
4
 
8
5
 
9
6
  require 'minitest/autorun'
@@ -80,7 +77,7 @@ end
80
77
 
81
78
  # 跑完测试之后再发结果到Codelimate
82
79
  # 测试CODECLIMATE_REPO_TOKEN: c454b9a54151b3ed3e18949279aec49d6a25bf507706815f99a919f1c01679ed
83
- Minitest.after_run do
80
+ Minitest.after_run do
84
81
  COVERAGE_FILE = "coverage/.resultset.json".freeze
85
82
  if (repo_token = ENV["CODECLIMATE_REPO_TOKEN"]) && !repo_token.empty?
86
83
  if File.exist?(COVERAGE_FILE)
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fir-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.9
4
+ version: 2.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - NaixSpirit
8
8
  - atpking
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-03-26 00:00:00.000000000 Z
12
+ date: 2021-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -137,6 +137,20 @@ dependencies:
137
137
  - - "~>"
138
138
  - !ruby/object:Gem::Version
139
139
  version: '0.7'
140
+ - !ruby/object:Gem::Dependency
141
+ name: rexml
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :runtime
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
140
154
  - !ruby/object:Gem::Dependency
141
155
  name: CFPropertyList
142
156
  requirement: !ruby/object:Gem::Requirement
@@ -157,14 +171,14 @@ dependencies:
157
171
  requirements:
158
172
  - - "~>"
159
173
  - !ruby/object:Gem::Version
160
- version: 0.1.0
174
+ version: 0.1.1
161
175
  type: :runtime
162
176
  prerelease: false
163
177
  version_requirements: !ruby/object:Gem::Requirement
164
178
  requirements:
165
179
  - - "~>"
166
180
  - !ruby/object:Gem::Version
167
- version: 0.1.0
181
+ version: 0.1.1
168
182
  description: fir.im command tool, support iOS and Android
169
183
  email:
170
184
  - atpking@gmail.com
@@ -218,6 +232,8 @@ files:
218
232
  - lib/fir/util/build_common.rb
219
233
  - lib/fir/util/build_ipa.rb
220
234
  - lib/fir/util/config.rb
235
+ - lib/fir/util/dingtalk_helper.rb
236
+ - lib/fir/util/feishu_helper.rb
221
237
  - lib/fir/util/http.rb
222
238
  - lib/fir/util/info.rb
223
239
  - lib/fir/util/login.rb
@@ -232,6 +248,7 @@ files:
232
248
  - lib/fir/util/publish.rb
233
249
  - lib/fir/util/publisher.rb
234
250
  - lib/fir/util/qiniu_uploader.rb
251
+ - lib/fir/util/third_notifier_module.rb
235
252
  - lib/fir/version.rb
236
253
  - lib/fir/xcode_wrapper.sh
237
254
  - lib/fir_cli.rb
@@ -254,7 +271,10 @@ metadata: {}
254
271
  post_install_message: "\n ______________ ________ ____\n /
255
272
  ____/ _/ __ \\ / ____/ / / _/\n / /_ / // /_/ /_____/ / / / /
256
273
  /\n / __/ _/ // _, _/_____/ /___/ /____/ /\n /_/ /___/_/ |_| \\____/_____/___/\n\n
257
- \ ## 更新记录\n - (2.0.9) publish 支持了 企业微信通知 可以使用 --wxwork_access_token 或 --wxwork_webhook,
274
+ \ ## 更新记录\n - (2.0.14) 第三方通知加入了 app 类型, 第三方报错将不再直接报出异常\n - (2.0.13) 修复了无法跳过企业微信通知逻辑的bug\n
275
+ \ - (2.0.12) 修复因为钉钉机器人不再支持base64导致无法显示二维码,另外开始支持钉钉加签方式的鉴权, 参数为 --dingtalk_secret\n
276
+ \ - (2.0.11) 兼容了 ruby 3.0 版本, 增加了环境变量FEISHU_TIMEOUT,可以多给飞书一些超时时间\n - (2.0.10) 飞书支持了
277
+ V2 版本的机器人推送\n - (2.0.9) publish 支持了 企业微信通知 可以使用 --wxwork_access_token 或 --wxwork_webhook,
258
278
  增加了回调超时时间至20秒\n - (2.0.8) publish 支持 飞书通知, 可使用 `feishu_access_token` 和 `feishu_custom_message`,
259
279
  详情见 `fir publish --help`\n - (2.0.7) 修复了提示 token 有问题的错误\n - (2.0.6) 将校验文件是否存在提前\n
260
280
  \ - (2.0.5) 更换了上传域名, 避免与 深信服的设备冲突\n - (2.0.4) 修复了 cdn 不支持 patch 方法透传, 导致在修改 app
@@ -284,7 +304,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
284
304
  version: '0'
285
305
  requirements: []
286
306
  rubygems_version: 3.0.3
287
- signing_key:
307
+ signing_key:
288
308
  specification_version: 4
289
309
  summary: fir.im command tool
290
310
  test_files: