一个基于Github Actions的能修复lint问题并提PR解决的机器人
Mulatram One

我们的TeaCon参赛作品minecart-revolution仓库最近有格式问题看的人头疼,全改过来又太累。于是我整了个能自己修lint并提PR的Github Actions机器人,很好用,遂分享。

前言

我们的TeaCon参赛作品minecart-revolution仓库最近有格式问题看的人头疼,全改过来又太累。于是我整了个能自己修lint并提PR的Github Actions机器人,很好用,遂分享。

设计思路

核心就是 super-linter,这东西本身就集成了几十种 lint 工具(从 Java 到 JSON 到 Markdown 无一例外)。

但 super-linter 默认只报告错误,不会给你修。不难发现,super-linter 也暴露了 FIX_* 系列环境变量。于是我开了这些:

1
2
3
4
5
FIX_GOOGLE_JAVA_FORMAT: true  # Java 代码格式化
FIX_JSON: true # JSON 格式化
FIX_MARKDOWN: true # Markdown 格式化
FIX_NATURAL_LANGUAGE: true # 自然语言拼写修正
FIX_BIOME_FORMAT: true # Biome 格式化

开着这些跑一圈 super-linter,文件就被原地修好了。然后呢?直接用 git-auto-commit-action 把改动提交到新分支,再用 gh pr create 提个 PR,一个能自己修自己提的机器人就出来了。

坑和细化

递归问题无疑是第一个坑:这个 workflow 是 on: push 触发的,如果自动提交触发新的 push,那就无限循环了。解法很简单——新分支统一用 auto-lint-* 前缀,trigger 里直接排除:

1
2
3
4
on:
push:
branches-ignore:
- auto-lint-*

两个 job 的拆分也挺关键的。第一个 job lint-report 只做诊断,生成 report 存成 artifact;第二个 job fix-lint-issues 才真正修。分开的好处是:就算修的那步挂了,report 还是能拿到(毕竟修完了 diff 直接看也行,但我就是喜欢留个报告,,,)。

第二个 job 需要 contents: writepull-requests: write 权限,第一个只用读就够。权限最小化这事还是有追求的。

旧 PR 的清理:每次 push 都会开新 PR,旧的不关就堆起来了。我用 gh pr list --label auto-lint 找出旧的,逐个 close,再删掉对应的 remote branch。然后新 PR 用同样的 label auto-lint,方便一眼认出是机器人干的。

1
2
3
4
gh pr list --state open --label auto-lint --json number \
--jq '.[].number' | while read -r pr_num; do
gh pr close "$pr_num" --comment "Superseded by a newer auto-lint PR."
done

同run_id但是重新运行:要是你重跑一个已经跑过的 workflow,github.run_id 是一样的,分支名冲突就炸了。我直接把 github.run_attempt 也拼进分支名里:

1
echo "NEW_BRANCH=auto-lint-${{ github.run_id }}-${{ github.run_attempt }}" >> $GITHUB_ENV

重跑时 run_attempt 会自增,分支名就不同了。

Actions无法修改Actions,会报错:super-linter 如果顺手修了 .github/workflows/ 下的文件,后面的 git-auto-commit-action 推上去会直接炸——Github 不允许 workflow 自己改 workflow 文件。解决方式也很直接,让 super-linter 忽略这个目录就行:

1
FILTER_REGEX_EXCLUDE: .*\.github/workflows/.*

顺便一提

  • 如果没有lint问题是不会发新PR创建新分支的。
  • fuck-u-code 非常好工具,跑得快并且有意思,使我项目旋转,爱来自瓷器。\
  • 如果你想要我的Github Actions文件,可以下载super-linter.ymlfuck-u-code.yml
    这很有用,我希望帮助更多人。
 评论
评论插件加载失败
正在加载评论插件