fir-cli 2.0.7 → 2.0.12

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: 967038e356ad00c23c84e175e188cd207535c61f38aa61be8239d6098e9bc38b
4
- data.tar.gz: 15e60d63ee583736cffe5762a791d442cd84b2b69d688fabec1cf6bf0c108eeb
3
+ metadata.gz: 954e969109ed3d6d61b3ca1a736f3078607fc56bfb079e225042d8badd061902
4
+ data.tar.gz: 9a07109ea940a55fac9a95794261536c622e068d53ea26f6fa99d493ba2acea8
5
5
  SHA512:
6
- metadata.gz: eb20ac7ae2209fcb33e6a23a71262b58bae83c8ee5c116f99724c8b8d35a187b09c9c3cbe742707ae65a197090049769e30ff8ef30047df900a32acc41c35da1
7
- data.tar.gz: 03e47091c491838a8c6b1fd2f45c91def50c29e276cc9764567f82e3dfd8bb771aa8a3ca718255634becdb688abd4f4aec43f63dc932f71794df3f4a9eb88f3c
6
+ metadata.gz: 78807f3b119d7386fdd67b3073983edfb61b68cfb77b7b0efd2746cc32b37eb27b8f99d4b736b7b541d3d7b75154551d701b0b6a3449a4a1dfd05d5ed7d6ddad
7
+ data.tar.gz: 3acc0e40268677755254abf3e9232eedc3765b34f26983fc8a34d4eed089dee22fe4f8e742039f6802395c0670d9010ccd2d6ce23608ed0ad8b5ea8277b5f8fc
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/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 更换域名后, 需要升级至 `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.12) 修复因为钉钉机器人不再支持base64导致无法显示二维码,另外开始支持钉钉加签方式的鉴权, 参数为 --dingtalk_secret
21
+ - (2.0.11) 兼容了 ruby 3.0
22
+ - (2.0.10) 飞书支持了 V2 版本的机器人推送
23
+ - (2.0.9) publish 支持了 企业微信通知 可以使用 --wxwork_access_token 或 --wxwork_webhook, 增加了回调超时时间至20秒
24
+ - (2.0.8) publish 支持 飞书通知, 可使用 `feishu_access_token` 和 `feishu_custom_message`, 详情见 `fir publish --help`
21
25
  - (2.0.7) 修复了提示 token 错误的问题
22
26
  - (2.0.6) 修复了因为文件读取方式变化而导致的文件找不到不报错的问题
23
27
  - (2.0.5) 因为深信服 的黑名单误判, 将 api 切换到了备用域名
@@ -45,24 +49,49 @@ fir.im-cli 可以通过指令查看, 上传, iOS/Android 应用.
45
49
 
46
50
  ## 热门问题
47
51
 
48
- ### 如何配合 jenkins 使用?
52
+ ### 啥是 钉钉 / 企业微信 / 飞书 的 `access_token` ?
53
+
54
+ 就是回调地址中的长得最像 access_token 的东西
55
+
56
+ ```
57
+ 钉钉: https://oapi.dingtalk.com/robot/send?access_token=xxxxx
58
+ 就是 xxx 那部分
59
+
60
+ 企业微信: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx-xxxx-xxxx-xxxx-xxxxx
61
+ 就是 xxxxx-xxxx-xxxx-xxxx-xxxxx 那部分
62
+
63
+ https://open.feishu.cn/open-apis/bot/hook/xxxxxxxxxxxxxxxxxxx
64
+
65
+ 就是 xxxxxxxxxxxxxxxx 那部分
66
+
67
+ ```
68
+
69
+
70
+
71
+
72
+
73
+ ### 如何配合 jenkins 使用?
49
74
 
50
75
  参见 blog [http://blog.betaqr.com/use-fir-cli-in-jenkins/](http://blog.betaqr.com/use-fir-cli-in-jenkins/)
51
76
 
52
- ### Circle CI, Travis CI 或 Github Actions 等境外服务上, 有概率超时, 能否解决?
77
+ 这里有个快速检查脚本, 可以在 jenkins 中新建一个 脚本, 进行检查
53
78
 
54
- 2.0.3 版本 及其以上, 可以申请海外加速内测资格, 开启后可以使用海外加速上传
79
+ ```
80
+ #!/bin/bash --login
55
81
 
