我们的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 | FIX_GOOGLE_JAVA_FORMAT: true # Java 代码格式化 |
开着这些跑一圈 super-linter,文件就被原地修好了。然后呢?直接用 git-auto-commit-action 把改动提交到新分支,再用 gh pr create 提个 PR,一个能自己修自己提的机器人就出来了。
坑和细化
递归问题无疑是第一个坑:这个 workflow 是 on: push 触发的,如果自动提交触发新的 push,那就无限循环了。解法很简单——新分支统一用 auto-lint-* 前缀,trigger 里直接排除:
1 | on: |
两个 job 的拆分也挺关键的。第一个 job lint-report 只做诊断,生成 report 存成 artifact;第二个 job fix-lint-issues 才真正修。分开的好处是:就算修的那步挂了,report 还是能拿到(毕竟修完了 diff 直接看也行,但我就是喜欢留个报告,,,)。
第二个 job 需要 contents: write 和 pull-requests: write 权限,第一个只用读就够。权限最小化这事还是有追求的。
旧 PR 的清理:每次 push 都会开新 PR,旧的不关就堆起来了。我用 gh pr list --label auto-lint 找出旧的,逐个 close,再删掉对应的 remote branch。然后新 PR 用同样的 label auto-lint,方便一眼认出是机器人干的。
1 | gh pr list --state open --label auto-lint --json number \ |
同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.yml和fuck-u-code.yml
这很有用,我希望帮助更多人。