铁轨上的危险:让机器人为您做一些代码审查!
本文是我最近的 RailsConf 演讲“Terraforming 遗留 Rails 应用程序”(视频、幻灯片)的 B 面。
我们开发人员的工作时间中,很大一部分都花在了代码审查上。有时,这比编写代码的时间还要多。即使花费几个小时,也无法避免错过拉取请求中的一些潜在问题。
我们只是人,我们都会犯错,尤其是在处理日常任务时。
谁喜欢做无聊的事,而且(几乎)不会犯错?机器人!🤖
在本文中,我想介绍一个可以帮助你进行代码审查的机器人。它的名字叫Danger(或者更准确地说,是她的名字)。
危险在您的 CI 过程中运行,并让团队有机会自动执行常见的代码审查工作。
将 Danger 添加到项目就像添加danger
到 Gemfile 并运行交互式bundle exec danger init
命令一样简单,该命令:
- 生成一个示例
Dangerfile
——您可以在其中使用 Ruby DSL定义审查规则; - 引导您完成 GitHub 集成设置;
- 最后,帮助您向 CI 添加危险任务。
宝石danger
本身仅提供一个“小核心”:
- Git 集成允许访问 repo 信息(提交、差异等)。
- Git 托管服务集成(GitHub、BitBucket、Gitlab)以访问 PR 数据并添加评论。
- (内部)CI 服务集成,以正确匹配 CI 构建和 PR。
所有特定功能(例如,linters 集成)都是通过插件实现的(请查看awesome-danger)。
这篇文章本来可以就此结束:安装 Danger,选择插件,添加 Dangerfile,就大功告成了。如果这就是我想要分享的全部内容,我可能只会发推文。事实证明,将 Danger 添加到 Rails 项目要复杂得多,也有趣得多……
GitHub 重新集成
Danger 假设以下GitHub 工作流程:
- 您创建一个新的 GitHub 用户;
- 将其作为合作者添加到 repo 中(对于闭源项目);
- 为该用户生成访问令牌并将其添加到 CI 中
DANGER_GITHUB_API_TOKEN
。
等等,创建一个新的 GitHub 用户?用邮箱和密码?难道没有更好的方法来添加机器人吗?有的,有——GitHub Apps。
GitHub Apps 可以完成我们需要的一切:读取 repos/PRs 数据、添加评论,更重要的是,拥有更细粒度的权限*。
* 最近,GitHub为协作者引入了新的权限级别:Triage 和 Maintenance。Triage 非常适合 Danger 用户。
主要区别在于 GitHub Apps 访问令牌的工作方式:它们的生命周期非常短(最多 10 分钟)。因此,每次运行 Danger 时,我们都需要生成一个访问令牌。
尽管如此,其他一切都保持不变:我们将此令牌作为用户的访问令牌传递,DANGER_GITHUB_API_TOKEN
并且 Danger 使用它就像用户的访问令牌一样。
继续阅读,了解如何创建 GitHub App 并使其充当 CircleCI 上的 Danger 机器人。
步骤 1.创建一个新的 GitHub 应用程序。
您可以创建个人 GitHub App,也可以创建组织级别的 GitHub App。如果您有组织,我们建议使用组织级别的 GitHub App。
按照以下说明创建新应用。我们只关注“权限”部分:
- 对“存储库内容”选择“读取”。
- 对“问题”选择“只读”(问题和 PR “密切相关”)。
- 为“拉取请求”选择“读写”。
在新创建的应用中,前往“安装应用”部分并将其安装到您的帐户。在那里,您将能够选择要与此应用一起使用的存储库列表。
别忘了为你的机器人选择一个头像)
步骤2.添加令牌生成器。
为了解决令牌过期问题,我们编写了一个简单的 Ruby 脚本 ( ),使用“身份验证即安装”github-token
流程请求新令牌。我们在 CircleCI 配置中是这样使用的:
danger:
executor: ruby
steps:
- attach_workspace:
at: .
- run:
name: Add github.com to known_hosts
command: mkdir -p ~/.ssh && ssh-keyscan -H github.com > ~/.ssh/known_hosts
- run:
name: Danger review
command: |
DANGER_GITHUB_API_TOKEN=$(bundle exec .circleci/github-token) bundle exec danger
- store_artifacts:
path: tmp/brakeman
该脚本的源代码
github-token
可以在evilmartians/terraforming-rails repo 中找到。
脚本本身需要以下信息:
- 私钥——前往应用程序的配置文件并生成一个;
- 您的应用程序 ID——您也可以在应用程序页面上找到它;
- 您的安装 ID — 转到https://github.com/organizations/MY-ORG/settings/installations(或个人安装的https://github.com/settings/installations),单击应用程序的“配置”,然后检查 URL:它应该是 的形式
.../installations/ID
。
将以上信息放入 CircleCI 环境中,分别使用以下名称:GITHUB_APP_PRIVATE_KEY
* GITHUB_APP_ID
、、GITHUB_INSTALLATION_ID
。
*CircleCI 不支持多行环境值,因此您可以执行以下操作来复制展平值:
$ cat private-key.pem | perl -p -e 's/\n/\\n/g' | pbcopy
该github-token
脚本将负责将密钥多行返回。
模块化Dangerfile
默认情况下,Dangerfile
这是所有审核检查的唯一入口点。将所有内容保存在一个文件中效果很好,但文件过大时通常很快就会变得过大。
另一方面,大多数检查彼此之间并不依赖。那么,为什么不分别保存在单独的文件中呢?
这正是我们所做的:
- 所有检查都存储在
.danger/
目录中的 Ruby 文件中。 Dangerfile
负责执行所有检查并包含一些共享逻辑。
这是我们的危险文件:
# Shared consts
CHANGED_FILES = (git.added_files + git.modified_files).freeze
ADDED_FILES = git.added_files.freeze
Dir[File.join(__dir__, ".danger/*.rb")].each do |danger_rule_file|
danger_rule = danger_rule_file.gsub(%r{(^./.danger/|.rb)}, "")
$stdout.print "- #{danger_rule} "
# execute each check using `eval`
eval File.read(danger_rule_file), binding, File.expand_path(danger_rule_file)
$stdout.puts "✅"
# allow a single check to fail without breaking others
rescue Exception => e
$stdout.puts "💥"
# make sure the result is a failure if some check failed to execute
fail "Danger rule :#{danger_rule} failed with exception: #{e.message}\n" \
"Backtrace: \n#{e.backtrace.join("\n")}"
end
输出如下所示:
$ bundle exec danger
- rails_credentials ✅
- missing_labels ✅
- brakeman ✅
- ruby_deps_inconsistency ✅
- updated_deps ✅
- missing_tests ✅
- merge_commits ✅
- db_schema_inconsistency ✅
- outdated_seeds ✅
Warnings:
- [ ] Are you sure we don't need to add/update tests for the main app?
额外奖励:危险遇见制动员
我开始尝试使用 Danger 的原因之一是想用Brakeman实现安全检查的自动化。简单地在 CI 上运行它并不符合我的要求:
- 我需要一种更好的方法来查看扫描仪运行的结果,最好是在 Github 上
- 我不希望制动员的失败让我的构建变成“红色”(它不是 100% 准确并且可能会产生误报,特别是当你使用大量元编程时)。
Danger 似乎是完成这项工作的合适工具。只是它没有现成的 Brakeman 集成(或插件)。
所以,我自己写了它,你可以在这里获取它。
该检查以编程方式运行 Brakeman(即无需 CLI),生成 HTML 报告并将链接*与报告摘要一起添加到最终危险结果中:
* 我们生成了一个指向 CircleCI 构建“Artifacts”选项卡的链接,报告可在此处找到。代码可在 中找到Dangerfile
。
综上所述
事实证明,Danger 是一个很好的代码审查伙伴。从现在开始,我会在每个项目中都使用它。
你对 Danger 有什么看法?有什么建议吗?欢迎在评论区分享!
附言:虽然我们已经在代码库中开源了上述代码terraforming-rails
,但更好的分享方式是向 Danger 本身和/或其插件添加 PR。所以,如果你想为开源软件做贡献——你知道该怎么做 😉。
阅读更多开发文章,请访问https://evilmartians.com/chronicles!
链接:https://dev.to/evilmartians/danger-on-rails-make-robots-do-some-code-review-for-you-5a3h