82
+ rvm list # 确保 rvm 正确安装, 如果直接通过系统安装ruby, 可以注释此行
83
+ ruby -v # 查看 ruby 的版本, 请确保大于 2.4.0
84
+ gem install fir-cli # 现场安装fir-cli , 如果安装过, 则会略过
85
+ fir -v # 查看 fir-cli 的版本
56
86
 
57
- 由于监管要求, 我们必须将服务于存储放置在境内. 由于众所周知的原因, 国内外连通性的表现不太好, 虽然我们的存储服务商 阿里云 提供了 OSS 境外加速服务, 但是高达 1.25 元/GB 的传输成本确实我们也没办法负担.
87
+ # 在这里执行 fir publish xxxxx
88
+ ```
58
89
 
59
90
 
91
+ ### 在 Circle CI, Travis CI 或 Github Actions 等境外服务上, 有概率超时, 能否解决?
60
92
 
61
- 目前我们提供三种临时解决方案来缓解问题(2.0.2以下版本):
93
+ 2.0.3 版本 及其以上, 可以申请海外加速内测资格, 开启后可以使用海外加速上传 `--oversea_turbo`
62
94
 
63
- 1. 设置较长的超时时间 如 `FIR_TIMEOUT=300 fir publish xxxx`, 则可将超时时间设置为 300 秒.
64
- 2. 如果fir-cli 版本 >= 2.0.0, 也可在出现超时后, 使用 `--switch-to-qiniu` 来切换到我们的另外一条存储线路. 如 `fir publish xxxx.apk --switch-to-qiniu`, 多一条线路备选.
65
- 3. 如果确实对这方面服务要求很高, 则可购买我们的私有部署服务. 我们可以在 aws 上部署一套专供您使用, 具体情况可以与客服或者加我微信进行沟通.
66
95
 
67
96
  更多细节请参考 [https://github.com/FIRHQ/fir-cli/issues/260](https://github.com/FIRHQ/fir-cli/issues/260)
68
97
 
@@ -91,13 +120,13 @@ fir-cli 提供对 aab 文件有限程度支持的上传与下载. 在使用 fir-
91
120
 
92
121
  ### 我想将 我上传的版本展示在下载的页面上
93
122
 
94
- 可以在 publish 的时候使用 --force_pin_history 这样 这个上传的版本即成为 "历史版本", 会在下载页面里一直显示. 当有新的版本上传后, 这个版本会作为 "历史版本" 在下载页面中展示.
123
+ 可以在 publish 的时候使用 --force_pin_history 这样 这个上传的版本即成为 "历史版本", 会在下载页面里一直显示. 当有新的版本上传后, 这个版本会作为 "历史版本" 在下载页面中展示.
95
124
 
96
125
  当版本设置为历史版本后, 用户可以直接下载指定的版本, 由于因成本原因, 一个 app 最多的 "历史版本" 为 30 个, 如果有用户有特殊需求, 可以与我们取得联系进行单独修改
97
126
 
98
127
  当达到上限后, 如果继续标记 force_pin_history, 则历史版本的最老版本(以上传时间为准)会被移出历史版本列表
99
128
 
100
- ### 境外上传老出现 stream closed
129
+ ### 境外上传老出现 stream closed
101
130
 
102
131
  因为网络时延问题, 可传入环境变量 `FIR_TIMEOUT=xxx` 进行超时时间设置
103
132
 
@@ -112,22 +141,22 @@ fir-cli 提供对 aab 文件有限程度支持的上传与下载. 在使用 fir-
112
141
  - [fir publish 发布应用到 fir.im](https://github.com/FIRHQ/fir-cli/blob/master/doc/publish.md)
113
142
  - [fir upgrade 升级相关](https://github.com/FIRHQ/fir-cli/blob/master/doc/upgrade.md)
114
143
 
115
- ## Docker 运行 fir-cli
144
+ ## Docker 运行 fir-cli
116
145
 
117
146
  ### 准备工作
118
147
  1. 将自己需要的文件挂载到 docker 中, 之后即可直接运行
119
- 2. 将自己的 API_TOKEN 以环境变量的形式传入container
148
+ 2. 将自己的 API_TOKEN 以环境变量的形式传入container
120
149
 
121
150
  ### 如何运行
122
151
 
123
- 假设 我需要上传桌面的 1.apk
152
+ 假设 我需要上传桌面的 1.apk
124
153
 
125
154
  ```
