言語を切り替える
テーマを切り替える

GitHub Actions入門:YAMLワークフローの基礎とトリガー設定

画面に表示される赤いエラーが目に刺さって、キーボードを叩き壊したくなる。

ローカルではちゃんと動いていたコードが、GitHubにプッシュした途端に落ちる。あのYAMLファイルを6回も直したのに、毎回インデントの問題ばかり。これって、コードを書くより難しいんじゃないか。

実のところ、GitHub Actions自体は複雑ではありません。やっかいなのはドキュメントです。いきなり数百ページの設定説明を渡されて、頭がくらくらしてしまう。この記事では、いちばんシンプルな方法で、YAMLワークフローのコア構造を理解していきます。

この記事で学べること:

  • YAMLファイルの4つのコアフィールドと、それぞれの実際の役割
  • よく使う8種類のトリガーの設定方法と利用シーン
  • そのままコピーして使える完全なワークフローテンプレート
  • 筆者がはまった落とし穴と、その避け方

準備はいいですか。それでは始めましょう。

YAMLワークフローファイル:4つのコアフィールド

正直に言うと、GitHub Actionsに触れたばかりの頃、.github/workflowsディレクトリ下のYAMLファイルを見て、まるで暗号のように感じました。インデントだらけ、コロンだらけで、スペースを1つ間違えるだけで全部落ちてしまう。

あとになって気づいたのですが、これは結局4つのコア部分でできています。この4つを理解すれば、残りはすべて応用にすぎません。

name:ワークフローに名前を付ける

このフィールドはいちばんシンプルですが、多くの人(筆者を含む)が最初は見落としてしまいます。

name: CI for Node.js App

nameは、あなたのワークフローがGitHub Actionsのタブページにどう表示されるかを決める名前です。コードをプッシュしたあと、リポジトリのActionsページを開くと、そこに表示される行がこれにあたります。

名前付けには小さなコツがあります。プロジェクト名+機能説明を使うのです。たとえばMyApp CIBackend Deployのように。こうしておくと、ワークフローが増えてきても、見たいものを一目で見つけられます。

このフィールドは実は省略できます。書かなければ、GitHubがファイル名で代用します。ただ、筆者は省略をおすすめしません。ファイル名はたいてい英語の略語で、見ても直感的ではないからです。

on:いつトリガーするか

8種類
よく使うトリガー
GitHub Actionsは数十種類のトリガーをサポートしていますが、実際のプロジェクトでよく使うのはpush、pull_request、schedule、workflow_dispatchの4種類です

onはワークフロー全体の「スイッチ」です。どんな状況でこのワークフローを実行するのかをGitHubに伝えます。

いちばんシンプルな書き方:

on: push

意味は、コードのプッシュがあればトリガーする、ということです。

ただ実際のプロジェクトでは、もっと細かい制御が必要になるのが普通です。たとえばmainブランチへのプッシュがあったときだけ実行する場合:

on:
  push:
    branches: [main]

あるいは、プルリクエストの作成時にもトリガーしたい場合:

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

トリガーはGitHub Actionsの真髄です。後半で、よく使う8つのシーンを1節まるごと使って説明します。ここでは、onがワークフローの「実行タイミング」を決める、とだけ覚えておけば十分です。

jobs:何をするかを定義する

jobsはワークフローの本体で、「具体的に何を実行するか」を定義します。

1つのワークフローには複数のjobを含められ、デフォルトでは並列に実行されます。各jobにはruns-onフィールドで実行環境を指定する必要があります。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # ...ステップ一覧

上のコードはbuildという名前のjobを定義しており、GitHubが提供するUbuntuの最新版で実行されます。

ワークフローに複数のjobがある場合、needsフィールドで依存関係を定義できます。

jobs:
  test:
    runs-on: ubuntu-latest
    # ... テストステップ

  deploy:
    needs: test  # testが終わってから実行
    runs-on: ubuntu-latest
    # ... デプロイステップ

