GitHub Actions 上で Markuplint のエラーログを検出してジョブを止める方法
Markuplint を初めて使ってみた。
存在はしっていたものの、実際には使ったことがなかったので検証してみました。
この記事は、markuplintの検出されたログをGithub Actionsでエラー検知する方法を紹介します。
結論
先に結論から述べます。
普段の開発では、reviewdog というツールを使いレポートをチェックしてジョブを失敗させています。
しかし、reviewdog のサポートには、markuplintは含まれていません。
ジョブを失敗させるため自作スクリプトを用意することにしました。
自作したシェルスクリプトは、以下のコードです。
検証リポジトリ
ブログ記事用に検証リポジトリを用意しました。
はじめに
まずはじめに環境を用意するところから始めていきます。
Vue.js のプロジェクトが多く担当しているので、本記事では Vue.js を前提に進めます。
- Node.js 20.11.0
- Vue.js 3系
- Markuplint 4系
導入時期で変わりますが、導入時は Markuplint 3系を利用していました。
しかし、 *.vue
ファイルに対して --fix
オプションを使うと HTML
以外の部分が削除されてしまうという問題がありました。
タイミングよく 4系がリリースされたため 4系を利用することにしました。
本題
ここから本題の GitHub Actions
でのエラー検知方法を紹介します。
まずは、Vue.js プロジェクトに Markuplint して導入します。
Vue.jsでプロジェクトを作成
Vue.jsの公式ドキュメント通りに create vue@latest
コマンドでプロジェクトを作成します。
npm create vue@latest
Vue.jsのプロジェクトを作成します。
Markuplint の導入
公式のドキュメント に設定ファイルを生成するCLIが用意されています。
npx markuplint --init
を実行すると、対話式で設定ファイルを生成することができます。
- template: Vue // Vueを選択
- May I install them automatically: true // 自動でインストールする
- customize rules: false // Customルールは検証のため false(必要に応じて設定します)
- import the recommended config: true // 推奨設定をインポートする
npx markuplint --init
? Which do you use template engines? …
✔ React (JSX)
✔ Vue
✔ Svelte
✔ SvelteKit
✔ Astro
✔ Pug
✔ PHP
✔ Smarty
✔ eRuby
✔ EJS
✔ Mustache/Handlebars
✔ Nunjucks
✔ liquid (Shopify)
? May I install them automatically? (y/N) true
? Do you customize rules? (y/N) › false
? Does it import the recommended config? (y/N) › true
インストールされた ルート配下に .markuplintrc
が生成されます。
{
"extends": [
"markuplint:recommended"
]
}
次に、HTML環境以外で利用する(.vueファイル)ため、Vueのparserとspecsをインストールします。公式ドキュメントが用意されています。
この2つをインストールすることで、独自の構文がある場合に対応することができます。
npm install -D @markuplint/vue-parser @markuplint/vue-spec
インストール後、 .markuplintrc
にparserとspecsを追記します。
{
"extends": [
"markuplint:recommended"
],
"specs": {
"\\.vue$": "@markuplint/vue-spec",
},
"parser": {
"\\.vue$": "@markuplint/vue-parser",
}
}
package.jsonにスクリプトを追加
package.jsonに markuplintを実行できるコマンドを追加します。
ここでのコマンドは、src
ディレクトリ配下の *.vue
ファイルを対象に --fix
コマンドで対象ファイルの修正および --config
設計ファイルのパスを定義します。
-f
でJSONを選択することで、エラー結果をJSONで出力することができます。
詳しいコマンドは、公式のコマンドインターフェイスを参照してください。
{
"scripts": {
"html:fix": "markuplint -f JSON src/**/*.vue --fix --config .markuplintrc"
}
}
試してみる
試しにコマンドが実行され、エラーログを出力できるか確認をします。
ここでは、試しに以下のようなHTMLコードを用意しておきました。
ボタンタグにdivタグを入れることでエラーを発生させます。
<button><div>エラーを出す</div></button>
npm run html:fix
を実行すると、以下のようなエラーログが出力されます。
[
{
"severity": "error",
"message": "このコンテキストでは、要素「button」に要素「div」を含めることはできません",
"line": 10,
"col": 13,
"raw": "<div>",
"ruleId": "permitted-contents",
"filePath": "XXXX/src/components/HelloWorld.vue"
}
]
このように対象ファイルを横断的に検証し、エラーログを出力することができます。
GitHub Actions のワークフローを作成
GitHub Actions の サンプルジョブを用意しました。
PRをトリガーに Markuplint を実行し、エラーログがあればジョブを失敗させることができます。
name: lint
on:
pull_request:
branches: [ main, develop ]
jobs:
lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '20.11.0'
- name: npm install
run: npm install
- name: Run Markuplint
run: |
./markuplint-check.sh
最後の行で、 ./markuplint-check.sh
を実行しエラーを出力した場合にジョブが失敗するようにしました。
- npm run html:fix を実行してエラーログを出力
- sed で1行目から4行目を削除
- 整形したログを temp_results.json に1時保存
-
[]
でない場合はエラーとしてジョブを失敗させる、それ以外はSuccess: No issues found by markuplint.
を出力
#!/bin/bash
# markuplint を実行して結果を一時ファイルに保存
# sed を使用して最初の4行を削除
npm run html:fix | sed '1,4d' > temp_results.json
# 結果ファイルが空でないかつ、"[]" ではない場合、エラーがあると見なす
if [ -s temp_results.json ] && [ "$(cat temp_results.json)" != "[]" ]; then
echo "Error: markuplint found issues."
# エラー詳細をログに出力
cat temp_results.json | jq '.[] | "\(.filePath):\(.line):\(.message)"' | while read line; do
echo "Error: $line"
done
# 一時ファイルを削除
rm temp_results.json
# 非ゼロの終了コードでスクリプトを終了
exit 1
else
echo "Success: No issues found by markuplint."
# 一時ファイルを削除
rm temp_results.json
# スクリプトを正常終了
exit 0
fi
先ほどの検証コードで利用した buttonタグにdivタグを挿入して PR を作成します。
エラーを起こしたPRは以下のジョブです。
エラーが検知され、ジョブが失敗していることが確認できます。
まとめ
このように、GitHub Actions で Markuplintのエラー出力に応じて ジョブを失敗させるためには 出力結果の状態に応じて行う形が必要です。
初めて使ったので、やり方が違うかもしれませんが自分はこの実装で対応してみました。
使用感として、reviewdog でもサポートされると嬉しいですが、出力結果のフォーマットでファイルで保存できるコマンドがあると嬉しいと感じました。
( sed は、拡張性の観点から個人的には避けたい)
個人的にMarkuplintに欲しい機能
- format type file コマンドでエラーログだけをファイル出力できるコマンド
GitHub Actions でエラー検知してジョブを失敗させたい場合の参考として読んでいただけると幸いです。
Discussion