GitHub Actions の Problem Matchers で ShellCheck の指摘を表示する

Today I Learned

ShellCheck は、シェルスクリプト用の Lint ツールで、文法上の問題や想定外な実行結果が起こらないようにチェックするツールである。
シェルスクリプトは雰囲気で書いているので、Linter があるのは嬉しい。

この記事では、ShellCheck の実行方法や、GitHub Actions の Problem Matchers で ShellCheck の指摘を表示する方法を説明する。

ShellCheck をインストールする

Mac であれば homebrew を使ってインストールできる。

$ brew install shellcheck

ShellCheck を実行する

ShellCheck は次のコマンドで実行できる。

$ shellcheck *.sh

例えば次のような、定義されていない変数を使っているようなスクリプトに対してチェックをしたとする。

invalid.sh
#!/bin/bash

echo "$foo"

ShellCheck を実行すると、構文エラーとなる項目が表示される。

$ shellcheck -f gcc *.sh

test.sh:3:7: warning: foo is referenced but not assigned. [SC2154]

GitHub Actions で ShellCheck を実行する

GitHub Actions では、ランナーが Linux の場合のみ、ShellCheck がプリインストールされている。
そのため、他の Lint ツールのように事前にインストールする必要がない。
Ref. https://github.com/koalaman/shellcheck#in-your-build-or-test-suites

ShellCheck を GitHub Actions で動かすためのアクションはいくつか公開されているが、開発元が公開した Actions はなかった。
今回は、Problem Matchers を使って、指摘内容を GitHub Actions のアノテーションに表示させる。
ちなみに、ludeeus/action-shellcheck というアクションでは、Problem Matchers を使ってアノテーション表示できるようだった。

エラー結果をキャプチャするルールファイルを追加する

Problem Matchers とは、GitHub Action の出力結果を正規表現のパターンとして解析し、アノテーションを表示する機能である。
出力結果のパターンをどのようにキャプチャするかのルールは、json ファイルで定義する。
あとで GitHub Actions のワークフロー側で指定するため、ファイル名や位置は何でも良い。
ただ、GitHub.com の機能なので、.github 以下に置くと行儀が良さそう。

owner に Problem Matchers の固有の ID を割り振り、pattern 以下に正規表現のパターンを定義する。
今回の ShellChecker は gcc 形式で出力するので、regexp は gcc 形式に合わせた正規表現とした。
また、キャプチャしたグループの順番を、file(ファイル名)や line(行番号)といったプロパティに指定する。

.github/shellcheck-matcher.json
{
  "problemMatcher": [
    {
      "owner": "shellcheck-matcher",
      "pattern": [
        {
          "regexp": "^(.+):(\\d+):(\\d+):\\s(note|warning|error):\\s(.*)\\s\\[(SC\\d+)\\]$",
          "file": 1,
          "line": 2,
          "column": 3,
          "severity": 4,
          "message": 5,
          "code": 6
        }
      ]
    }
  ]
}

GitHub Actions のワークフローを追加する

ShellChecker を実行する GitHub Actions のワークフローを追加する。
Problem Matchers を使って実行結果をキャプチャするには、ツールの実行前に echo "::add-matcher::ルールファイルのパス" を実行すれば良い。

.github/workflows/shellcheck.yml
name: shellcheck

on:
  pull_request:
    paths:
      - "*.sh"

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/[email protected]
      - name: Enable Problem Matchers
        run: echo "::add-matcher::.github/shellcheck-matcher.json"
      - name: Exec shellcheck
        run: |
          shellcheck -f gcc *.sh
          echo "::remove-matcher owner=shellcheck-matcher::"

先ほどの、定義していない変数を使ったシェルスクリプトに対し、このワークフローを実行すると、アノテーションにエラー内容が表示された。

画面キャプチャ:GitHub Actions のアノテーションに、ShellChecker の指摘が表示されている