こうするとdeploytestが終わるのを待ってから始まります。testが落ちれば、deployは実行されません。

steps:具体的な実行ステップ

stepsはjob内の最小実行単位で、コマンドやActionが1つずつ順番に実行されます。

各stepには2つの書き方があります。

1. runでコマンドを実行する:

steps:
  - name: Install dependencies
    run: npm ci

  - name: Run tests
    run: npm test

runのあとに書くのが、ターミナルで実行したいコマンドです。ローカルでコマンドを叩くのと同じです。

2. usesでActionを呼び出す:

steps:
  - name: Checkout code
    uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'

usesはGitHub Actionsの切り札です。誰かが作ってくれたActionを、そのまま使えます。たとえばactions/checkout@v4はコードを取得してくれますし、actions/setup-node@v4はNode.js環境を設定してくれます。

withはActionにパラメータを渡すためのものです。たとえば上のnode-version: '20'は、setup-nodeに「Node.js 20を使う」と伝えています。

4つのフィールドの説明が終わりました。思ったよりシンプルではないでしょうか。

トリガー徹底解説:よく使う8つのシーン

先ほど、onフィールドが実行タイミングを決めると述べました。GitHub Actionsは数十種類のトリガーをサポートしていますが、正直なところ、よく使うのはほんの数個です。

各トリガーの利用シーンをすばやく把握できるよう、表を用意しました。

トリガー典型的なシーン設定例
pushブランチへのコードプッシュon: push: branches: [main]
pull_requestPRの作成または更新on: pull_request: types: [opened, synchronize]
schedule定期実行(Cron)on: schedule: - cron: '0 0 * * *'
workflow_dispatch手動トリガーon: workflow_dispatch: inputs: env: ...
workflow_call再利用可能なワークフローon: workflow_call: inputs: ...
releaseリリースイベントon: release: types: [published]
issuesIssueイベントon: issues: types: [opened, labeled]
repository_dispatch外部イベントon: repository_dispatch: types: [deploy]

以下では、もっともよく使ういくつかを掘り下げて説明します。

push:もっとも基本的なトリガー

pushは最初に出会うトリガーです。コードをブランチにプッシュしたときにトリガーされます。

シンプルな設定:

on: push

ただ、この設定には問題があります。どのブランチへのプッシュでもトリガーされてしまうのです。リポジトリに20個のブランチがあると、誰かがコードをプッシュするたびにワークフローが走り、無料枠があっという間に使い切られてしまいます。

より合理的な設定は、ブランチを限定することです。

on:
  push:
    branches: [main, develop]

あるいはワイルドカードを使います。

on:
  push:
    branches:
      - 'main'
      - 'release/**'  # release/v1.0, release/v2.0 などにマッチ

pull_request:マージ前のコードを守る番人

pull_requestはPRの作成または更新時にトリガーされ、通常はテスト実行やコードスタイルのチェックに使います。

on:
  pull_request:
    branches: [main]

typesフィールドで、トリガーのタイミングをさらに制御できます。

on:
  pull_request:
    types: [opened, synchronize, reopened]
  • opened:PRが作成された直後
  • synchronize:PRに新しいコミットがあった
  • reopened:PRが再オープンされた

こう設定すると、この3つの状況でのみワークフローが走り、リソースを無駄にしません。

schedule:定期実行

scheduleはCron式で定期トリガーを定義します。たとえば毎日深夜にテストを1回実行する場合:

on:
  schedule:
    - cron: '0 0 * * *'  # 毎日 UTC 0時

Cron式には5つのフィールドがあります。分、時、日、月、曜日です。

よく使う時刻をいくつか挙げます。

  • 0 0 * * *:毎日 UTC 0時(日本時間の朝9時)
  • 0 */6 * * *:6時間ごと
  • 30 2 * * 1:毎週月曜 UTC 2:30

注意すべき落とし穴があります。GitHubが使うのはUTC時間です。日本時間の朝9時にタスクを実行したいなら、UTC 0時(0 0 * * *)に設定する必要があります。