126
- docker run -e API_TOKEN=您的token -v 您的上传文件的目录的绝对路径:/tmp firhq/fir-cli:latest publish /tmp/你的文件
155
+ docker run -e API_TOKEN=您的token -v 您的上传文件的目录的绝对路径:/tmp firhq/fir-cli:latest publish /tmp/你的文件
127
156
 
128
157
  # 如 `docker run -e API_TOKEN=xxxxxxxe -v /Users/atpking/Desktop:/tmp firhq/fir-cli:latest publish /tmp/1.apk`
129
158
 
130
- # 实际含义是把我的桌面挂载到 docker 里的 /tmp 目录 之后上传 docker 文件里的 /tmp/1.apk
159
+ # 实际含义是把我的桌面挂载到 docker 里的 /tmp 目录 之后上传 docker 文件里的 /tmp/1.apk
131
160
  # 也可以修改为其他目录
132
161
  ```
133
162
 
@@ -135,13 +164,13 @@ docker run -e API_TOKEN=您的token -v 您的上传文件的目录的绝对路
135
164
 
136
165
  - 联系微信 `atpking`, 请注明 "fir-cli 交流"
137
166
 
138
- - 使用 Github 的 [Issue](https://github.com/FIRHQ/fir-cli/issues)
167
+ - 使用 Github 的 [Issue](https://github.com/FIRHQ/fir-cli/issues)
139
168
 
140
- ## 特别感谢
169
+ ## 特别感谢
141
170
 
142
171
  - 感谢 sparkrico 提供修正的 https://github.com/sparkrico/ruby_apk 解决了 android 解析的问题
143
-
172
+ - 感谢 fabcz 同学对企业微信的通知的支持 https://github.com/FIRHQ/fir-cli/pull/277
144
173
 
145
174
  ## 鼓励维护
146
175
 
147
- 挂了好久没都人鼓励维护, 想想算了吧
176
+ 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.12) 修复因为钉钉机器人不再支持base64导致无法显示二维码,另外开始支持钉钉加签方式的鉴权, 参数为 --dingtalk_secret
31
+ - (2.0.11) 兼容了 ruby 3.0 版本, 增加了环境变量FEISHU_TIMEOUT,可以多给飞书一些超时时间
32
+ - (2.0.10) 飞书支持了 V2 版本的机器人推送
33
+ - (2.0.9) publish 支持了 企业微信通知 可以使用 --wxwork_access_token 或 --wxwork_webhook, 增加了回调超时时间至20秒
34
+ - (2.0.8) publish 支持 飞书通知, 可使用 `feishu_access_token` 和 `feishu_custom_message`, 详情见 `fir publish --help`
30
35
  - (2.0.7) 修复了提示 token 有问题的错误
31
36
  - (2.0.6) 将校验文件是否存在提前
32
37
  - (2.0.5) 更换了上传域名, 避免与 深信服的设备冲突
@@ -49,12 +54,13 @@ Gem::Specification.new do |spec|
49
54
  # spec.add_development_dependency 'byebug'
50
55
  spec.add_development_dependency 'minitest', '~> 5.7'
51
56
  spec.add_development_dependency 'pry', '~> 0.10'
52
-
57
+
53
58
  spec.add_dependency 'admqr_knife', '~> 0.1.5'
54
59
  spec.add_dependency 'thor', '~> 0.19'
55
60
  spec.add_dependency 'rest-client', '~> 2.0'
56
61
  spec.add_dependency 'ruby_android_apk', '~> 0.7.7.1'
57
62
  spec.add_dependency 'rqrcode', '~> 0.7'
63
+ spec.add_dependency 'rexml'
58
64
  spec.add_dependency 'CFPropertyList'
59
- spec.add_dependency 'api_tools', '~> 0.1.0'
65
+ spec.add_dependency 'api_tools', '~> 0.1.1'
60
66
  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,16 @@ 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********)'
130
+
131
+ method_option :feishu_access_token, type: :string, desc: 'Send msg to feishu, need access_token, not whole url'
132
+ method_option :feishu_custom_message, type: :string, desc: 'add custom message to feishu'
133
+
134
+ method_option :wxwork_webhook, type: :string, desc: 'wxwork webhook url (optional)'
135
+ method_option :wxwork_access_token, type: :string, desc: 'Send msg to wxwork group, need group bot webhook, not whole url'
136
+ method_option :wxwork_custom_message, type: :string, desc: 'add custom message to wxwork group'
137
+ method_option :wxwork_pic_url, type: :string, desc: 'message background image, best size is 1068x455'
129
138
 
130
139
  method_option :open, type: :boolean, desc: 'true/false if open for everyone'
131
140
  method_option :password, type: :string, desc: 'Set password for app'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FIR
2
4
  class AppUploader
3
5
  include ApiTools::DefaultRestModule
@@ -14,6 +16,8 @@ module FIR
14
16
  def upload
15
17
  upload_icon
16
18
  binary_callback_info = upload_binary
19
+ raise binary_callback_info if binary_callback_info.is_a? StandardError
20
+
17
21
  # 将 binary 的callback信息返回
18
22
  binary_callback_info
19
23
  end
@@ -21,9 +25,12 @@ module FIR
21
25
  protected
22
26
 
23
27
  def callback_to_api(callback_url, callback_binary_information)
28
+ logger.debug 'begin to callback api'
24
29
  return if callback_binary_information.blank?
25
30
 
26
- post callback_url, callback_binary_information
31
+ answer = post callback_url, callback_binary_information, timeout: 20
32
+ logger.debug 'callback api finished'
33
+ answer
27
34
  end
28
35
 
29
36
  def icon_file_path
@@ -74,6 +81,7 @@ module FIR
74
81
 
75
82
  def callback_icon_information
76
83
  return {} if icon_file_path.nil?
84
+
77
85
  {
78
86
  key: icon_cert[:key],
79
87
  token: icon_cert[:token],
@@ -106,6 +114,5 @@ module FIR
106
114
  def logger
107
115
  FIR.logger
108
116
  end
109
-
110
117
  end
111
- end
118
+ end
@@ -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]})"
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,95 @@
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
+ @title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]})"
14
+ end
15
+
16
+ def send_msg
17
+ return if feishu_access_token.blank?
18
+
19
+ answer = v2_request
20
+ v1_request if answer.dig('ok') == 'false'
21
+ end
22
+
23
+ def v2_request
24
+ url = "https://open.feishu.cn/open-apis/bot/v2/hook/#{feishu_access_token}"
25
+ x = build_v2_info
26
+ # byebug
27
+ DefaultRest.post(url, x, {timeout: ENV['FEISHU_TIMEOUT'] ? ENV['FEISHU_TIMEOUT'].to_i : 30 })
28
+ end
29
+
30
+ def v1_request
31
+ url = "https://open.feishu.cn/open-apis/bot/hook/#{feishu_access_token}"
32
+ payload = {
33
+ "title": "#{title} uploaded",
34
+ "text": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:feishu_custom_message]}\n"
35
+ }
36
+ DefaultRest.post(url, payload, {timeout: ENV['FEISHU_TIMEOUT'] ? ENV['FEISHU_TIMEOUT'].to_i : 30 })
37
+ end
38
+
39
+ private
40
+
41
+ def build_v2_info
42
+ {
43
+ msg_type: 'post',
44
+ content: {
45
+ post: {
46
+ zh_cn: {
47
+ title: title,
48
+ content: [build_info_tags, [build_image_tag]]
49
+ }
50
+ }
51
+ }
52
+ }
53
+ end
54
+
55
+ def build_info_tags
56
+ text = "#{title} uploaded at #{Time.now}\n#{options[:feishu_custom_message]}\n"
57
+ [
58
+ {
59
+ "tag": 'text',
60
+ "text": text
61
+ },
62
+ {
63
+ "tag": 'a',
64
+ "text": download_url,
65
+ "href": download_url
66
+ }
67
+ ]
68
+ end
69
+
70
+ def build_image_tag
71
+ {
72
+ "tag": 'img',
73
+ "image_key": upload_qr_code,
74
+ "width": 300,
75
+ "height": 300
76
+ }
77
+ end
78
+
79
+ def fetch_image_access_token
80
+ answer = DefaultRest.post(fir_api[:fetch_feishu_v3_token] || 'http://fir-api.admqr.com/user/fetch_feishu_v3_token', {})
81
+ answer[:feishu_v3_token]
82
+ end
83
+
84
+ def upload_qr_code
85
+ answer = RestClient.post('https://open.feishu.cn/open-apis/image/v4/put/', {
86
+ image_type: 'message',
87
+ image: File.new(qrcode_path, 'rb')
88
+ }, {
89
+ 'Authorization' => "Bearer #{fetch_image_access_token}"
90
+ })
91
+
92
+ json = JSON.parse(answer)
93
+ json.dig('data', 'image_key')
94
+ end
95
+ end
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # require 'byebug'
4
+
4
5
  require_relative './qiniu_uploader'
5
6
  require_relative './ali_uploader'
7
+ require_relative '../util/feishu_helper'
8
+ require_relative '../util/dingtalk_helper'
6
9
 
7
10
  module FIR
8
11
  module Publish
@@ -11,8 +14,10 @@ module FIR
11
14
  logger_info_publishing_message
12
15
 
13
16
  logger.info 'begin to upload ...'
17
+ logger.info "fir-cli version #{FIR::VERSION} (#{RUBY_VERSION} @ #{RUBY_PLATFORM})"
14
18
  received_app_info = upload_app
15
19
 
20
+
16
21
  short = received_app_info[:short]
17
22
  download_domain = received_app_info[:download_domain]
18
23
  release_id = received_app_info[:release_id]
@@ -25,7 +30,11 @@ module FIR
25
30
  logger.info "Published succeed: #{download_url}"
26
31
 
27
32
  qrcode_path = build_qrcode download_url
33
+
28
34
  dingtalk_notifier(download_url, qrcode_path)
35
+ feishu_notifier(download_url, qrcode_path)
36
+ wxwork_notifier(download_url)
37
+
29
38
  upload_mapping_file_with_publish
30
39
 
31
40
  upload_fir_cli_usage_info(received_app_info)
@@ -190,26 +199,31 @@ module FIR
190
199
  end
191
200
 
192
201
  def dingtalk_notifier(download_url, qrcode_path)
193
- return if options[:dingtalk_access_token].blank?
202
+ DingtalkHelper.new(@app_info, options, qrcode_path, download_url).send_msg
203
+ end
204
+
205
+ def feishu_notifier(download_url, qrcode_path)
206
+ FeishuHelper.new(@app_info, options, qrcode_path, download_url).send_msg
207
+ end
208
+
209
+ def wxwork_notifier(download_url)
210
+ webhook_url = options[:wxwork_webhook]
211
+ webhook_url ||= "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=#{options[:wxwork_access_token]}"
212
+ return if webhook_url.blank?
194
213
 
195
214
  title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]})"
196
215
  payload = {
197
- "msgtype": 'markdown',
198
- "markdown": {
199
- "title": "#{title} uploaded",
200
- "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)))})"
201
- # "text": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:dingtalk_custom_message]}\n"
202
- }
216
+ "msgtype": "news",
217
+ "news": {
218
+ "articles": [{
219
+ "title": "#{title} uploaded",
220
+ "description": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n#{options[:wxwork_custom_message]}\n",
221
+ "url": download_url,
222
+ "picurl": options[:wxwork_pic_url]
223
+ }],
224
+ },
203
225
  }
204
- build_dingtalk_at_info(payload)
205
- url = "https://oapi.dingtalk.com/robot/send?access_token=#{options[:dingtalk_access_token]}"
206
-
207
- # 用完了二维码, 就删了
208
- File.delete(qrcode_path) unless @export_qrcode
209
-
210
- DefaultRest.post(url, payload)
211
- rescue StandardError => e
212
- logger.warn "Dingtalk send error #{e.message}"
226
+ DefaultRest.post(webhook_url, payload)
213
227
  end
214
228
 
215
229
  def initialize_publish_options(args, options)
@@ -219,10 +233,10 @@ module FIR
219
233
 
220
234
  check_file_exist(@file_path)
221
235
  check_supported_file(@file_path)
222
-
236
+
223
237
  @token = options[:token] || current_token
224
238
  check_token_cannot_be_blank(@token)
225
-
239
+
226
240
  @changelog = read_changelog(options[:changelog]).to_s.to_utf8
227
241
  @short = options[:short].to_s
228
242
  @passwd = options[:password].to_s
@@ -234,7 +248,10 @@ module FIR
234
248
  @app_id = @uploading_info[:id]
235
249
 
236
250
  @skip_update_icon = options[:skip_update_icon]
251
+
237
252
  @force_pin_history = options[:force_pin_history]
253
+
254
+ @app_info[:api_url] = fir_api[:base_url]
238
255
  unless options[:specify_icon_file].blank?
239
256
  @specify_icon_file_path = File.absolute_path(options[:specify_icon_file])
240
257
  end
@@ -247,17 +264,5 @@ module FIR
247
264
  end
248
265
 
249
266
 
250
-
251
- def build_dingtalk_at_info(payload)
252
- answer = {}
253
- answer[:isAtAll] = options[:dingtalk_at_all]
254
-
255
- unless options[:dingtalk_at_phones].blank?
256
- answer[:atMobiles] = options[:dingtalk_at_phones].split(',')
257
- payload[:markdown][:text] += options[:dingtalk_at_phones].split(',').map { |x| "@#{x}" }.join(',')
258
- end
259
-
260
- payload[:at] = answer
261
- end
262
267
  end
263
268
  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.7'
4
+ VERSION = '2.0.12'
5
5
  end
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.7
4
+ version: 2.0.12
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-15 00:00:00.000000000 Z
12
+ date: 2021-02-19 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
@@ -254,18 +270,23 @@ metadata: {}
254
270
  post_install_message: "\n ______________ ________ ____\n /
255
271
  ____/ _/ __ \\ / ____/ / / _/\n / /_ / // /_/ /_____/ / / / /
256
272
  /\n / __/ _/ // _, _/_____/ /___/ /____/ /\n /_/ /___/_/ |_| \\____/_____/___/\n\n
257
- \ ## 更新记录\n - (2.0.7) 修复了提示 token 有问题的错误\n - (2.0.6) 将校验文件是否存在提前\n - (2.0.5)
258
- 更换了上传域名, 避免与 深信服的设备冲突\n - (2.0.4) 修复了 cdn 不支持 patch 方法透传, 导致在修改 app 信息的时候返回的 400
259
- 错误\n - (2.0.3) 增加 dingtalk_at_phones, 钉钉通知可 at 用户手机号, 以逗号,分割. 此命令需配合 `dingtalk_access_token`
260
- 使用\n - (2.0.3) 增加 dingtalk_at_all, 钉钉通知可 at 所有人, 此命令需配合 `dingtalk_access_token`
261
- 使用\n - (2.0.3) publish 增加海外加速参数 --oversea_turbo\n - (2.0.2) 有限支持 aab 文件上传, 强依赖`bundletool`工具,
262
- 具体请参见参数 `--bundletool_jar_path` `auto_download_bundletool_jar`\n - (2.0.1) publish
263
- 支持 新参数 `specify_app_display_name`, 指定 app 显示名称\n - (2.0.1) publish 支持 新参数 `need_ansi_qrcode`,
264
- 在控制台直接打印二维码, jenkins 用户可能需要使用 `AnsiColor Plugin` 插件配合\n - (2.0.1) publish 支持 新参数
265
- `dingtalk_custom_message`, 可以在钉钉通知里增加自定义消息, 此命令需配合 `dingtalk_access_token` 使用\n
266
- \ - (2.0.1) publish 支持 新参数 `skip_fir_cli_feedback`, 可禁止 fir-cli 发送统计信息\n - (2.0.0)
267
- publish 使用更快的存储商, 加速上传速度, 若感觉没以前可使用 switch_to_qiniu 恢复\n - [fir-cli](https://github.com/firhq/fir-cli)
268
- 已经开源\n - 欢迎 fork, issue pull request\n "
273
+ \ ## 更新记录\n - (2.0.12) 修复因为钉钉机器人不再支持base64导致无法显示二维码,另外开始支持钉钉加签方式的鉴权, 参数为 --dingtalk_secret\n
274
+ \ - (2.0.11) 兼容了 ruby 3.0 版本, 增加了环境变量FEISHU_TIMEOUT,可以多给飞书一些超时时间\n - (2.0.10) 飞书支持了
275
+ V2 版本的机器人推送\n - (2.0.9) publish 支持了 企业微信通知 可以使用 --wxwork_access_token --wxwork_webhook,
276
+ 增加了回调超时时间至20秒\n - (2.0.8) publish 支持 飞书通知, 可使用 `feishu_access_token` `feishu_custom_message`,
277
+ 详情见 `fir publish --help`\n - (2.0.7) 修复了提示 token 有问题的错误\n - (2.0.6) 将校验文件是否存在提前\n
278
+ \ - (2.0.5) 更换了上传域名, 避免与 深信服的设备冲突\n - (2.0.4) 修复了 cdn 不支持 patch 方法透传, 导致在修改 app
279
+ 信息的时候返回的 400 错误\n - (2.0.3) 增加 dingtalk_at_phones, 钉钉通知可 at 用户手机号, 以逗号,分割. 此命令需配合
280
+ `dingtalk_access_token` 使用\n - (2.0.3) 增加 dingtalk_at_all, 钉钉通知可 at 所有人, 此命令需配合
281
+ `dingtalk_access_token` 使用\n - (2.0.3) publish 增加海外加速参数 --oversea_turbo\n - (2.0.2)
282
+ 有限支持 aab 文件上传, 强依赖`bundletool`工具, 具体请参见参数 `--bundletool_jar_path` `auto_download_bundletool_jar`\n
283
+ \ - (2.0.1) publish 支持 新参数 `specify_app_display_name`, 指定 app 显示名称\n - (2.0.1)
284
+ publish 支持 新参数 `need_ansi_qrcode`, 在控制台直接打印二维码, jenkins 用户可能需要使用 `AnsiColor Plugin`
285
+ 插件配合\n - (2.0.1) publish 支持 新参数 `dingtalk_custom_message`, 可以在钉钉通知里增加自定义消息, 此命令需配合
286
+ `dingtalk_access_token` 使用\n - (2.0.1) publish 支持 新参数 `skip_fir_cli_feedback`,
287
+ 可禁止 fir-cli 发送统计信息\n - (2.0.0) publish 使用更快的存储商, 加速上传速度, 若感觉没以前可使用 switch_to_qiniu
288
+ 恢复\n - [fir-cli](https://github.com/firhq/fir-cli) 已经开源\n - 欢迎 fork, issue 和 pull
289
+ request\n "
269
290
  rdoc_options: []
270
291
  require_paths:
271
292
  - lib
@@ -281,7 +302,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
281
302
  version: '0'
282
303
  requirements: []
283
304
  rubygems_version: 3.0.3
284
- signing_key:
305
+ signing_key:
285
306
  specification_version: 4
286
307
  summary: fir.im command tool
287
308
  test_files: