【Github】Github Actions ~ JSON Linter ~

■ はじめに

今日、TOMLファイルのカンマ忘れでシステムがうまく動かなくて、
ドハマりした。
設定ファイル系のJSON/YAML/TOMLなどは、コンパイルがないので
フォーマット誤りを起こしていたとしても、そこに気が付くのが
なかなか難しく、これを極力事前に分かるようにするために、
Github Actionsでチェックできる機構が欲しいなーっと思った。

そこで、今回は、手始めに、
JSONファイルをGithub Actionsでチェックする方法について
調べてみた。

目次

【0】Github Actionsでファイルチェックする方法を考える
【1】Third-Party Github Action を利用する
【2】Jqコマンドを利用する
【3】自作する

【0】Github Actionsでファイルチェックする方法を考える

* 他にも方法はあると思うが、とりあえず、以下を考えてみた。

[1] Third-Party Github Action を利用する
[2] Jqコマンドを利用する
[3] 自作する

【1】Third-Party Github Action を利用する

* 以下が利用可能
 => ただ、あんまり一般的な感じじゃないっぽい、、、

OrRosenblatt/validate-json-action
https://github.com/marketplace/actions/validate-json
limitusus/json-syntax-check
https://github.com/marketplace/actions/json-syntax-check

【2】Jqコマンドを利用する

* 例えば、Jqコマンドでエラーだったらフォーマットエラーと見なす

.github/workflows/demo-validate-json.yml

name: ValidateJson

on:
  push:
    paths:
      # JSON ファイル (.json) をプッシュするたびに実行
      - '**.json'

jobs:
  validate-json:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Validate JSON file
        run: |
          for file in '**.json'
          do
            echo "- target_file: ${file}"
            jq . $file
          done

正常なJSONの場合

{
  "Key1": "value1",
  "Key2": "value2",
  "Key3": "value3"
}

出力結果例

- target_file: **.json
{
  "Key1": "value1",
  "Key2": "value2",
  "Key3": "value3"
}

不正なJSONの場合

{
  "Key1": "value1",
  "Key2": "value2",
  "Key3": "value3",
  invalid
}

出力結果例

- target_file: **.json
parse error: Invalid numeric literal at line 6, column 0
Error: Process completed with exit code 4.

【3】自作する

正直、文法エラーチェックが簡易的に分かればいいので、
PythonのAPIを呼び出すだけでいいのではっと思う、、、

.github/validate_json.py

import json
import sys

# e.g. python3 demo.py test.json
#  => {'Key1': 'value1', 'Key2': 'value2', 'Key3': 'value3'}

input_json = sys.argv[1]

with open(input_json, 'r') as json_file:
  output = json.load(json_file)
  print(output)

.github/workflows/demo-validate-json.yml

name: ValidateJson

on:
  push:
    paths:
      # JSON ファイル (.json) をプッシュするたびに実行
      - '**.json'

jobs:
  validate-json:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12' 
      - name: Validate JSON file
        run: |
          for file in '**.json'
          do
            echo "- target_file: ${file}"
            # jq . $file
            python .github/validate_json.py $file
          done

OKの場合

- target_file: **.json
{'Key1': 'value1', 'Key2': 'value2', 'Key3': 'value3'}

NGの場合

- target_file: **.json
Traceback (most recent call last):
  File "/home/runner/work/github-actions-demo/github-actions-demo/.github/validate_json.py", line 10, in <module>
    output = json.load(json_file)
             ^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.12.4/x64/lib/python3.12/json/__init__.py", line 293, in load
    return loads(fp.read(),
           ^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.12.4/x64/lib/python3.12/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.12.4/x64/lib/python3.12/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.12.4/x64/lib/python3.12/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
               ^^^^^^^^^^^^^^^^^^^^^^
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 5 column 3 (char 64)
Error: Process completed with exit code 1.

関連記事

Github Actions ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/04/142835
Github Actions ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/06/16/151443
Github Actions ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/12/22/195715
Github Actions ~ Pythonを使うには ~
https://dk521123.hatenablog.com/entry/2024/02/04/011205
Github Actions ~ Python関連 ~
https://dk521123.hatenablog.com/entry/2022/06/21/143624
Github Actions ~ SQL Linter ~
https://dk521123.hatenablog.com/entry/2024/03/04/180308
Github Actions ~ Scala Linter ~
https://dk521123.hatenablog.com/entry/2024/04/02/002828
Github Actions ~ YAML Linter ~
https://dk521123.hatenablog.com/entry/2024/08/09/141801
Github Actions ~ TOML Linter ~
https://dk521123.hatenablog.com/entry/2024/08/10/115429
Python ~ 基本編 / コマンドライン引数 ~
https://dk521123.hatenablog.com/entry/2019/10/11/223651
Python ~ 基本編 / JSON
https://dk521123.hatenablog.com/entry/2019/10/19/104805
Python ~ 基本編 / JSONあれこれ ~
https://dk521123.hatenablog.com/entry/2022/02/14/000000