workflow_dispatch:手動トリガー

自動でトリガーするのではなく、ボタンを押して手動で実行したいときもあります。workflow_dispatchはそのためのものです。

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'デプロイ環境'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

設定しておくと、Actionsページに「Run workflow」ボタンが表示され、クリックすると環境パラメータを選んでからトリガーできます。

このトリガーはデプロイのシーンでとくに実用的です。自動でテスト、手動でデプロイ、という使い分けができます。

workflow_call:ワークフローの再利用

ワークフローのロジックが複雑だったり、複数のリポジトリで同じ流れを使いたかったりする場合、workflow_callを使ってワークフローを再利用可能なコンポーネントにできます。

再利用可能なワークフローを定義する:

# .github/workflows/ci.yml
on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci && npm test

別のワークフローから呼び出す:

# .github/workflows/main.yml
on: push

jobs:
  call-ci:
    uses: ./.github/workflows/ci.yml
    with:
      node-version: '20'

こうすれば、異なるリポジトリ間で同じCIロジックを再利用でき、1か所を直せばすべてに反映されます。

ほかのいくつかのトリガー(releaseissuesrepository_dispatch)は比較的使う機会が少ないので、ここでは掘り下げません。興味があれば、GitHubの公式ドキュメントを参照してください。

実践:はじめてのワークフローテンプレート

ここまで概念をたくさん説明してきましたが、実際に手を動かして試してみるほうが早いでしょう。

以下は、完全なNode.jsプロジェクトのCIワークフローです。そのまま自分のプロジェクトにコピーして使えます。

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      # 1. コードを取得
      - name: Checkout code
        uses: actions/checkout@v4

      # 2. Node.js環境を設定
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      # 3. 依存関係をインストール
      - name: Install dependencies
        run: npm ci

      # 4. テストを実行
      - name: Run tests
        run: npm test

どう使う?

第1ステップ: プロジェクトのルートディレクトリに.github/workflowsフォルダを作成します(まだなければ)。

第2ステップ: このフォルダ内にci.ymlファイルを作成し、上のコードを貼り付けます。

第3ステップ: コミットしてGitHubにプッシュします。

プッシュしたあと、リポジトリのActionsタブを開くと、ワークフローが走っているのが見えるはずです。

1行ずつ解説

  • name: CI:ワークフロー名。Actionsページに表示される
  • on: push: branches: [main]:mainブランチにプッシュしたときトリガー
  • on: pull_request: branches: [main]:mainへのPRが出されたときもトリガー
  • jobs: build::buildという名前のjobを定義
  • runs-on: ubuntu-latest:GitHubが提供する最新のUbuntuで実行
  • actions/checkout@v4:公式Action。コードを仮想マシンに取得する
  • actions/setup-node@v4:公式Action。Node.js環境を設定する
  • npm ci:依存関係をインストール(npm installより速くクリーン)
  • npm test:テストを実行

プロジェクトがNode.jsでなければ、中間のステップを差し替えるだけです。たとえばPythonプロジェクトなら:

steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-python@v5
    with:
      python-version: '3.11'
  - run: pip install -r requirements.txt
  - run: pytest

基本的には「コード取得 → 環境設定 → 依存インストール → テスト実行」という流れの一連のパターンです。

よくある設定エラーの診断

筆者がはまった落とし穴です。あなたが二度とはまらないことを願っています。

ここに診断チェックリストをまとめました。問題が起きたときに照らし合わせて確認してください。

エラーの現象考えられる原因解決方法
ワークフローがトリガーされないブランチのフィルタ条件が誤りbranchesの設定を確認し、ブランチ名の大文字小文字が正しいか確認
YAMLの解析に失敗インデントにTabを使用すべてスペースのインデントに変更。YAMLはTabをサポートしない
Secretsが効かないスコープが誤りsecretsが正しい階層(jobまたはstep)にあるか確認
Jobの依存が失敗needsの参照が誤りjob-idのスペルを確認し、大文字小文字を区別
ワークフローの実行が遅いキャッシュ未使用actions/cacheを追加して依存をキャッシュ
権限不足でエラーGITHUB_TOKENの権限不足jobにpermissions設定を追加

エラー1:インデントを間違えた

これはもっともよくあるエラーで、ほかに並ぶものはありません。

YAMLはインデントに極めて敏感です。必ずスペースを使い、Tabは使えません。しかも各階層のインデントは2スペースでなければなりません(または統一された別の数字でもよいですが、GitHub Actionsのデフォルトは2です)。

# 誤った例:インデントが乱れている
jobs:
  build:
  runs-on: ubuntu-latest  # この行は4スペースのインデントが必要
# 正しい書き方
jobs:
  build:
    runs-on: ubuntu-latest  # 4スペースのインデント

ほとんどのエディタ(VS Code、WebStorm)は「Tabキーで自動的にスペースを挿入する」設定にできます。この設定を有効にして、毎回手動でスペースを打つ手間を省くことをおすすめします。

エラー2:ブランチ名を書き間違えた

GitHubのブランチ名は大文字小文字を区別します。mainMainは別々のブランチです。

# ブランチ名が main の場合
on:
  push:
    branches: [Main]  # 誤り。トリガーされない

# 正しい書き方
on:
  push:
    branches: [main]  # 小文字

ブランチ名が不確かなら、GitHubのリポジトリページで確認するか、ローカルでgit branchを実行しましょう。

エラー3:job-idのスペルミス

ワークフローに複数のjobがあり、依存関係を持つ場合、needsフィールドは他のjobのidを正確に参照しなければなりません。

jobs:
  test:
    runs-on: ubuntu-latest
    # ...

  deploy:
    needs: Test  # 誤り。大文字小文字が一致しない
    runs-on: ubuntu-latest
# 正しい書き方
jobs:
  test:
    runs-on: ubuntu-latest

  deploy:
    needs: test  # 小文字。上のjob idと一致
    runs-on: ubuntu-latest

エラー4:Secretsを誤った階層で使った

GitHubのSecretsには2つのスコープがあります。リポジトリレベルと環境レベルです。参照には${{ secrets.XXX }}を使います。

# 誤った例:secretsを誤った位置に書いた
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      API_KEY: secrets.MY_KEY  # 誤り。${{ }} がない
# 正しい書き方
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      API_KEY: ${{ secrets.MY_KEY }}  # ${{ }} で囲む

なお、Secretsは暗号化されており、ログ上では実際の値を見ることはできません。ログで正しく渡されたか確認したい場合は、代替の値を出力できます。

- name: Debug
  run: echo "API_KEY is set: ${{ secrets.MY_KEY != '' }}"

こうすれば実際のKeyを漏らさずに、空かどうかを確認できます。

GitHub Actions vs ほかのCI/CDツール

Jenkins、GitLab CI、CircleCIを使ったことがあるかもしれません。では、GitHub Actionsはそれらと比べてどんな強みと弱みがあるのでしょうか。

比較表を用意しました。

比較項目GitHub ActionsGitLab CIJenkinsCircleCI
設定言語YAMLYAMLGroovyYAML
ホスティング方式クラウドネイティブクラウド/セルフホストセルフホストクラウドネイティブ
統合度GitHubネイティブGitLabネイティブ要設定要設定
学習コスト
無料枠2000分/月(プライベート)400分/月無制限(セルフホスト)6000分/月
公開リポジトリ無制限無制限無制限無制限

GitHub Actionsの強み

1. ゼロ設定の統合

コードがすでにGitHubでホストされているなら、GitHub Actionsを使うのがいちばんスムーズな選択です。余計なwebhookの設定も、サーバーの保守も、プラグインのインストールも不要です。YAMLファイルを1つ作ってプッシュすれば、それで動きます。

2. Marketplaceのエコシステム

GitHub Marketplaceには何千ものActionがあり、AWS、Azure、Google Cloudにも公式Actionがあります。必要な機能は、たいてい誰かがすでに作ってくれていて、usesで呼び出すだけです。

