---
title: "actionlintとは？GitHub Actionsワークフローの静的解析ツールの使い方・インストール・設定"
url: "https://www.issoh.co.jp/tech/details/10397/"
published: 2025-12-25
updated: 2026-10-17
categories: ["CI/CD"]
publisher: "株式会社一創"
---

# actionlintとは？GitHub Actionsワークフローの静的解析ツールの使い方・インストール・設定

actionlintは、GitHub Actionsのワークフローファイル（`.github/workflows/*.yml`）をpushする前に検査する静的解析ツールです。作者はrhysd氏、Go製でMITライセンス、2026年10月時点の最新版はv1.7.12（2026年3月30日リリース）です。YAMLの構文だけでなく、`${{ }}`式の型、存在しないstep IDやjobへの参照、`run:`のシェルスクリプト（shellcheck連携）、信頼できない入力によるスクリプトインジェクションまで検出します。この記事では、実際に誤りを仕込んだワークフローに対するv1.7.12の出力と直し方を示したうえで、インストール、警告の除外設定、CIへの組み込みと必須チェック化、ghalint・zizmorとの使い分けを説明します。v1.7.12の後にGitHubが追加した構文（`concurrency.queue`やbackground steps、`ubuntu-26.04`ラベルなど）を誤ってエラーにする問題も、実測結果と回避設定をまとめました。

## まとめ：actionlintの要点（v1.7.12時点）

- 引数なしの`actionlint`で、リポジトリ内の`.github/workflows`配下を全部検査します。問題があれば終了コード1を返すので、CIの失敗条件にそのまま使えます。
- インストールはmacOSなら`brew install actionlint`、Windowsはwinget・Scoop・Chocolatey、CI上では公式のダウンロードスクリプトかDockerイメージ`rhysd/actionlint`が手軽です。
- shellcheckが入っている環境でだけ`run:`のシェルスクリプトも検査されます。入っていなくてもエラーにはならず、黙って省略されます。
- 誤検知や不要な警告は、`-ignore`オプション（正規表現）か`.github/actionlint.yaml`の`paths.<glob>.ignore`で除外します。セルフホストランナーのラベルもこのファイルに登録します。
- v1.7.12は2026年4月以降にGitHubが追加した構文を知りません。`cache-mode`・`concurrency.queue`・background steps・`uses: $/`・`ubuntu-26.04`は正しく書いてもエラーになるので、該当ファイルに限った`ignore`で逃がします。
- 検査対象はワークフローファイルです。composite actionの`steps`は検査されず、`action.yml`を単体で引数に渡すこともできません。権限の最小化やSHA固定といったセキュリティ方針の強制は守備範囲外で、ghalintかzizmorを併用します。

以下、検出内容の実例から見ていきます。

## actionlintが検出するエラーの実例

次のワークフローには、よくある誤りを8つ仕込んであります。GitHubにpushしてもYAMLとしては読み込めてしまうものが大半で、実行して初めて失敗するか、失敗すらせず意図と違う動きをします。

```
name: CI
on:
  push:
    branch: main              # 正しくは branches
  pull_request:
jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v3
      - name: Build
        id: build
        run: echo "version=1.0" >> $GITHUB_OUTPUT
      - name: Comment title
        run: echo "${{ github.event.pull_request.title }}"
      - name: Show version
        run: echo "${{ steps.bulid.outputs.version }}"   # build の打ち間違い
      - name: Show platform
        run: echo "${{ matrix.platform }}"                # matrix に platform は無い
  deploy:
    needs: tset                                          # test の打ち間違い
    runs-on: linux-gpu
    steps:
      - run: echo deploy
```

actionlint v1.7.12（shellcheck 0.11.0導入済み）で`-oneline`を付けて実行した結果です。8件すべてが行・列つきで報告され、終了コードは1でした。以下の出力では、長いメッセージの一部を「…」で省略しています。

```
$ actionlint -oneline
.github/workflows/ci.yaml:4:5: unexpected key "branch" for "push" section. expected one of "branches", "branches-ignore", "paths", "paths-ignore", "tags", "tags-ignore", "types", "workflows" [syntax-check]
.github/workflows/ci.yaml:13:15: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue [action]
.github/workflows/ci.yaml:16:9: shellcheck reported issue in this script: SC2086:info:1:23: Double quote to prevent globbing and word splitting [shellcheck]
.github/workflows/ci.yaml:18:24: "github.event.pull_request.title" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. ... [expression]
.github/workflows/ci.yaml:20:24: property "bulid" is not defined in object type {build: {conclusion: string; outcome: string; outputs: {string => string}}} [expression]
.github/workflows/ci.yaml:22:24: property "platform" is not defined in object type {os: string} [expression]
.github/workflows/ci.yaml:23:3: job "deploy" needs job "tset" which does not exist in this workflow [job-needs]
.github/workflows/ci.yaml:25:14: label "linux-gpu" is unknown. available labels are "windows-latest", ... [runner-label]
```

