ESLintの実行結果をGitHub Code Scanningで確認する

Blog

GiHub Code Scanningとは

GitHub Code Scanning(以降、Code Scanning)は、リポジトリのコードを分析して、セキュリティの問題を検出できるGitHubの機能である。
検出された問題は、Code Scan Alertとして次の方法で確認できる。

  • 「Code Scanning」画面([Security]>[Code Scanning])
  • Pull Requestのコメント

また、Code Scanningでは、GitHub Actions経由でSARIF形式のファイルをアップロードすることで、ファイルの内容をCode Scan Alertに表示できる。
したがって、SARIF形式に対応しているツールであれば、その実行結果はCode Scanningの機能で確認できる。
SARIFファイルをGitHubにアップロードする

プライベートリポジトリの場合、Code Scanningを利用するにはAdvanced Securityライセンスが必要だが、パブリックリポジトリの場合は無料で利用できる。

ESLintの実行結果をSARIF形式に出力する

ESLint自体はSARIF形式での出力に対応していないため、@microsoft/eslint-formatter-sarifを利用する。

ESLint formatter for the SARIF (Static Analysis Results Interchange Format) v2.1.0 file format. Latest version: 3.1.0, last published: 5 months ago. Start using @microsoft/eslint-formatter-sarif in your project by running `npm i @microsoft/eslint-formatter-sarif`. There are 3 other projects in the npm registry using @microsoft/eslint-formatter-sarif.
npm
# インストール
npm install --save-dev @microsoft/eslint-formatter-sarif

--formatオプションに@microsoft/eslint-formatter-sarifを指定することで、SARIF形式に出力できる。 また、--output-fileオプションを指定すると、実行結果をファイルに出力できる。

# ESLintの実行
npx eslint -f @microsoft/eslint-formatter-sarif --output-file eslint-results.sarif

出力されたSARIF形式のファイルの例を以下に示す。

eslint-results.sarif
{
  "version": "2.1.0",
  "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.5",
  "runs": [
    {
      "tool": {
        "driver": {
          "name": "ESLint",
          "informationUri": "https://eslint.org",
          "rules": [
            {
              "id": "no-undef",
              "helpUri": "https://eslint.org/docs/latest/rules/no-undef",
              "properties": {},
              "shortDescription": {
                "text": "Disallow the use of undeclared variables unless mentioned in `/*global */` comments"
              }
            }
          ],
          "version": "9.5.0"
        }
      },
      "artifacts": [
        {
          "location": {
            "uri": "file:///Users/chick-p/works/playground/eslint.config.mjs"
          }
        },
        {
          "location": {
            "uri": "file:///Users/chick-p/works/playground/index.js"
          }
        }
      ],
      "results": [
        {
          "level": "error",
          "message": {
            "text": "'console' is not defined."
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "file:///Users/chick-p/works/playground/index.js",
                  "index": 1
                },
                "region": {
                  "startLine": 7,
                  "startColumn": 3,
                  "endLine": 7,
                  "endColumn": 10
                }
              }
            }
          ],
          "ruleId": "no-undef",
          "ruleIndex": 0
        }
      ]
    }
  ]
}

このSARIF形式のファイルをGitHubにアップロードすることで、Code Scan AlertにESLintの実行結果を表示できる。

Code Scan AlertにESLintの実行結果を表示する

GitHub ActionsではSARIF形式のファイルをGitHubにアップロードするActions(github/codeql-action/upload-sarif)が用意されている。
このActionsを使用すると、SARIF形式のファイルのアップロードを実現できる。

また、Code Scan AlertにESLintの実行結果を表示するにあたって、リポジトリの設定でCode scanningを有効にする必要はない。
スクリーンショット:Code scanningが未設定の状態

ESLintの実行結果をCode Scan Alertに表示するGitHub Actionsの設定例を以下に示す。
ESLintの実行は、npm run eslintで行なうことを想定している。

.github/workflows/eslint.yml
name: ESLint

on:
  pull_request:

permissions:
  contents: read
  security-events: write

jobs:
  eslint:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version-file: ./.node-version
          cache: "npm"

      - name: Install dependencies
        run: npm ci
        env:
          CI: true

      - name: Run eslint
        run: |
          npm run eslint -- -f @microsoft/eslint-formatter-sarif --output-file eslint-results.sarif
        continue-on-error: true

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: eslint-results.sarif
          wait-for-processing: true

このワークフローのポイントは、次の3点である。

ポイント1:permissions

security-eventsのwrite権限を付与する。
これで、GitHub ActionsによるCode Scan Alertの状態が更新可能になる。

permissions:
  contents: read
  security-events: write

ポイント2:エラーがあってもジョブを続行する

continue-on-error: trueを指定することで、ESLintの実行エラーがあってもジョブを続行できる。

- name: Run eslint
  run: |
    npm run eslint -- -f @microsoft/eslint-formatter-sarif --output-file eslint-results.sarif
  continue-on-error: true

ポイント3:SARIFファイルのアップロード

前述の通り、github/codeql-action/upload-sarifを使用して、SARIF形式のファイルをアップロードする。

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: eslint-results.sarif
          wait-for-processing: true

SARIF形式のファイルは「eslint-results.sarif」というファイルに出力されるため、sarif_fileにファイル名を指定する。

wait-for-processingはアップロードされたファイルが処理されることを待ってから、ジョブを完了するための設定である。 このパラメータは、デフォルトでtrueなので省略可能である。

動作確認

ESLintでエラーが検出されるコードで、Code Scan AlertにESLintの実行結果が表示されることを確認する。
まずは、ESLintでエラーを検出するコードを用意し、Pull Requestを作成する。

このPull Requestは、「CI Code Scanning」のジョブでエラーが発生する。
スクリーンショット:「CI Code Scanning」でエラーが発生している

ESLintのerrorとwarningのどちらも、Pull Requestにコメントされる。
スクリーンショット:Pull RequestにESLintの実行結果が表示されている

また、「Code Scanning」画面([Security]>[Code Scanning])でも、ESLintの実行結果を確認できる。
ただし、初期表示では「is:open branch:main」で絞り込まれている。
Pull Requestごとに結果を確認するには「is:open pr:PR番号」で絞り込みする。
スクリーンショット:「Code Scanning」画面にESLintの実行結果が表示されている