CI/CD

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

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)に掲載されています。

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の中身で、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)に載っている入手経路を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はセルフホストランナーを使うリポジトリでほぼ必須です。登録しないと、独自ラベルがすべて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のワークフロー構文リファレンスには次の構文が加わり、正しく書いても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で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イメージ一覧で確認)。

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

上の表の構文をすべて使った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の解説にまとめています。

公式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は、必要な権限としてジョブの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の概要と使い方が入口になります。

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

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

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

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日)の監査項目一覧で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の設計を外部リポジトリに切り出す場合は、呼び出される側のリポジトリにも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の中身も検査対象外です。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

ほか 3 件の記事からもリンクされています。

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.29 テックブログ ソニー生命の不正アクセス:38.5万件の対象確認と窓口、停止中の手続き
  2. 2026.10.31 テックブログ 松屋の不正アクセス:237万件の対象確認と窓口、漏れたパスワードの守り方
  3. 2026.10.31 テックブログ 無印良品の情報漏洩:MUJIアプリ最大2,726万件の対象確認となりすましメール対策
  4. 2026.10.27 テックブログ Joshin(ジョーシン)不正アクセス:最大600万件の対象とサブスク初期パスワードの対処
  5. 2026.10.28 テックブログ リンツ不正アクセス:314万件の対象確認とパスワード強制リセット後の対処

RELATED POSTS 関連記事

目次