行末の角括弧はルール名（kind）です。出力から読み取れる検査の種類を整理すると次のとおりです。

| ルール名         | 検出したもの                | 放置した場合           |
| ------------ | --------------------- | ---------------- |
| syntax-check | 存在しないキー（branch）       | フィルタが効かず全ブランチで起動 |
| action       | ランタイムが古いアクション         | 実行時に非推奨警告・将来停止   |
| shellcheck   | 変数の未引用（SC2086）        | 空白を含む値で引数が割れる    |
| expression   | 信頼できない入力の直接埋め込み       | PRタイトル経由のコマンド注入  |
| expression   | steps・matrixの未定義プロパティ | 空文字に評価され気づけない    |
| job-needs    | 存在しないjobへのneeds       | ワークフロー全体が起動しない   |
| runner-label | 未知のランナーラベル            | ジョブが割り当て待ちのまま止まる |

特に効くのは`steps.bulid`と`matrix.platform`の2件です。GitHub Actionsは存在しないプロパティを空文字として評価するため、実行してもエラーにならず、空のバージョン番号がそのまま後続に流れます。actionlintは`id: build`の出力やmatrixの定義から型を組み立てて照合するので、この種の「静かな失敗」を実行前に拾えます。

このほか、cron式の妥当性（v1.7.12で`timezone`のIANA名検査が追加）、`workflow_dispatch`の入力数（v1.7.10で上限を25へ変更）、`permissions`の値、Reusable Workflowの`inputs`・`secrets`の型、`if: true`のような定数条件、YAMLアンカーの未使用なども検査対象です。全ルールは[actionlint v1.7.12の公式検査一覧（docs/checks.md）](https://github.com/rhysd/actionlint/blob/v1.7.12/docs/checks.md)に掲載されています。

### 8件を直した修正後のワークフロー

上の指摘を1件ずつ直したものが次のワークフローです。PRタイトルは`env:`で環境変数に渡してから`"$TITLE"`で参照し、`$GITHUB_OUTPUT`は二重引用符で囲みます。`linux-gpu`はGitHubホステッドランナーのラベルに置き換えました（セルフホストランナーのラベルとして使い続けるなら、後述の`actionlint.yaml`に登録します）。

```
name: CI
on:
  push:
    branches: main
  pull_request:
jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v7
      - name: Build
        id: build
        run: echo "version=1.0" >> "$GITHUB_OUTPUT"
      - name: Comment title
        env:
          TITLE: ${{ github.event.pull_request.title }}
        run: echo "$TITLE"
      - name: Show version
        run: echo "${{ steps.build.outputs.version }}"
      - name: Show platform
        run: echo "${{ matrix.os }}"
  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - run: echo deploy
```

同じv1.7.12で再実行すると出力は0行、終了コードは0でした。`actions/checkout`の最新メジャーは2026年10月時点でv7（v7.0.1、2026年7月20日リリース）です。

### actionlintの検査対象外とローカルアクションの検査範囲

公式ドキュメントに明記されている対象外が2つあります。1つは[composite action](/tech/details/8799/)の中身で、`docs/checks.md`に「`steps` in Composite action’s metadata is not checked at this point」とあります。もう1つは`action.yml`の単体検査で、ワークフローから`uses: ./path`で参照されたローカルアクションのメタデータ（`name`・`description`・`runs`の必須キーや`runs.using`の値）は検査されますが、「it is not supported to specify `action.yml` directly via command line arguments」とされています。アクションを自作して配布するリポジトリでは、actionlintだけでは中身を守れません。

また、アクションをタグでなくコミットSHAで固定しているか、jobごとに`permissions`を絞っているかといった運用方針は検査しません。構文と型が正しくても安全とは限らないので、この領域は後述のghalint・zizmorに任せます。

## actionlintのインストール方法

[公式のインストール手順（docs/install.md）](https://github.com/rhysd/actionlint/blob/v1.7.12/docs/install.md)に載っている入手経路をOS別にまとめました。どれで入れても中身は同じ単一バイナリです。

| 環境                       | コマンド                                               |
| ------------------------ | -------------------------------------------------- |
| macOS（Homebrew公式formula） | `brew install actionlint`                          |
| Windows（winget）          | `winget install actionlint`                        |
| Windows（Scoop）           | `scoop install actionlint`                         |
| Windows（Chocolatey）      | `choco install actionlint`                         |
| Arch Linux               | `pacman -S actionlint`                             |
| Nix（NixOS以外）             | `nix-env -iA nixpkgs.actionlint`                   |
| mise                     | `mise use -g actionlint@latest`                    |
| Docker                   | `docker run --rm rhysd/actionlint:latest -version` |

上記のパッケージマネージャーが使えないLinux環境では、リリースページのビルド済みバイナリか、次のダウンロードスクリプトを使います。スクリプトは最新版をカレントディレクトリに置き、第1引数でバージョン、第2引数で配置先を指定できます。

```
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) latest /usr/local/bin
actionlint -version
```

Goのツールチェーンがあれば`go install github.com/rhysd/actionlint/cmd/actionlint@latest`でもビルドできます。サポートされるGoは直近2系列（v1.7.12時点で1.25と1.26）です。

### Homebrewのformulaとcaskの違い

`brew install actionlint`で入るのはHomebrew本体が管理する公式formulaです。rhysd/actionlintリポジトリは別に独自のcaskも提供しており、リリースと同時に自動更新されます。以前あったリポジトリ独自のformulaはv1.7.11で廃止されたので、rhysd/actionlintをtapしてformulaで入れていた場合は、公式formulaかcaskへ切り替えます（公式formulaには影響ありません）。

```
brew tap "rhysd/actionlint" "https://github.com/rhysd/actionlint"
brew install --cask actionlint
```

caskのバイナリは署名されていないため、macOSが警告を出してゴミ箱へ移そうとします。使う場合は「システム設定」の「プライバシーとセキュリティ」で実行を許可する必要があり、特にこだわりが無ければ公式formulaの方が手間はかかりません。

### ダウンロードしたバイナリの真正性確認

v1.7.11以降のリリース成果物にはArtifact attestationが付いており、GitHub CLIで改ざんされていないかを検証できます。CIでバイナリを取得する構成なら、検証の1行を足しておく価値があります。

```
gh release download --repo rhysd/actionlint --pattern '*_linux_amd64.tar.gz' v1.7.12
gh attestation verify -R rhysd/actionlint actionlint_1.7.12_linux_amd64.tar.gz
```

## actionlintコマンドの使い方と終了コード

基本は3通りです。引数なしならカレントディレクトリから親をたどってGitリポジトリを探し、その`.github/workflows`を全部検査します。ファイルを指定すればそれだけを、`-`を渡せば標準入力を検査します。

```
actionlint                                    # リポジトリ内の全ワークフロー
actionlint .github/workflows/ci.yaml         # ファイル指定
cat ci.yaml | actionlint -stdin-filename ci.yaml -   # 標準入力
```

Gitリポジトリの外で引数なしで実行すると、`no project was found in any parent directories`と出て終了コード3で止まります。`git init`前のディレクトリで試すときはファイルを明示してください。終了コードの意味は次のとおりです。

| 終了コード | 意味              |
| ----- | --------------- |
| 0     | 実行成功・問題なし       |
| 1     | 実行成功・問題あり       |
| 2     | コマンドラインオプションが不正 |
| 3     | その他の致命的エラー      |

### よく使うコマンドラインオプション

v1.7.12の`actionlint -h`に並ぶフラグは13個です。日常的に使うものを用途別に絞りました。

| オプション                  | 用途                            |
| ---------------------- | ----------------------------- |
| `-oneline`             | 1エラー1行で出力（grepやCIログ向け）        |
| `-format '{{json .}}'` | JSONなどGoテンプレートで整形             |
| `-ignore <正規表現>`       | 一致するエラーを除外（複数指定可）             |
| `-config-file <パス>`    | 既定以外の場所の設定ファイルを読む             |
| `-init-config`         | .github/actionlint.yamlの雛形を生成 |
| `-shellcheck=`         | shellcheck連携を止める（空文字）         |
| `-pyflakes=`           | pyflakes連携を止める（空文字）           |
| `-color`／`-no-color`   | 色付けの強制・無効化                    |
| `-verbose`／`-debug`    | 読み込んだ設定や処理過程を表示               |

`-format '{{json .}}'`はJSON配列で`message`・`filepath`・`line`・`column`・`kind`・`snippet`を返します。公式リポジトリの`testdata/format/sarif_template.txt`の内容を`-format "$(cat sarif_template.txt)"`のように渡せばSARIF形式にもできるので、GitHubのCode scanningへ結果を上げる構成も組めます。

## 警告を除外する方法：-ignoreとactionlint.yaml

actionlintには「この行だけ無視する」ためのコメント記法がありません。除外はエラーメッセージに対する正規表現で行います。手段は目的別に3つです。

### \-ignoreオプションによる一時的な警告除外

`-ignore`はRE2構文の正規表現で、エラーメッセージに一致したものを落とします。繰り返し指定できます。

```
actionlint -ignore 'SC2086:' -ignore 'label ".+" is unknown'
```

冒頭の例にこの2つを付けると、shellcheckのSC2086とランナーラベルの2件が消えて6件になりました。CIのコマンドに書き足すだけで済む一方、ローカル実行やエディタ連携には効かないので、恒常的な除外は次の設定ファイルへ移します。

### .github/actionlint.yamlによる恒常的な警告除外

設定ファイルは`.github/actionlint.yaml`（または`.yml`）に置き、`actionlint -init-config`で雛形を生成できます。v1.7.12で設定できるのは3項目だけです。

```
self-hosted-runner:
  labels:
    - linux-gpu            # セルフホストランナーに付けた独自ラベル
config-variables:          # 定義済みの vars.* を列挙すると未定義参照を検出
  - DEPLOY_ENV
paths:
  .github/workflows/**/*.{yml,yaml}:
    ignore:
      - 'SC2086:'
  .github/workflows/release.yaml:
    ignore:
      - 'the runner of ".+" action is too old to run on GitHub Actions'
```

`self-hosted-runner.labels`は[セルフホストランナー](/tech/details/7759/)を使うリポジトリでほぼ必須です。登録しないと、独自ラベルがすべて`label "..." is unknown`として報告されます（globパターンも書けます）。`config-variables`は既定の`null`だと検査なし、配列を書くとそこに無い`vars.*`をエラーにし、空配列なら`vars`の使用自体を禁止します。`paths`のキーはリポジトリルートからの相対パスに対するglobで、区切りは常に`/`です。

### shellcheckの警告抑制と外部ツール連携の無効化

shellcheck由来の指摘は、`run:`のスクリプト内に`# shellcheck disable=SC2086`と書くとそのスクリプトだけ抑えられます（v1.7.12とshellcheck 0.11.0で確認）。全体で特定ルールを外すなら環境変数`SHELLCHECK_OPTS='--exclude=SC2086'`を使います。shellcheck連携そのものを止めるには`-shellcheck=`（空文字）を渡します。外部プロセスを大量に起動しなくなるため、実行時間も短くなります。pyflakes連携（`shell: python`のスクリプト検査）も同様に`-pyflakes=`で止められます。

## v1.7.12が未対応のGitHub Actions新構文と誤検知の回避

actionlintはワークフローのキーやランナーラベルの一覧を本体に埋め込んでいるため、GitHub側の追加にはリリースで追随します。ところがv1.7.12（2026年3月30日）の後、2026年10月17日時点まで新しいリリースは出ていません。その間にGitHubの[ワークフロー構文リファレンス](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax)には次の構文が加わり、正しく書いてもv1.7.12はエラーを返します。公式の記述どおりに書いたワークフローを、v1.7.12と、mainブランチを`go install ...@main`でビルドした版（v1.7.13-0.20260419144658-011a6d15e749）の両方で検査しました。

| 新しい構文                                              | 公式に載った時期     | v1.7.12          | mainビルド          |
| -------------------------------------------------- | ------------ | ---------------- | ---------------- |
| `services.<id>.entrypoint`・`command`               | 2026年4月      | unexpected key   | エラーなし            |
| `concurrency.queue`                                | 2026年5月      | unexpected key   | unexpected key   |
| `background`・`wait`・`wait-all`・`cancel`・`parallel` | 2026年6月      | unexpected key 等 | 同左               |
| `uses: $/...`（自リポジトリ参照）                            | 2026年7月      | ref is missing   | ref is missing   |
| `cache-mode`（workflow・job）                         | 2026年9月      | unexpected key   | unexpected key   |
| `runs-on: ubuntu-26.04`・`-arm`                     | 2026年9月17日GA | label is unknown | label is unknown |

mainで直っているのはservicesの`entrypoint`・`command`（PR #645）だけです。`queue`はPR #654、`$/`はPR #732が2026年10月17日時点で審査中のまま、`ubuntu-26.04`はissue #682が未対応です。background系の4キーワード（`wait`・`wait-all`・`cancel`・`parallel`）は`step must run script with "run" section or run action with "uses" section`として、`background: true`は`unexpected key "background"`として報告されます。

この中で影響が大きいのはランナーラベルです。GitHubは[2026年9月17日のChangelog](https://github.blog/changelog/2026-09-17-ubuntu-26-generally-available-and-latest-migration/)でUbuntu 26.04ランナーの一般提供と、`ubuntu-latest`を2026年10月19日から11月19日にかけて段階的に26.04へ切り替えると告知しました。`ubuntu-latest`のままなら actionlint は困りませんが、版を固定するために`ubuntu-26.04`と書いた時点でCIが落ちます。なお`ubuntu-latest`の切り替えでランナーのshellcheckも0.9.0（Ubuntu 24.04イメージ）から0.11.0（26.04イメージ）に上がるため、CI上のactionlintの検出内容が変わることがあります（[actions/runner-imagesのUbuntu 26.04イメージ一覧](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2604-Readme.md)で確認）。

### 新構文の誤検知をファイル単位で除外する設定

上の表の構文をすべて使った`deploy.yaml`は、v1.7.12で13件のエラーになりました。次の設定を置くと、その13件はすべて消えます。ランナーラベルは`self-hosted-runner.labels`に足すのが正規の逃がし方です。

```
self-hosted-runner:
  labels:
    - ubuntu-26.04
    - ubuntu-26.04-arm
paths:
  .github/workflows/deploy.yaml:      # 新構文を使っているファイルだけに限定する
    ignore:
      - 'unexpected key "(cache-mode|queue|background|entrypoint|command)"'
      - 'step must run script with "run" section'
      - 'specifying action "\$/'
```

`paths`のキーを`**/*.{yml,yaml}`にして全ファイルへ広げるのは避けてください。`step must run script with "run" section`は、`run`も`uses`も書き忘れた本物のミスと同じメッセージです。同じリポジトリに`run`を書き忘れたステップを持つ別ファイルを置いて検査すると、そちらのエラーだけが残り、終了コードは1でした。除外対象外のファイルでは本物のミスを引き続き検出できます。一方、除外対象のdeploy.yaml内では、runやusesの書き忘れも同じ正規表現に一致して見逃されるため、該当ステップの目視確認が必要です。新しいリリースが出たら、この`ignore`を消して再実行し、残るエラーが無いかを確かめます。

見慣れない`unexpected key`が出たら、除外する前にGitHubのワークフロー構文リファレンスにそのキーがあるかを確かめてください。リファレンスで見つからない場合は、GitHub公式Changelogや対象環境の対応状況も確認し、正式な構文と確認できるまでは除外しないでください。過去の版でも、v1.7.11で`case()`関数と`macos-26-large`・`windows-2025-vs2026`ラベル、v1.7.12で`macos-26-intel`に対応したように、GitHub側の追加はリリース単位で取り込まれてきました。逆にmacOS 13ランナーのように提供が終わったラベルは、v1.7.10からエラー扱いです。

## GitHub ActionsのCIでactionlintを動かす方法

CIへの組み込み方は4通りあり、違いはバイナリの入手方法と結果の見せ方です。

| 方法                          | 結果の表示                    | 向いている場面                     |
| --------------------------- | ------------------------ | --------------------------- |
| 公式ダウンロードスクリプト               | ログ（Problem Matcher併用で注釈） | 依存を増やしたくない                  |
| Dockerイメージ                  | ログ                       | shellcheck・pyflakesも同梱で使いたい |
| reviewdog/action-actionlint | 既定はChecks、設定でPR行コメント     | レビューで指摘を見せたい                |
| raven-actions/actionlint    | PRの注釈・ジョブ出力              | キャッシュやWindows・macOSでも動かしたい  |

### 公式スクリプトによるactionlintの取得とCI実行

公式ドキュメントが推奨する形です。スクリプトはダウンロードした実行ファイルの絶対パスを`executable`出力に書くので、次のステップから参照できます。

```
name: Lint GitHub Actions workflows
on: [push, pull_request]
jobs:
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: Download actionlint
        id: get_actionlint
        run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
        shell: bash
      - name: Check workflow files
        run: ${{ steps.get_actionlint.outputs.executable }} -color
        shell: bash
```

`shell: bash`を明示しているのは、Windowsランナーの既定シェルがpwshで、`<( )`のプロセス置換が通らないためです。shellcheckはUbuntuランナーにプリインストールされているので、ubuntu-latestならshellcheck連携も有効になります。結果をファイル差分上に注釈として出したい場合は、公式の`actionlint-matcher.json`を`.github/`に置き、実行前に`echo "::add-matcher::.github/actionlint-matcher.json"`を1行入れます。

この例は`main`ブランチのスクリプトを毎回取りに行くので、再現性を重視するなら、ダウンロードURLの`main`を確認済みのコミットSHAに置き換え、さらに第1引数へ`1.7.12`を渡して取得するバイナリの版も固定します。`actions/checkout`などの参照をタグでなくコミットSHAで固定する方法は[SHA Pinningの解説](/tech/details/10238/)にまとめています。

### 公式DockerイメージによるactionlintのCI実行

公式イメージ`rhysd/actionlint`にはshellcheckとpyflakesが同梱されています。`uses: docker://`で直接呼べます。

```
      - name: Check workflow files
        uses: docker://rhysd/actionlint:1.7.12
        with:
          args: -color
```

タグは`latest`とバージョン番号（`1.7.12`など）が用意されています。Dockerコンテナのアクションが動くのはLinuxランナーだけなので、macOS・Windowsランナーのjobでは使えません。

### reviewdog・raven-actionsによる検査結果の表示

`reviewdog/action-actionlint`は公式ドキュメントにも統合例として載っており、`on: [pull_request]`のジョブに`uses: reviewdog/action-actionlint@v1`を追加すると、既定のreporter（`github-pr-check`）でChecksに結果が出ます。[reviewdog/action-actionlintのREADME](https://github.com/reviewdog/action-actionlint)は、必要な権限としてジョブの`permissions:`に`contents: read`・`checks: write`・`issues: write`・`pull-requests: write`の4つを挙げています。PRの該当行にコメントとして付けるには、`with:`で`reporter: github-pr-review`を指定します。forkからのPRではトークンの書き込み権限が制限されるため、同じ投稿動作にはなりません。検出時にジョブも失敗させる場合は`fail_level: error`を指定します。

`raven-actions/actionlint`はランナーのOS上でネイティブに動くアクションで、actionlintのバイナリをActionsのキャッシュに保存し、Problem Matcherでの注釈も既定で有効です。`flags`入力で`-ignore`などを渡せ、`fail-on-error: false`にすると失敗させずに`total-errors`などの出力だけ受け取れます。

```
      - name: actionlint
        uses: raven-actions/actionlint@v2
        with:
          flags: "-ignore SC2086"
```

どちらもサードパーティ製アクションなので、組織の方針でMarketplaceアクションの利用を絞っている場合は、公式スクリプトかDockerイメージを選ぶ方が審査を通しやすくなります。ワークフローの基本構文から確認したい場合は[GitHub Actionsの概要と使い方](/column/details/3005/)が入口になります。

### actionlintをマージの必須チェックにする設定

CIで動かしただけでは、actionlintが失敗してもPRはマージできてしまいます。止めるには、リポジトリの「Settings」→「Rules」→「Rulesets」でブランチ用ルールセットを作り、対象ブランチを指定してEnforcement statusをActiveに設定し、「Require status checks to pass before merging」にactionlintのジョブ名（上の例なら`actionlint`）を追加します。[GitHubのルールセットの説明](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets)どおり、有効にすると必須チェックの条件を満たすまでマージが制限されます。ただし、チェックの結論がskippedやneutralでも条件を満たすため、検査が実際に実行されたことまで保証する設定ではありません。

ここで`on.pull_request.paths`に`.github/workflows/**`を指定して「ワークフローを変えたPRだけ検査する」形にすると、ワークフローに触れないPRが永久に止まります。[GitHubの必須チェックのトラブルシューティング](https://docs.github.com/en/pull-requests/how-tos/merge-and-close-pull-requests/troubleshooting-required-status-checks)には、パスやブランチのフィルタでワークフローごとスキップされた場合、必須チェックは「Pending」のままマージを妨げると書かれています。actionlintは数秒で終わるので、必須にするジョブにはパスの絞り込みを付けない方が運用は単純です。CI/CD全体の設計から相談したい場合は、[DevOps・CI/CD導入支援](/service/system/devops/)も用意しています。

## pre-commitとエディタによるコミット前の検査

CIで落ちてから直すより、コミット前に止める方が往復が減ります。pre-commitには公式フックがあり、`.pre-commit-config.yaml`に次を書きます。

```
repos:
  - repo: https://github.com/rhysd/actionlint
    rev: v1.7.12
    hooks:
      - id: actionlint
```

設定ファイルを保存したら、pre-commit導入済みの環境で`pre-commit install`を実行し、Gitのコミットフックを登録します。既存ファイルをまとめて検査するには`pre-commit run --all-files`を実行します。

フックIDは3種類あり、actionlintの入手方法が違います。

| フックID             | actionlintの入手方法    |
| ----------------- | ------------------ |
| actionlint        | Goツールチェーンで隔離環境にビルド |
| actionlint-docker | 公式Dockerイメージを取得    |
| actionlint-system | 手動でインストール済みのものを使用  |

既定の`actionlint`フックはpre-commit 3.0.0以降ならGo未導入でも自動取得して動作します。入手方法をチームで明示的に統一する場合は`actionlint-docker`か、各自がbrew等で入れる前提の`actionlint-system`が扱いやすいです。

エディタでは、VS Code拡張（vscode-actionlint）が`.github/workflows`を検出して編集中にエラーを表示します。Neovimはnvim-lint、VimとNeovimはALE、EmacsはFlycheck・Flymake用のパッケージが対応しています。インストールせずに試すだけなら、ブラウザ上のプレイグラウンド（rhysd.github.io/actionlint/）が使えます。WebAssemblyで動き、入力内容は外部へ送信されません。

## ghalint・zizmorとの違いと併用の判断

「github actions lint」で比較されるツールは3つありますが、検査している層が違うので、どれか1つを選ぶものではありません。

| ツール        | 主な対象        | 代表的な検査                             | 最新版     |
| ---------- | ----------- | ---------------------------------- | ------- |
| actionlint | 構文・式の型・シェル  | 未定義プロパティ、needs誤り                   | v1.7.12 |
| ghalint    | 組織のセキュリティ方針 | job単位のpermissions必須、SHA固定          | v1.5.6  |
| zizmor     | 攻撃経路の監査     | template-injection、cache-poisoning | v1.31.1 |

ghalint（作者はsuzuki-shunsuke氏）は「全jobに`permissions`を書く」「`read-all`・`write-all`を使わない」「`secrets: inherit`を使わない」「アクションの参照はフル長のコミットSHAにする」「`timeout-minutes`を必須にする」「`actions/checkout`の`persist-credentials`は`false`にする」といったポリシーを強制します。`ghalint run-action`で`action.yml`も検査でき、actionlintが見ない領域を補えます。zizmorは`template-injection`・`dangerous-triggers`・`excessive-permissions`・`unpinned-uses`・`cache-poisoning`など、v1.31.1（2026年10月15日）の[監査項目一覧](https://github.com/zizmorcore/zizmor/blob/v1.31.1/docs/audits.md)で41項目を持つセキュリティ特化の解析ツールです。

actionlintは、GitHub Actionsのワークフローを管理するリポジトリの基本検査として導入を勧めます。設定ファイルなしで導入でき、この記事の例のように未定義プロパティやjob参照の誤りを実行前に検出できるからです。そのうえで、パブリックリポジトリや`pull_request_target`を使うリポジトリにはzizmorを、社内で「permissionsとSHA固定を全リポジトリに強制したい」という方針があるならghalintを足します。逆に、actionlintのスクリプトインジェクション検査だけで供給網攻撃への備えができたと考えるのは誤りです。actionlintのインジェクション検査は、PRタイトルなどの信頼できない入力を`run:`や`actions/github-script`の`script`入力へ埋め込むパターンを対象としますが、アクションの参照先が書き換えられるリスクやトークン権限の過剰は対象外です。

なお、複数のリンターを束ねるsuper-linterもactionlintを内蔵しています。super-linter経由で動かす場合、`actionlint.yaml`の置き場所はsuper-linter側の規約に従うため、`.github/`に置いても読まれないことがあります。

## actionlint導入時の誤検知・未検出への対処

### shellcheckの未検出時に確認する導入状況

actionlintは実行環境に`shellcheck`コマンドがあるときだけ連携します。見つからなくてもエラーや警告は出ないため、ローカルでは指摘が出ずCI（Ubuntuランナーはプリインストール済み）では出る、という差が生まれます。`brew install shellcheck`などで開発機にも入れるか、同梱済みのDockerイメージで実行をそろえます。

### macOSでactionlintが終了しない場合のshellcheck連携の停止

Apple Silicon（darwin/arm64）のMacで、actionlintがCPUを使い続けたまま終わらないことがあります。issue #650によると、`run:`のステップが2つ以上あり、スクリプトの合計が1KB前後を超えると、shellcheckへスクリプトを渡す処理がデッドロックします。修正PR #651の説明では、公式バイナリのv1.7.10・v1.7.11・v1.7.12で再現しています。修正は2026年4月19日にmainへ取り込まれましたが、リリースはまだです。当面は`-shellcheck=`でshellcheck連携を止めるか、Dockerイメージ（Linux上で動く）で実行するか、`go install github.com/rhysd/actionlint/cmd/actionlint@main`で修正入りの版をビルドします。

### Windows・Linux混在matrixでのpwsh誤検知とシェル指定

`runs-on: ${{ matrix.os }}`のようにOSを静的に決められないjobでは、actionlintはシェルを楽観的にbashとみなします。`if: matrix.os == 'windows-latest'`で守ったPowerShellのスクリプトもshellcheckにかけられ、パス区切りなどで誤検知が出ます。そのステップに`shell: pwsh`を明示すれば、shellcheckの対象から外れます。shellcheckがかかるのは`bash`と`sh`だけです。

### Reusable Workflowのローカル参照と外部参照の検査範囲

`workflow_call`で呼び出すワークフローが`uses: ./.github/workflows/xxx.yml`のようなローカル参照なら、actionlintは呼び出し側の`with`・`secrets`と呼び出される側の`inputs`・`secrets`・`outputs`の定義を突き合わせます。公式ドキュメントにあるとおり、この照合は`./`で始まるローカル参照でしか働かず、別リポジトリの再利用ワークフローは中身を読めません。[Reusable Workflowsの設計](/tech/details/10765/)を外部リポジトリに切り出す場合は、呼び出される側のリポジトリにもactionlintを入れておきます。

## actionlintに関するよくある質問

### actionlintとは何ですか？

GitHub Actionsのワークフローファイルを実行前に検査する、Go製・MITライセンスの静的解析ツールです。YAMLの構文、`${{ }}`式の型、job間の依存、ランナーラベル、shellcheckによるシェルスクリプト検査、スクリプトインジェクションの検出を1コマンドで行います。

### actionlintをbrewでインストールするには？

`brew install actionlint`でHomebrewの公式formulaが入ります。rhysd/actionlintのcaskも`brew install --cask actionlint`で入りますが、署名されていないバイナリのためmacOSのセキュリティ設定で実行を許可する必要があります。

### actionlintで特定の警告を無視するには？

エラーメッセージに一致する正規表現を`-ignore`オプションで渡すか、`.github/actionlint.yaml`の`paths.<glob>.ignore`に書きます。行単位で無視するコメント記法はありません。shellcheck由来の指摘は、スクリプト内の`# shellcheck disable=SCxxxx`でも抑えられます。

### actionlintとghalintの違いは何ですか？

actionlintは構文・型・参照の誤りを見つけるツールで、ghalintは「全jobにpermissionsを書く」「アクションはコミットSHAで固定する」といったセキュリティ方針を強制するツールです。構文検査に加えて権限やSHA固定の方針も強制したい場合に、併用します。

### actionlintでaction.ymlやcomposite actionは検査できますか？

ワークフローから`uses: ./path`で参照されたローカルアクションの`action.yml`は、必須キーや`runs.using`の値が検査されます。ただし`action.yml`を引数で直接渡すことはできず、composite actionの`steps`の中身も検査対象外です。

## 関連記事

- [Composite Action（GitHub Actions）とは？action.ymlの書き方とpost処理の実装](/tech/details/8799/)
- [Reusable Workflowsの使い方｜GitHub Actionsのworkflow\_call・secrets・outputsと上限](/tech/details/10765/)
- [SHA Pinningとは？GitHub ActionsをコミットSHAで固定する方法【Enforce設定・pinact v5】](/tech/details/10238/)
- [GitHubセルフホストランナーとは？導入手順とhosted版の違い【2026年版】](/tech/details/7759/)
- [GitHub Actionsとは？できること・使い方とCI/CD自動化の活用例をわかりやすく解説](/column/details/3005/)

---

出典: [actionlintとは？GitHub Actionsワークフローの静的解析ツールの使い方・インストール・設定](<https://www.issoh.co.jp/tech/details/10397/>)（株式会社一創）
