🚀 Bot & Workflow automation
我很早就有这个想法了。在 PR 31 前后,越发认为这个项目需要 bot。那些机械重复劳动,让人来完成,费时费力、不方便、还容易出错,不如交给机器。
目前建议使用 Mergify 管理 PR。如有需要,以后可以考虑引进其他的。
Index
- Labels: https://github.com/TieBaMma/InstallTutorial/issues/41#issuecomment-635387255
- Mergify configuration: https://github.com/TieBaMma/InstallTutorial/issues/41#issuecomment-637672452
- Repo sync: https://github.com/TieBaMma/InstallTutorial/issues/41#issuecomment-637672942
Mergify configuration
Outdated
pull_request_rules:
- name: Automatic squash merge when approved
conditions:
- "#approved-reviews-by>=1"
- "#changes-requested-reviews-by=0"
- "base=gh-pages"
- '-title~=(?i)\bWIP\b'
actions:
merge:
strict: "smart"
method: squash
commit_message: "title+body"
- name: Delete head branch after merge
conditions:
- "merged"
actions:
delete_head_branch: {}
- name: Add label `Area-Content`
conditions:
- "files=index.md"
actions:
label:
add: ["Area-Content"]
- name: Add label `Area-WebPageDesign`
conditions:
- 'files~=(?i)\.(css|html|htm|js)$'
actions:
label:
add: ["Area-WebPageDesign"]
- name: Request a review from the owner because it is a `[MEGA]` (complex) PR
conditions:
- 'title~=(?i)\[MEGA\]'
actions:
request_reviews:
users: ["TieBaMma"]
- name: Assign the author because it is a draft PR
conditions:
- "draft"
actions:
assign:
users: ["{{author}}"]
- name: Assign the author because its title contains `WIP`
conditions:
- 'title~=(?i)\bWIP\b'
actions:
assign:
users: ["{{author}}"]
- name: Ask to remove `WIP` from title before merge
conditions:
- "#approved-reviews-by>=1"
- "#changes-requested-reviews-by=0"
- "base=gh-pages"
- 'title~=(?i)\bWIP\b'
actions:
comment:
message: |
此 pull request 似乎已经准备就绪,但 title 中仍然有 `WIP` 字样。
如果这是笔误,请修正。
谢谢。
- name: (Test Env) AutoApprove # For test ONLY! Do not use in production!
conditions:
- "label=AutoApprove"
actions:
review:
type: "APPROVE"
下面详细介绍各规则。
Automatic squash merge when approved
如果
- 至少 1 个 approved by reviewers with write permission。
- 没有 requested changes。
- title 中没有
WIP字样。
那么,
- 根据 base branch 更新 topic branch。 (Strict Merge)
- squash merge.
Delete head branch after merge
理论上,与 GitHub 的 automatic deletion of branches 等效。
Add label Area-Content
如果
- 修改了文件
index.md。
那么,
- 添加
Area-Contentlabel。(文章内容相关)
Add label Area-WebPageDesign
如果
- 修改了 CSS、HTML 或 JavaScript 文件。
那么,
- 添加
Area-WebPageDesignlabel。(网页相关)
Request a review from the owner because it is a [MEGA] (complex) PR
如果
- title 中有
[MEGA]字样。(复杂的工作)
那么,
- 请求 TieBaMma review。
Assign the author because it is a draft PR
这条规则与下一条一起,确保所有 WIP 都默认得到 assign。
如果
- 是 draft PR。
那么,
- Assign the author.
Assign the author because its title contains WIP
如果
- title 中有
WIP字样。
那么,
- Assign the author.
Ask to remove WIP from title before merge
如果
- 符合 “Automatic squash merge when approved” 规定的 merge 条件。
- 但是 title 中有
WIP字样。
那么,
- 通知参与者来修正。
正则测试用例
testCases = [
r'wIp', # true
r'a wIp', # true
r'wIp a', # true
r'wIp-a', # true
r'wIp:a', # true
r'WIP7', # false
r'sWIP', # false
r'a[wIp]b', # true
r'📄wiP] Fix 蓝奏云', # true
r'📄 Fix 蓝WIP奏云', # false
r'📄 Fix 蓝奏云', # false
r'' # false
]
pattern = re.compile(r'(?i)\bWIP\b')
关于 label
之前,写 issue templates 时提到过。这里详细说明。
用 label 分类 issue 和 PR 是一种良好的实践。它能帮助参与者快速到达自己关注的区域。无论大小项目,都应该尽早设计一套实用的 label 体系,并给每一个 issue 或 PR 都打上 label。
而且,不晓得为什么,这个项目的流量近期呈现明显的上升趋势。拦不住,就做好管理大流量项目的准备。
此外,前面有几条 Mergify 规则都是根据特征来标记 PR,自然涉及 label。如果等用到时,才忙着创建,可能无法达到良好效果。最好现在就准备。
我建议直接修改 GitHub 预置的 label。最主要的原因是,GitHub 预置的颜色区别鲜明且可读性良好;如果自己从头创建,找个合适的颜色会比较费劲。所以,把预置的都用完了再想新的。🤦
Outdated
| Label | Description | 修改自 | 示例 |
|---|---|---|---|
| Area-Content | 文章内容相关 | bug | 43, 40, 39, 38, 36, 35, 34, 32, 31, 28, 27, 26, 25, 24, 23, 20, 18, 15, 14, 13, 11, 10, 8, 5, 3, 2 |
| Area-WebPageDesign | 网页相关 | enhancement | 31, 20 |
| Issue-Question | 询问或讨论 | question | 43, 41, 33, 30, 29, 22, 16, 12, 9, 7, 4, 1 |
| DuplicateOrInvalid | 重复或无效 | duplicate | 37, 21, 19, 17, 6 |
示例已核对,将来可以作为参考。
-
Area-*用于划分 issue 或 PR 涉及的项目部分。 -
Issue-*仅用于分类 issue。 -
DuplicateOrInvalid表示与任何已有内容(issue、PR 等)重复,或者本身是无意义、不合理的。(因为难以界定 duplicate 和 invalid,于是作为一个类别处理。)带有DuplicateOrInvalid的不需要其他 label。
如有需要,再设计其他的。
欸……这个……到底要怎么玩?能不能用三行字总结一下?
不晓得为什么,这个项目的流量近期呈现明显的上升趋势
结合贴吧等地的帖子来看,可能只是单纯地又到要交作业的时候了。
原来你一直没看懂呀,我还以为你这一个月在犹豫什么。😂 既然如此,~~工程学理论、经验传统、最佳实践之类的我都不聊了~~,直接谈解决方案。
你看,标题改了,直点主题:我们将在这个 issue 下讨论 label 体系、自动化管理 PR、自动化同步 upstream 与 fork。
现在,请你阅读上面的 Mergify 配置、label 体系,提出修改意见。 我再去研究一下 Actions 怎么配最合适。
(看来奈亚子也是过气了
现在,请你阅读上面的 Mergify 配置、label 体系,提出修改意见。
我就是这些内容看不懂啊(捂脸),而且说实话我觉得现在人工检查的强度并不大,至多就是有时候三五天没上线,没法及时Merge。
……👀我确实无法理解这波联动。
看不懂
哪里不明白呢?
我上面先展示整个 Mergify 配置文件,之后逐条解释,最后谈了 label 的问题。
你可以访问 Lemmingh/InstallTutorial#1,感受这套 Mergify 规则的力量。
人工检查的强度并不大
关键是,工作预分类、规则检查、数据同步、规范合并等非常固定、无聊的琐事,是机器的活,不应该由人来做。 事实上,现在有些项目更进一步,已经在用 AI 预分析、预处理 issue 了。
Bot 是基础设施。部署自动机器是为了方便常规管理,解放生产力,把人的精力留到创造性的工作上。
既然我已经决定不谈理论,那么,看案例

左侧的 tag 是我自己加的。
可以发现,23 ~ 28 和 39 拧出两个大麻花。 如果这个项目活了几十年(很有可能),后面接手的人看到这段记录,一定会 心理阴影 +1
这两团属于人当时脑子一抽、手一滑造成的失误,如果交由 bot 完成,可以得到非常干净高效的结果。
我能说几乎全不明白吗……我能理解这里是想引入一个机械审核的啥,但是这个需要一整套语言来操纵的审核器太让人恐惧了。
哦对了,还有一点,我个人应该算是对这类机械审核的工具持保留态度吧,很多网站——比如百度贴吧,还有stackexchange——都有类似的机制,但是效果似乎都不好,百度贴吧臭名昭著了姑且不谈,stackexchange作为程序员社区,技术应该过硬吧,可mathematica.stackexchange.com曾经引入过一个审核代码排版的机器人(https://mathematica.meta.stackexchange.com/q/2018/1871 ),结果反而把很多没问题的帖子给卡下去了。(该页右侧的Linked是冰山一角。)Mergify是否会导致类似的问题呢?
究竟是哪里不明白?我重新排版了上面的 YAML,可能有助于理解。😵 Workflow automation 应该是翻译成“工作流程自动化”,这个概念很直白,应当不需要基础知识就能理解。 Mergify 的首页也十分生动形象。
Workflow automation 不是“审核”,它就像传送带。
Mergify 自己只有 passed 和 neutral 两种返回状态,不会影响 mergeability。而且我配置的规则,都是日常,没有激进的东西。 这种 bot 只会根据指令干苦差,最蠢也只是 TensorFlow 的那个(一天到晚 ping assignee)。 佼佼者的话,我认为是 Fabric Bot,可惜尚未公测,没得用。
嗯……那就实际用用看吧,大不了撤掉嘛。
现在这样应该就行了?
你是不是……用了 Mergify Dashboard 里的编辑器?😂
没来得及跟你说,那玩意有 bug:它会自动在文件末尾乱加些东西。
https://github.com/TieBaMma/InstallTutorial/blob/00ba612f27d8980916109b07e911e081166ba13f/.mergify.yml#L74-L80
而且 Mergify configuration validation 也告警了: https://github.com/TieBaMma/InstallTutorial/pull/46/checks?check_run_id=712787307
我都是亲自编辑 .mergify.yml。
其他的配置文件我也是自己动手写。
这个错误或许是件好事。(?)
因为还没有处理 label,如果这时候 Mergify 跑起来,可能会发生无法预料的问题。
本来,我制定了一个 5 步计划,后一步依赖前一步,打算等所有细节都讨论确定后,发出来执行:
- Step 1. 🔧 Edit labels
- Step 2. 🔧 Add automation services configuration
- Step 3. 🚀 Enable bots
- Step 4. 📖 Update documentation
- Step 5. 🧪 Test GitHub Actions
现在看来要随机应变了。
采用什么样的 label 体系
label 是本 issue 中其他问题的基石。(~~尽管不是第一个讨论的事情~~)
请问,你对上文设计的 4 个 label 有什么意见?
如果没有问题,我们把 GitHub 预置的 label 改名即可。
请问,你对上文设计的 4 个 label 有什么意见?
嗯……现在能想到的是,Description部分显得不够明确。
“文章内容相关”建议改成“教程内容相关”,“网页相关”建议直接用英文直译“网页设计相关”。
| Label | Description | 修改自 | 示例 |
|---|---|---|---|
| Area-Content | 教程内容相关 | bug | 45, 43, 42, 40, 39, 38, 36, 35, 34, 32, 31, 28, 27, 26, 25, 24, 23, 20, 18, 15, 14, 13, 11, 10, 8, 5, 3, 2 |
| Area-WebPageDesign | 网页设计相关 | enhancement | 31, 20 |
| Issue-Question | 询问或讨论 | question | 45, 44, 43, 41, 33, 30, 29, 22, 16, 12, 9, 7, 4, 1 |
| DuplicateOrInvalid | 重复或无效 | duplicate | 46, 37, 21, 19, 17, 6 |
同意,具体的词会比上位概念更清晰明确、易于理解。等这边敲定了,issue templates 那边应该也需要对应更新。
其实,我还想再加一个 Area-CommunityProfile,表示社区资料、服务配置文件相关。(怎么这么拗口)
看来,我选的词不好。 “管理”是这个概念的一部分。
……用英语说可能会容易理解:
- 📖 Community profile
- ⚙ Repository settings
- 🚀 Integration services
基本上是按影响的文件判断,排除了 Content 和 WebPageDesign,就是这个类别了:
-
.github/ -
.vscode/ -
docs/ -
.editorconfig -
.gitattributes -
.gitignore -
.mergify.yml -
CODE_OF_CONDUCT.md -
LICENSE.txt -
README.md - ……
看来,我选的词不好。 “管理”是这个概念的一部分。
……用英语说可能会容易理解:
⚙ Repository settings
🚀 Integration services
基本上是按影响的文件判断,排除了 Content 和 WebPageDesign,就是这个类别了:
.github/.vscode/docs/.editorconfig.gitattributes.gitignore.mergify.ymlCODE_OF_CONDUCT.mdLICENSE.txtREADME.md- ……
……“其他”?“杂项”?
好,这样,每个 issue 或 PR 都有 Area 归属了。
| Label | Description | Color | 修改自 | 示例 |
|---|---|---|---|---|
| Area-Content | 教程内容相关 | #ff8c00 |
bug | 45, 43, 42, 40, 39, 38, 36, 35, 34, 32, 31, 28, 27, 26, 25, 24, 23, 20, 18, 15, 14, 13, 11, 10, 8, 7, 5, 3, 2 |
| Area-WebPageDesign | 网页设计相关 | #84b6eb |
enhancement | 31, 20 |
| Area-Other | balabala | #3ae8c8 |
† | 44, 41, 33, 31, 30, 29, 22, 20, 16, 12, 9, 4, 1 |
| Issue-Question | 询问或讨论 | #cc317c |
question | 45, 44, 43, 41, 33, 30, 29, 22, 16, 12, 9, 7, 4, 1 |
| DuplicateOrInvalid | 重复或无效 | #cccccc |
duplicate | 46, 37, 21, 19, 17, 6 |
†: 它的颜色是我几次选出来的,如果你不喜欢,可以找其他的。
示例已核对,将来可以作为参考。
Step 1. 🔧 Edit labels
Assignees: @TieBaMma Estimated: 1 day
- 根据上面的设计,修改 label 体系。
- 为上面各示例应用 label。参看批量应用 label。一个列出所有 issue 和 PR 的方法。
实际试用之后发现大红色的Area-Content观感非常糟糕,所以改了改。
大红色的
Area-Content观感非常糟糕
一片红让人惊恐?确实瘆得慌。😅
现在,Content 与 Other 有些接近,不易区分。要不要再稍微调调?不妨参考一些色板,比如
准备部署自动化
- 是否需要拉直历史记录的那两个结?(amend 大约 14 条 commit)
- 我修改了 “Add label
Area-Content” 和 “Add labelArea-WebPageDesign” 规则。头秃。 - workflow 还有点问题需要讨论。
Mergify configuration
File: .mergify.yml
pull_request_rules:
- name: Automatic squash merge when approved
conditions:
- "#approved-reviews-by>=1"
- "#changes-requested-reviews-by=0"
- "base=gh-pages"
- '-title~=(?i)\bWIP\b'
actions:
merge:
strict: "smart"
method: squash
commit_message: "title+body"
- name: Delete head branch after merge
conditions:
- "merged"
actions:
delete_head_branch: {}
- name: Add label `Area-Content`
conditions:
- 'files~=(?i)^(?!\.|CODE_OF_CONDUCT|docs|LICENSE|README).*\.md$' # To avoid false positives, only matches a few kinds of Markdown files. False negatives can be corrected by humans, but false positives cannot!
actions:
label:
add: ["Area-Content"]
- name: Add label `Area-WebPageDesign`
conditions:
- 'files~=(?i)(^_.*(?<!\.md)$)|(\.(css|js|less|scss)$)' # Not all. Only the most frequently modified files.
actions:
label:
add: ["Area-WebPageDesign"]
- name: Request a review from the owner because it is a `[MEGA]` (complex) PR
conditions:
- 'title~=(?i)\[MEGA\]'
actions:
request_reviews:
users: ["TieBaMma"]
- name: Assign the author because it is a draft PR
conditions:
- "draft"
actions:
assign:
users: ["{{author}}"]
- name: Assign the author because its title contains `WIP`
conditions:
- 'title~=(?i)\bWIP\b'
actions:
assign:
users: ["{{author}}"]
- name: Ask to remove `WIP` from title before merge
conditions:
- "#approved-reviews-by>=1"
- "#changes-requested-reviews-by=0"
- "base=gh-pages"
- 'title~=(?i)\bWIP\b'
actions:
comment:
message: |
此 pull request 似乎已经准备就绪,但 title 中仍然有 `WIP` 字样。
如果这是笔误,请修正。
谢谢。
Automatic squash merge when approved
如果
- 至少 1 个 approved by reviewers with write permission。
- 没有 requested changes。
- title 中没有
WIP字样。
那么,
- 根据 base branch 更新 topic branch。 (Strict Merge)
- squash merge.
Delete head branch after merge
理论上,与 GitHub 的 automatic deletion of branches 等效。
Add label Area-Content
如果
- 修改了 Markdown 文件 (
.md),而且它的路径的开头不是-
. -
CODE_OF_CONDUCT -
docs -
LICENSE -
README
-
那么,
- 添加
Area-Contentlabel。
Add label Area-WebPageDesign
如果
- 修改了路径的开头是
_,而且不是 Markdown 的文件。 - 或者,修改了 CSS、JavaScript、Less 或 Sass 文件。
那么,
- 添加
Area-WebPageDesignlabel。
Request a review from the owner because it is a [MEGA] (complex) PR
如果
- title 中有
[MEGA]字样,表明是复杂的工作。
那么,
- 请求 TieBaMma review。
Assign the author because it is a draft PR
这条规则与下一条一起,确保所有 WIP 都默认得到 assign。
如果
- 是 draft PR。
那么,
- Assign the author.
Assign the author because its title contains WIP
如果
- title 中有
WIP字样。
那么,
- Assign the author.
Ask to remove WIP from title before merge
如果
- 符合 “Automatic squash merge when approved” 规定的 merge 条件。
- 但是 title 中有
WIP字样。
那么,
- 发一条 comment,通知参与者来修正。
Pull from upstream at 00:00:00Z every Sunday
File: .github/workflows/github-repo-sync.yml
name: "Pull from upstream at 00:00:00Z every Sunday"
on:
schedule:
- cron: "0 0 * * 0"
repository_dispatch:
types: ["repo-sync"]
jobs:
repo-sync:
if: ${{ github.repository_owner != 'TieBaMma' }}
runs-on: ubuntu-latest
steps:
- name: Log trigger info
shell: bash
run: |
echo "Actor: $GITHUB_ACTOR"
echo "Event: $GITHUB_EVENT_NAME"
echo
echo "Commit: $GITHUB_SHA"
echo "Branch: $GITHUB_REF"
- uses: actions/checkout@v2
- name: Invoke GitHub Repo Sync
uses: repo-sync/github-sync@v2
with:
source_repo: "TieBaMma/InstallTutorial"
source_branch: "gh-pages"
destination_branch: "gh-pages"
github_token: ${{ secrets.GITHUB_TOKEN }}
用于同步 upstream 与 fork 的 GitHub Actions workflow,利用 GitHub Repo Sync。
目前的困惑是,应该多久运行一次。这个项目的流量波动太大。
吐槽
最迟在 2013 年,已经有人向 GitHub 申请了这项功能。但不知为何,至今没有官方实现。倒是民间方案层出不穷,比如
- GitHub Repo Sync (曾用名 GitHub Sync)
- Forkrefresh
- Upriver
~~看完,我甚至觉得自己也可以用 Node 写一个,发布为 action。~~ 但是 GitHub REST API 似乎有一些诡异的响应。
现在,Content 与 Other 有些接近,不易区分。要不要再稍微调调?
把 Other 改成 darkorange 了,这样区分度应该是够了,但是说实话总感觉 Other 不应该是这个颜色……不过考虑到 Other 下面的条目还比较多,这样或许也不错?
目前的困惑是,应该多久运行一次。这个项目的流量波动太大。
难办,除非能搞到全国(全球?)大学 Mathematica 相关课程大作业上交时间表。话说有没有什么自动检测流量变动率的工具什么的……?——等下,在此之前的问题:这个 Pull from upstream 是做什么用的?
颜色
我的看法是,之前水色 #3ae8c8 的 Other 挺美观。
而 #ff8c00 更适合 Content。红、橙、黄带有醒目、紧迫的感觉。我认为,在这个项目中,内容是重大的事情,值得用较突出的色彩。
流量
我说的“流量”是 Commit Activity,是过去一年内 commit 的按周分布。你作为 owner,应该还能看到其他统计信息。可以发现,有时候几个月也没动静,有时候连着几天都有 commit。
如果要监测网站的流量,有很多成熟的服务。我担心是否合算:
- 注册、配置服务要花一波精力。
- 需要增加少说几十 kB 的脚本,可能会赶超网页本身的大小。毕竟这项目全是字。
- 如果碰上个 Firefox + Adblock Plus 之类的神级组合,基本抓不到有价值的数据。
至于看课程表,大可不必。
Pull from upstream at 00:00:00Z every Sunday
同步 upstream 与 fork。定时于每个星期日早上 8 时(中国标准时)运行。也可以用 repository_dispatch 触发。
取了一个折中的时间,不至于空跑费电太多。一年大约 52 星期,70% 无意义,运行一次大约 40 秒,这个浪费还可以接受。
本来想设成每个月跑一次,但在密集的时期,起不到该有的便利,经常需要 contributor 自己手工操作。
研究这方面主要是想方便 Asuka Minato。他似乎很频繁,但没有掌握怎么同步。希望这次找的 3 个方案能帮到他。但愿我曾经说错的办法没有给他造成太多困扰。
你好像落了第 1 问。
@Lemmingh 奇怪,上一条评论 Github 怎么没发邮件提醒……
标签颜色已修改。
你好像落了第 1 问。
嗯?是指“是否需要拉直历史记录的那两个结”吗?拉直了之后是个什么效果呢?
没邮件
你查查垃圾箱。国内的邮件服务商有时会莫名其妙地屏蔽海外来的邮件。
拉直的效果
就是反复应用 cherry-pick 和 rebase,把那些 commit 都移到一条线上。最后 force push,得到一条直线的、易于查看的历史记录。
垃圾箱里没有啊,而且在此之前和之后的邮件都收到了……
那拉直有什么坏处咧。
垃圾箱里没有啊
恐怕是被服务器拒收了。😂
拉直有什么坏处
操作难度大:
- 需要 force push。因为修改点及之后的 commit 的 SHA 变了。
- 需要 amend 一些 commit message 以正确链接历史上的 PR。(如果没有历史回溯需求,可以省略)因为 SHA 变了,GitHub 无法自动定位到新的 commit。
在有严格的审计制度的项目里,这是麻烦事。但在其他地方,只是一两个小时的工作。
那就不拉直了吧,留个纪念(?)。
好,你说啥就是啥。
接着聊之前的。
你看 .mergify.yml 和 github-repo-sync.yml 写得怎么样?有什么需要改的吗?
你看 .mergify.yml 和 github-repo-sync.yml 写得怎么样?有什么需要改的吗?
还不错吧………………
好吧说实话,光看这些规则我在理解上还是有障碍,实际用一用可能会比较容易理解。如果这两个东西不致于会造成什么破坏的话,干脆实际上马看看效果?
这表情有些年头了……
给我 1 个月写文档。
Step 2. 🚀 📖 Add automation services
Assignees: @Lemmingh Estimated: 28 days
- Add configuration files:
-
.github/workflows/repo-sync.yml(probably a more suitable name) -
.mergify.yml
-
- Update docs:
-
docs/Automation-services/Mergify.md -
docs/Automation-services/Workflow-repo-sync.md -
docs/CONTRIBUTING.md -
docs/Labels.md -
README.md
-
Step 3. 🧪 Validation
Assignees: @Lemmingh, @TieBaMma Estimated: 6 months
现在的状态就是等。
估计未来半年内的活动足以测试。
有问题及时讨论。👏
Stale bot
建议引入 Stale 来标记活跃状况。
- 需要
Needs-Feedbacklabel。我推荐的颜色有:-
#737300昏暗的黄色 -
#E6E600明亮的黄色 -
#000000黑底白字 -
#000080深沉的蓝色
-
- 我推荐一个很安静的配置,已提交在 PR 64。
@TieBaMma 可以请你谈一下对 Stale bot 的态度吗?
@TieBaMma 可以请你谈一下对 Stale bot 的态度吗?
说实话我觉得必要性不是很强(如果我对它的功能理解无误的话),不过我觉得在条件允许的前提下尽量尝试新东西总是好的。
Stale 的功能有
- 用 label 标出所有不活跃的 issue / PR。
- 推送 comment 以提醒参与者。
- 关闭陈旧、没人搭理的 issue / PR。
我倾向于只打标记,所以我提交的配置仅会操作 label 以及在 PR 下发点 comment。
最终还是看你的需求。
如果是一个有上千个 item 的项目,label、bot 确实很省时间。对于这个现在还不太热的项目,如果你感觉全人工也能收拾,就随你了。