3. 個人開発者にやさしい無料枠

公開リポジトリは無制限、プライベートリポジトリは月2000分です。個人プロジェクトや小規模チームなら、基本的に十分足ります。

GitHub Actionsを選ばないのはどんなとき?

1. コードがGitHubにない

GitLabやBitbucketを使っているなら、それらに付属するCI/CDを使いましょう。GitHub Actionsもwebhook経由でトリガーできますが、あれこれ手をかけるより、ネイティブの方法を直接使うほうが楽です。

2. 実行環境を完全に制御したい

GitHub Actionsのrunner環境は固定(Ubuntu/Windows/macOS)で、自分のソフトをインストールしたり特殊な環境を構成したりはできません。この場合は、Jenkins+セルフホストrunnerのほうが柔軟です。

3. セキュリティに極端な要件がある

GitHub Actionsのrunnerは、GitHubがホストする仮想マシンです。コードが高度に機微な情報を含むなら、CIシステムを自前で構築する必要があるかもしれません。ただし、GitHubもself-hosted runnerをサポートしており、折衷的に解決できます。

筆者のおすすめ

ほとんどの個人開発者と小規模チームには:

  • コードがGitHubにある → GitHub Actionsを選ぶ
  • コードがGitLabにある → GitLab CIを選ぶ
  • 高度なカスタマイズが必要 → Jenkinsまたはself-hosted runner

絶対的な最適解はありません。自分に合ったものこそが、いちばんよい選択です。

まとめ

ここまで読んで、GitHub ActionsのYAMLワークフローがどういうものか、おおよそわかってきたのではないでしょうか。

コアとなるポイント:

  • 4つのコアフィールド:nameで命名、onでトリガー、jobsでタスク定義、stepsで実行ステップ
  • 8種類のよく使うトリガー:もっとも使うのはpushpull_requestschedule
  • コピーできるテンプレート:コード取得 → 環境設定 → 依存インストール → テスト実行
  • 4つのよくある落とし穴:インデント、ブランチ名、job-id、Secrets

次にできること:

  1. 自分のプロジェクトではじめてのワークフローを作る(本記事のテンプレートをコピーし、自分のプロジェクト設定に書き換えるだけ)
  2. シリーズの応用記事『GitHub Actionsのキャッシュ戦略:CI/CDパイプラインを5倍高速化』を読み、ワークフローをもっと速く走らせる方法を学ぶ
  3. GitHub Marketplaceをのぞいて、そのまま使える便利なActionがないか探してみる

自動化というものは、一度その甘い果実を味わうと、もう後戻りできなくなります。

FAQ

GitHub Actionsのワークフローに必須のフィールドは何ですか?
最小構成では `on`(トリガー)と `jobs`(タスク定義)の2つのフィールドだけが必要です。`name` と `steps` は任意ですが、ワークフローを読みやすくするため省略はおすすめしません。
pushとpull_requestトリガーの違いは何ですか?
`push` はコードをブランチにプッシュしたときにトリガーされ、デプロイ処理に向いています。`pull_request` はPRの作成や更新時にトリガーされ、コードチェックやテストに向いています。通常は両方を組み合わせ、PRでテストを実行し、マージ後にデプロイを実行します。
YAMLのインデントはTabとスペースのどちらを使いますか?
必ずスペースを使います。YAMLはTabのインデントをサポートしません。VS Codeで「Tabでスペースを挿入」の設定を有効にして、落とし穴を避けることをおすすめします。各階層のインデントは通常2スペースを使います。
無料枠はどのくらいですか?超えたらどうしますか?
プライベートリポジトリは月2000分、公開リポジトリは無制限です。超えた場合は追加枠を購入するか、self-hosted runner(セルフホストの実行環境。無料枠に含まれない)を使えます。

5分で読めます · 公開日: 2026年4月10日 · 更新日: 2026年6月8日

関連記事

コメント

GitHubアカウントでログインしてコメントできます