pre-commitの出力に対してProblem Matchersを適用して、GitHubのPullRequestにAnnotationする
この記事は、GitHub Actions Advent Calendar 2024 の14日目の記事です。
GitHub Actions Advent Calendar 2024
https://qiita.com/advent-calendar/2024/github-actions
様々なlinter/formatterをpre-commitで動かし、
また、GitHubActions(pre-commit/actionを使う)でもチェックさせると、
linter/formatterを一箇所で管理できます。
pre-commit
https://pre-commit.com/
pre-commit/action | GitHub
https://github.com/pre-commit/action
GitHubActionsでは、
linter/formatterの出力にProblemMatcherを適用してAnnotationできますが、
出力形式の異なるものをpre-commitでまとめていると、
そのままではProblemMatcherを適用できません。
Problem Matchers | actions/toolkit | GitHub
https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md
この問題に対しては、
pre-commit hookにlog_fileの設定をおこなうことで対処が可能です。
log_file | .pre-commit-config.yaml - hooks | pre-commit
https://pre-commit.com/#config-log_file
このエントリでは、この対処方法の適用手順を説明します。
対象リポジトリの作成
まず対象リポジトリを作成します。
ここでは、flake8とmarkdownlintを導入したリポジトリを作成します。
mkdir problemmatcher-study && cd $_
git init
python -m venv venv
. venv/bin/activate
pip install pyproject-flake8
pip freeze > test-requirements.txt
リポジトリにファイルをcommit、GitHubにpushします。
echo "venv" > .gitignore
git add .
git commit -a -m "initial commit"
git remote add origin ※GitHubリポジトリを指定
git branch -M main
git push -u origin main
linterの適用対象のファイルを作ります。
main.py
import sys
def main():
pass
README.md
## foo
linterの設定を追加します。
pyproject.toml
[tool.flake8]
exclude = ["venv"]
flake8の動作を確認します。
$ pflake8
./main.py:1:1: F401 'sys' imported but unused
./main.py:2:1: E302 expected 2 blank lines, found 0
ブランチを切り替え、リポジトリにファイルをcommitしておきます。
git switch -c ci
git add .
git commit -a -m "add target files"
pre-commitの設定追加
pre-commitの設定を追加します。
.pre-commit-config.yaml
repos:
- repo: https://github.com/csachs/pyproject-flake8
rev: v7.0.0
hooks:
- id: pyproject-flake8
- repo: https://github.com/markdownlint/markdownlint.git
rev: v0.13.0
hooks:
- id: markdownlint
pre-commitの動作を確認します。
$ pre-commit run --files main.py README.md
pyproject-flake8.........................................................Failed
- hook id: pyproject-flake8
- exit code: 1
main.py:1:1: F401 'sys' imported but unused
main.py:2:1: E302 expected 2 blank lines, found 0
yamllint.............................................(no files to check)Skipped
Markdownlint.............................................................Failed
- hook id: markdownlint
- exit code: 1
README.md:1: MD002 First header should be a top level header
リポジトリにファイルをcommitします。
git add .pre-commit-config.yaml
git commit .pre-commit-config.yaml -m "add pre-commit"
GitHubActionsの設定追加
GitHub Actionsの設定を追加します。
.github/workflows/ci.yaml
name: CI
on: pull_request
jobs:
pre-commit-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pre-commit/action@v3.0.1
リポジトリにファイルをcommit、GitHubにpushします。
git add .github/workflows/ci.yaml
git commit -a -m "add github ci workflow"
git push origin ci
GitHubのUIからPullRequestをあげて、ステータスチェックが失敗することを確認します。
ProblemMatcherの設定追加
それでは本題のProblemMatcherを設定していきます。
ProblemMatcherの定義flake8用・markdownlint用を追加します。
.github/problem-matcher/flake8.json
{
"problemMatcher": [
{
"owner": "flake8",
"pattern": [
{
"regexp": "^(([^:]+):(\\d+):(\\d+):\\s+.+)$",
"message": 1,
"file": 2,
"line": 3,
"column": 4
}
]
}
]
}
.github/problem-matcher/markdownlint.json
{
"problemMatcher": [
{
"owner": "markdownlint",
"pattern": [
{
"regexp": "^(([^:]+):(\\d+):\\s+.+)$",
"message": 1,
"file": 2,
"line": 3
}
]
}
]
}
pre-commitでlogfileを出力して、CI側でProblemMatcherを適用するよう設定を変更します。
.pre-commit-config.yaml
repos:
- repo: https://github.com/csachs/pyproject-flake8
rev: v7.0.0
hooks:
- id: pyproject-flake8
log_file: /tmp/pre-commit-log-pyproject-flake8
- repo: https://github.com/markdownlint/markdownlint.git
rev: v0.13.0
hooks:
- id: markdownlint
log_file: /tmp/pre-commit-log-markdownlint
.github/workflows/ci.yaml
---
name: CI
on: pull_request
jobs:
pre-commit-run:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pre-commit/action@v3.0.1
- run: |
echo "::add-matcher::.github/problem-matcher/flake8.json"
cat /tmp/pre-commit-log-pyproject-flake8 \
| sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g"
echo "::remove-matcher owner=flake8::"
echo "::add-matcher::.github/problem-matcher/markdownlint.json"
cat /tmp/pre-commit-log-markdownlint \
| sed -r "s/\x1B\]8;;[^\x1B]*\x1B\\\\//g"
echo "::remove-matcher owner=markdownlint::"
if: always()
リポジトリにファイルをcommit、GitHubにpushします。
git add .github/problem-matcher
git commit -a -m "add ci problem matcher"
git push origin ci
GitHubのUIにAnnotationが表示されることが確認できます。
以上。