GitHub Actions とは?使い方と、安全に使うための設定(権限・SHA 固定・secrets)

PR
GitHub Actions とは?使い方と、安全に使うための設定(権限・SHA 固定・secrets)
この記事は約43分で読めます。

GitHub Actions は、GitHub の中で、ビルド・テスト・デプロイ(公開)の流れを自動で動かせる CI/CD の仕組みです。CI/CD は、コードを変えるたびに確かめて、出すところまでを自動にする考え方のことです。リポジトリの .github/workflows に YAML(設定を書くための書式)のファイルを置くと、push や pull request などの出来事をきっかけに、GitHub が用意した仮想マシン(または自分で用意した runner)の上で動き出します。この記事は、GitHub を使い始めた初心者向けに、GitHub Actions の仕組み、最初の workflow(自動の手順)の書き方、動かすきっかけ、そして安全に使うための設定(secrets の扱い、permissions で権限を絞ること、他人の action をコミットの SHA(コミットを指す ID)で固定すること)を、2026年10月10日時点の GitHub Docs(英語版)をもとにまとめたものです。

GitHub そのものや Git の基本がまだ心配なときは、【Github初心者】Gitコマンドのよく使う使い方を基本から学ぶと、手元から GitHub につなぐGitHub の SSH 設定入門を先に読んでおくと、話がつながりやすくなります。変更を取り込む流れはプルリクエストとは?で説明しています。

この記事でわかること
  • GitHub Actions の仕組み(workflow・event・job・step・action・runner の関係)と、最初の workflow の書き方
  • workflow を動かすきっかけ(push・pull_request・schedule・手動)の書き方と注意
  • secrets の作り方と、してはいけないこと
  • permissions で GITHUB_TOKEN の権限を絞る方法(1 つでも書くと、書かなかった権限は全部 none になる)
  • 他人の action を SHA で固定する理由と、固定だけでは足りない点、料金と無料枠(2026年10月10日時点)

公式の日本語版のページには、英語版と語が入れ替わっていたり、手順の番号が崩れていたりする所があります(2026年10月10日時点)。この記事の手順と注意は、英語版にもとづいています。リンクは日本語版のページです。

  1. GitHub Actions とは?何ができる?
    1. workflow・event・job・step・action・runner の関係
  2. 最初の workflow を書くには?
    1. GitHub の画面から作る手順
    2. YAML の主なキー
    3. 動かしたあとの結果の見方
  3. workflow はいつ動く?(push・pull_request・schedule・手動)
    1. push:特定のブランチへの push だけで動かす
    2. pull_request:pull request のたびに確かめる
    3. schedule:決めた時刻に動かす
    4. workflow_dispatch:手動で動かす
    5. 変えたファイルで絞る・動いている途中のものを止める
  4. secrets(秘密の値)はどう扱う?
    1. リポジトリに secret を作る手順
    2. workflow での使い方
    3. 秘密の値を守るためにしておくこと
  5. GITHUB_TOKEN の権限は permissions で絞るべき?
    1. GITHUB_TOKEN とは?
    2. permissions の書き方
    3. 権限はどう決まる? リポジトリの既定の設定
    4. GITHUB_TOKEN で push しても、新しい workflow は動かない
  6. 他人の action は SHA で固定すれば安全?
    1. なぜ他人の action に気をつける?
    2. タグ・SHA・ブランチの違い
    3. 公式の入門はタグ、安全のページは SHA
    4. SHA の調べ方
    5. このブログの CI での固定
    6. 固定すれば安全? 固定だけでは足りない点
    7. 過去にあった例:tj-actions/changed-files
    8. 固定を必須にする設定と、固定した部品の更新
  7. ほかに気をつけることは?(入力・pull_request_target・セルフホステッドランナー)
    1. 信用できない入力を、スクリプトに直接埋めない
    2. pull_request_target は、要らなければ使わない
    3. 公開リポジトリでは、セルフホステッドランナーはほぼ使わない
    4. workflow のファイルの変更にレビューを要る形にする
  8. 料金と無料枠は? runner の種類は?(2026年10月10日時点)
    1. 無料で使えるもの
    2. 非公開リポジトリの無料枠
    3. 無料枠を超えた分の値段
    4. 料金の動き
    5. runner の種類と ubuntu-latest
  9. よくある質問
    1. GitHub Actions は無料で使える? 料金は?
    2. 無料枠はいつリセットされる?
    3. workflow の YAML を置いたのに、Actions に出ない・手動実行のボタンが出ないときは?
    4. secrets が取得できない(空になる)ときは?
    5. cron(schedule)が動かない・遅れる・日本時間で動かしたいときは?
  10. まとめ
  11. 参考資料

GitHub Actions とは?何ができる?

GitHub Actions は、ビルド・テスト・デプロイの流れ(パイプライン)を自動にできる CI/CD の仕組みです。公式の説明では、リポジトリへの pull request のたびにビルドとテストをしたり、マージされた pull request を本番に出したりする workflow を作れます(公式の説明)。

CI/CD のほかにも、リポジトリで何かが起きたときに workflow を動かせます。たとえば、新しい issue が作られたら、合うラベルを自動で付ける workflow も作れます。

workflow を動かす機械は、GitHub が Linux・Windows・macOS の仮想マシンを用意しています。別の OS や特定のハードウェアが要るときは、自分のデータセンターやクラウドに自分の runner(セルフホステッドランナー)を置くこともできます。

workflow・event・job・step・action・runner の関係

公式の一文にまとめると、関係はこうなります。リポジトリで event(pull request が開かれた、issue が作られた、など)が起きると、workflow が動きます。workflow には 1 つ以上の job があり、job は順番にも並行にも動かせます。各 job は、自分専用の仮想マシン(runner)かコンテナの中で動き、1 つ以上の step を持ちます。step は、自分で書いたスクリプトを走らせるか、action(workflow を簡単にする、使い回せる部品)を走らせます。

言葉意味(公式の定義)
workflow1 つ以上の job を動かす、設定できる自動の手順。リポジトリに入れた YAML ファイルで決める。リポジトリの event・手動・決めた予定(スケジュール)で動く
eventworkflow の実行のきっかけになる、リポジトリでの特定の出来事。pull request を作る、issue を開く、コミットを push する、など。予定・REST API への送信・手動でも動かせる
jobworkflow の中の step の集まり。同じ runner の上で動く。step は順番に動き、互いに依存する。同じ runner なので、step から step へデータを渡せる
stepjob の中の 1 つ 1 つの作業。シェルスクリプトか action を走らせる
actionworkflow の中で決まった仕事をする、使い回せる定義済みの部品。GitHub からリポジトリを取ってくる、ビルドに要る道具をそろえる、クラウドへの認証をそろえる、など。自分で書くことも、GitHub Marketplace で探すこともできる
runnerworkflow が動き出したときに、それを動かすサーバー。1 つの runner は一度に 1 つの job だけを動かす。GitHub は Ubuntu Linux・Windows・macOS の runner を用意し、workflow の実行のたびに、新しく用意した仮想マシンで動く

job どうしは、既定では依存せず並行に動きます。ほかの job に依存させると、その job が終わるのを待ってから動きます。

workflow のファイルは、リポジトリの .github/workflows ディレクトリに置きます。1 つのリポジトリに複数の workflow を置けて、それぞれ別の仕事をさせられます。たとえば、pull request のビルドとテスト、リリースのたびのデプロイ、issue を開いたときのラベル付け、です。

最初の workflow を書くには?

workflow のファイルは YAML で書き、拡張子は .yml か .yaml にします。置き場はリポジトリの .github/workflows です。GitHub がリポジトリの workflow を見つけるには、このディレクトリに置く必要があります。ファイル名は好きに付けてかまいません(公式のクイックスタート、workflow の構文)。

GitHub の画面から作る手順

公式のクイックスタートの手順です。ボタンの名前は公式の英語版の表記です。

  1. GitHub でリポジトリのトップページを開き、Add file をクリックして、Create new file をクリックします。
  2. ファイル名に .github/workflows/github-actions-demo.yml と入れます。.github と workflows のディレクトリと、github-actions-demo.yml のファイルが、一度にできます。
  3. 次の YAML を貼ります。
  4. Commit changes をクリックします。"Propose changes" の画面で、既定のブランチにコミットするか、新しいブランチを作って pull request を始めるかを選び、Commit changes か Propose changes をクリックします。workflow のファイルをブランチにコミットすると push の event が起きて、workflow が動きます。

公式のクイックスタートにある workflow は、次のとおりです(2026年10月10日時点で、英語版と日本語版の中身は同じです)。

name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    steps:
      - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
      - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
      - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
      - name: Check out repository code
        uses: actions/checkout@v6
      - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
      - run: echo "🖥️ The workflow is now ready to test your code on the runner."
      - name: List files in the repository
        run: |
          ls ${{ github.workspace }}
      - run: echo "🍏 This job's status is ${{ job.status }}."

${{ <expression> }} は、文字列ではなく式(リテラル・コンテキストの参照・関数の組み合わせ)として評価するよう、GitHub に伝える書き方です(公式の説明)。この例の github.actor や github.event_name は、github のコンテキスト(workflow の実行と、そのきっかけの event の情報)から読んでいます(公式のリファレンス)。github のコンテキストには github.token のような秘密の情報も入っているので、丸ごと書き出すときは気をつけます。

注意: この例の actions/checkout@v6 は、版を タグ(v6)で指定しています。公式の文書は、場所によって書き方が違います。入門の例はタグで書いてあり、workflow の構文のページは「リリースした版のコミット SHA がいちばん安全」、安全のページは「第三者の action は SHA(コミットを指す ID)で固定」と書いています。くわしくは、あとの「他人の action は SHA で固定すれば安全?」の章で並べます。

YAML の主なキー

上の例と、このあとの例に出てくるキーを、公式の説明に沿って並べます(workflow の構文)。

キー意味
nameworkflow の名前。リポジトリの Actions タブに出る。書かなければ、リポジトリの根からのファイルの道筋が出る
onどの event で workflow を動かすかを決める。on: push は、そのリポジトリのどのブランチへの push でも動く
jobsworkflow の実行は 1 つ以上の job からなり、既定では並行に動く。順番に動かすには needs で依存を書く
<job_id>job の名札。英字か _ で始め、英数字・-・_ だけで書く
needs書いた job が成功してから動く。依存先が失敗するかスキップされると、それを needs にした job もスキップされる(条件の式で続けさせない限り)
runs-onjob を動かす機械の種類。GitHub ホステッドランナー、大きいランナー、セルフホステッドランナーのどれか
stepsjob の中の作業の並び。コマンドを走らせる、準備をする、action を走らせる。step はそれぞれ別のプロセスなので、step の中で変えた環境変数は次の step に残らない
runOS のシェルでコマンドを走らせる(21,000 字まで)。name を書かなければ、step の名前は run の中身になる。複数行を書くと、同じシェルで順に走る
usesstep で走らせる action を選ぶ。ほかのリポジトリの action は {owner}/{repo}@{ref} の形で書く(ref はブランチ・タグ・SHA)
withaction に渡す入力。要る入力は action の README で確かめる
timeout-minutesjob をこの分数で自動で止める。既定は 360(6 時間)

動かしたあとの結果の見方

公式のクイックスタートでは、次の順に開くと、各 step の記録(ログ)が見えます。

  1. リポジトリ名の下の Actions をクリックします。
  2. 左の一覧で、見たい workflow の名前をクリックします。
  3. 実行の一覧から、見たい実行の名前をクリックします。
  4. 実行のページの左で、Jobs の下にある job の名前(この例では Explore-GitHub-Actions)をクリックします。
  5. 各 step を開くと、中身が見えます。

リポジトリ名の下に Actions のタブが出ないときは、そのリポジトリで Actions が無効になっているのかもしれません(公式のクイックスタート)。

動かしたときのログの見た目は、この記事には載せません。ご自分の画面で確かめてください。

workflow はいつ動く?(push・pull_request・schedule・手動)

workflow を自動で動かすには、on に、どの event で動かすかを書きます(公式の説明)。よく使う 4 つを並べます。

event動くとき気をつけること
pushコミットやタグを push したとき既定のブランチにマージされていない workflow も含む
pull_request種類(types)を書かなければ、pull request が開かれたとき、開き直されたとき、head のブランチが更新されたときマージの衝突(コンフリクト)があると動かない
schedule決めた時刻混んでいると遅れる。既定のブランチにあるファイルだけが動く
workflow_dispatch手動画面の Run workflow ボタンは、workflow のファイルが既定のブランチにあるときに出る

push:特定のブランチへの push だけで動かす

push は、コミットやタグを push したときに動きます。既定のブランチにマージされていない workflow も含みます(公式の説明)。

特定のブランチへの push だけで動かすには、branches を書きます。公式の例では、main、mona/octocat、releases/** に当たるブランチへの push で動きます。

on:
  push:
    branches:
      - main
      - 'mona/octocat'
      - 'releases/**'

除きたいブランチの名前の形だけがあるときは、branches-ignore を使います。同じ event に branches と branches-ignore を両方は書けません(workflow の構文)。

pull_request:pull request のたびに確かめる

pull_request は、種類(types)を書かなければ、pull request が開かれたとき、開き直されたとき、pull request の head のブランチが更新されたときに動きます。pull request にマージの衝突(コンフリクト)があると、pull_request の workflow は動きません。先に衝突を直します(公式の説明)。

pull_request で動くとき、既定では「マージしたらどうなるか」の結果(merge branch)を検査します。actions/checkout が既定でそれを取ってくるからで、CI のテストは head のブランチだけでなく、マージした結果に対して動きます。

schedule:決めた時刻に動かす

schedule は、決めた時刻に workflow を動かします。書き方は POSIX の cron で、空白で区切った 5 つの欄(分・時・日・月・曜日)です。既定は UTC(協定世界時)で、timezone に IANA のタイムゾーン名を書くこともできます。いちばん短い間隔は 5 分に 1 回です(公式の説明)。

公式の注意(NOTE)は、次のとおりです。

  • GitHub Actions の実行が混んでいると、schedule は遅れることがあります。混みやすいのは毎時 0 分ごろです。混みすぎると、待っている job が捨てられることもあります。遅れにくくするには、時刻を毎時 0 分からずらします。
  • schedule は、workflow のファイルが既定のブランチにあるときだけ動き、既定のブランチの上でだけ動きます。
  • 公開リポジトリでは、60 日間リポジトリに動きがないと、schedule の workflow は自動で無効になります。

workflow_dispatch:手動で動かす

手動で動かしたいときは、on に workflow_dispatch を書きます。

on: workflow_dispatch

画面の Run workflow ボタンは、workflow のファイルが既定のブランチにあるときに出ます。一度動いたあとは、API や GitHub CLI から、どのブランチやタグに向けても動かせます(公式の説明)。

画面での手順は、次のとおりです。リポジトリへの書き込みの権限が要ります。

  1. リポジトリの Actions をクリックします。
  2. 左で workflow の名前をクリックします。
  3. 実行の一覧の上の Run workflow をクリックします。
  4. Branch のメニューで、動かすブランチを選びます。
  5. 入力があれば埋めて、Run workflow をクリックします。

変えたファイルで絞る・動いている途中のものを止める

paths-ignore には、変えたファイルが 全部 当たるときだけ動かない、という決まりがあります。1 つでも当たらないファイルがあれば、動きます。paths と paths-ignore は、同じ event に両方は書けません(workflow の構文)。

concurrency は、同じ group の job や workflow を一度に 1 つだけ動かします。cancel-in-progress: true を書くと、動いている途中のものを止めて、新しいほうを動かします。

このブログのサイトチェックの workflow(site-check.yml)は、push のたびにチェックして、合格したら Cloudflare Pages に公開します。docs/** などの文書だけの変更では動かさず(paths-ignore)、手動でも動かせます(workflow_dispatch)。一部を略して載せます。

# Pushのたびにチェックして、合格したら Cloudflare Pages に公開する
on:
  push:
    paths-ignore:
      - "docs/**"
      - "**/*.md"
      - ".claude/**"
      - "workers/**"
  workflow_dispatch:

同じブランチに新しい push が来たら、途中の実行を止めて最新だけを動かす書き方は、次のとおりです。

concurrency:
  group: site-check-${{ github.event_name }}-${{ github.ref }}
  cancel-in-progress: true

secrets(秘密の値)はどう扱う?

secrets は、パスワードやトークンなどの秘密の情報を、organization・リポジトリ・リポジトリの環境(environment)に預けておくための変数です。workflow の中で使います。GitHub Actions が secret を読むのは、workflow に はっきり書いたとき だけです(公式の説明)。

secret は、GitHub に届く前に暗号化されます(Libsodium の sealed box)。届いたあと、workflow の実行に渡すために、GitHub が復号します(公式の説明)。

リポジトリに secret を作る手順

画面での手順です(公式の手順。日本語版は手順の番号が崩れているので、英語版をもとに書いています)。

  1. リポジトリ名の下の Settings をクリックします。Settings のタブが見えないときは、…(More)のメニューから Settings をクリックします。
  2. 左の "Security" の Secrets and variables を選び、Actions をクリックします。
  3. Secrets のタブをクリックします。
  4. New repository secret をクリックします。
  5. Name の欄に、secret の名前を入れます。
  6. Secret の欄に、値を入れます。
  7. Add secret をクリックします。

作るのに要る権限は、organization のリポジトリなら write、個人のアカウントのリポジトリならコラボレーターであることです。

GitHub CLI(gh コマンド)でも作れます。値は、コマンドを流したあとに聞かれます。ファイルから読むときは、2 行目の形です。一覧は gh secret list で見られます。

gh secret set SECRET_NAME
gh secret set SECRET_NAME < secret.txt

名前の決まりは、次のとおりです(公式の説明)。

  • 英数字と _ だけ。空白は使えません。
  • GITHUB_ で始めません。
  • 数字で始めません。
  • 参照するときは、大文字小文字を区別しません(GitHub は大文字で保存します)。

数の上限は、リポジトリの secret が 100 個、organization が 1,000 個、environment が 100 個までです。1 つの secret は 48 KB までです(公式の説明)。

workflow での使い方

workflow では、secrets のコンテキストを使って ${{ secrets.名前 }} と書き、action の入力(with)か環境変数(env)として渡します(公式の手順)。

このブログのサイトチェックの workflow は、Cloudflare Pages に公開する job で、API トークンを secret(secrets.CLOUDFLARE_API_TOKEN)、アカウント ID を変数(vars.CLOUDFLARE_ACCOUNT_ID)で渡しています。この job は needs で、2 つのチェックの job が通ってから動きます。一部を略して載せます。

  deploy:
    needs: [html-and-seo, internal-links]
    if: vars.CLOUDFLARE_ACCOUNT_ID != ''
    runs-on: ubuntu-latest
    # (略)
    steps:
      # (略)
      - name: 公開
        uses: cloudflare/wrangler-action@953926a2e2182532811c01a25e53647d93bf07c0 # v4.1.3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}

秘密でない設定(ユーザー名やサーバー名など)は、変数(variables)に置けます。変数は、既定でログに 伏せ字にならずに 出ます。パスワードのように秘密にしたいものは、secrets に置きます(公式の説明)。

公式が書いている、secrets の使い方の注意は、次のとおりです。

  • 作っていない secret を参照すると、エラーにならず、空の文字列になります。「secret が取れない」ように見えるときは、まず、その名前で作ってあるかを確かめます。
  • secret は if: の条件に直接は書けません。 job の環境変数に入れてから、その環境変数で条件を書きます。
  • フォークから動いた workflow には、GITHUB_TOKEN 以外の secret は渡りません。 Dependabot(依存しているライブラリなどの更新や脆弱性を知らせてくれる、GitHub の仕組み)の event で動いた workflow も、secret を使えません。
  • secret をコマンドラインの引数で渡すのは、できるだけ避けます。 ps(動いているプロセスを見るコマンド)などで、ほかの人に見えることがあるからです。環境変数や標準入力を使います。どうしても引数で渡すなら、環境変数を "$SUPER_SECRET" のように引用符で囲みます。

秘密の値を守るためにしておくこと

ログに出た secret は、自動で伏せ字になります。ただし、値を変換する道がいくつもあるので、伏せ字は保証されません。runner が伏せられるのは、その job で使った secret だけです(公式の説明)。

公式の「安全に使うためのリファレンス」には、secrets の勧めが並んでいます(公式のページ)。このページの今の名前は "Secure use reference"(日本語版は「セキュリティで保護された使用に関するリファレンス」)で、以前は "Security hardening for GitHub Actions" という名前でした。古い URL はここへ転送されます。この記事では「安全に使うためのリファレンス」と呼びます。

やること中身
書き込みの権限を持つ人を意識するリポジトリへの書き込みの権限を持つ人は、そのリポジトリの secret を 全部読めます。だから、workflow で使う資格情報は、要る最小の権限にします
平文で書かない秘密の値を workflow のファイルに平文で書きません。GitHub の secret でない秘密の値は、::add-mask::VALUE で伏せ字にします
漏れたら取り替える伏せ字にならないまま secret がログに出たら、ログを消し、その secret を取り替えます(rotate)
塊にしないJSON・XML・YAML などの塊を 1 つの secret にしません。伏せ字は値の完全一致に頼るので、失敗しやすくなります。値ごとに別の secret を作ります
作った値も登録するsecret から別の秘密の値を作ったら(たとえば、秘密鍵で署名した JWT というトークン)、それも secret として登録します。Base64 や URL エンコードで形を変えた値も同じです
見直して取り替える登録した secret を定期的に見直し、要らないものは消し、定期的に取り替えます
承認を挟むenvironment の secret には、必須のレビュー担当者を付けられます。承認されるまで、job はその secret を使えません

資格情報を作るときは、権限を最小にします。読むだけで足りるなら、読むだけにします。また、personal access token(パスワードの代わりに使う文字列)より、細かい権限と短い寿命のトークンを使う GitHub App を考えるよう、公式は書いています(公式の説明)。

GITHUB_TOKEN の権限は permissions で絞るべき?

絞るのが、公式の勧めです。GITHUB_TOKEN は、workflow の中で GitHub に認証するための、自動で作られるトークンです。公式の「安全に使うためのリファレンス」は、GITHUB_TOKEN の既定の権限をリポジトリの中身(contents)を読むだけにして、要る job でだけ権限を足すのがよい、と書いています(公式のページ)。

GITHUB_TOKEN とは?

各 job の始めに、GitHub が自動で、その job 専用の GITHUB_TOKEN という secret を作ります。workflow の中で GitHub に認証するのに使えます。中身は GitHub App のインストールのアクセストークンで、権限は workflow のあるリポジトリに限られます(公式の説明)。

トークンは、job が終わるか、上限の時間で切れます。GitHub ホステッドランナーでは job の上限が 6 時間なので、トークンも最長 6 時間です。

書き方は、secret と同じです。${{ secrets.GITHUB_TOKEN }} と書きます。同じトークンは、github.token のコンテキストからも使えます(公式の手順)。名前が似ていますが、GITHUB_TOKEN がトークン(secret)の名前で、github.token は、そのトークンを読める場所の名前です。

公式の IMPORTANT には、次の注意があります。workflow が action に GITHUB_TOKEN を渡していなくても、action は github.token から GITHUB_TOKEN を使えます。 そのため公式は、安全のための心がけとして、GITHUB_TOKEN に与える権限を絞って、action に要る最小の権限だけを持たせるよう書いています。

permissions の書き方

permissions で、GITHUB_TOKEN に与える権限を変えます。workflow の一番上に書くと全部の job に、job の中に書くとその job にだけ効きます(workflow の構文)。

権限ごとに、read・write・none のどれかを選びます。write は read を含みます。ここで大事なのは、次の決まりです。

permissions で権限を 1 つでも書くと、書かなかった権限は全部 none になります。

たとえば contents: read だけを書くと、書いていない issues や pull-requests などは none です。「contents: read を足すだけで、ほかはそのまま」にはなりません。

権限の名前の例を、公式の表から挙げます。表には、2026年10月10日時点で 16 行あります。ここに載せたのは、その一部です。

権限できること(公式の表の例)
contentsリポジトリの中身を扱う。contents: read でコミットの一覧を見られ、contents: write でリリースを作れる
issuesissues: write で issue にコメントを付けられる
pull-requestspull-requests: write で pull request にラベルを付けられる
actionsactions: write で workflow の実行を取り消せる
id-tokenOpenID Connect(OIDC)のトークンを取る。id-token: write が要る。write か none だけ

全部まとめての書き方もあります。permissions: read-all、permissions: write-all、全部なしにするなら permissions: {} です。

公式の例は、issue を作る job に、contents: read と issues: write だけを与えます。job の下に書きます(公式の例)。

jobs:
  create-issue:    # job の名前は例です
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write

このブログのサイトチェックの workflow は、一番上に permissions: contents: read を書いています。GitHub への書き込みは何もしないので、中身を読むだけにしています。一番上に書いたので、全部の job に効きます。書いていない権限は none です。

# GitHub への書き込みは何もしない(読むだけ)。使う部品はコミットの SHA で固定する(タグは後から付け替えられる)。
permissions:
  contents: read

権限はどう決まる? リポジトリの既定の設定

GITHUB_TOKEN の権限は、まず enterprise・organization・リポジトリの既定の設定で決まります。次に、workflow の一番上の permissions、job の permissions の順に上書きされます。最後に、フォークからの pull request の event(pull_request_target 以外)で、"Send write tokens to workflows from pull requests" の設定が選ばれていなければ、書き込みの権限は読むだけに落とされます(workflow の構文)。

リポジトリの既定の権限は、2 つから選びます。全部の権限に読み書きを与える設定(permissive、ゆるい設定)か、contents と packages だけ読むだけにする設定(restricted、きつい設定)です。場所は、リポジトリの Settings → 左の Actions → General → "Workflow permissions" です(公式の説明)。

個人のアカウントで新しく作るリポジトリは、既定で contents と packages を読むだけです。organization で新しく作るリポジトリは、organization の設定を受け継ぎます。

既定を読むだけにしたのは、2023年2月2日の GitHub の変更履歴からです。それまでは、Actions を有効にすると、既定で読み書きでした。この変更は、それより前からある enterprise・organization・リポジトリには効きません(GitHub の変更履歴)。古いリポジトリは、読み書きのままのことがあります。

だから、リポジトリの既定に頼らず、workflow のファイルに permissions を書いておくと、既定がどちらでも、同じ権限になります。上で見た決まり方(既定を workflow の permissions が上書きする)から言えることです。

GITHUB_TOKEN で push しても、新しい workflow は動かない

リポジトリの GITHUB_TOKEN で作業をしたときに起きた event は、新しい workflow の実行を作りません。workflow が workflow を呼び続けるのを防ぐためです。たとえば、workflow が GITHUB_TOKEN でコードを push しても、push で動く別の workflow は動きません。

例外は、workflow_dispatch と repository_dispatch です。また、GITHUB_TOKEN で作った・更新した pull request の pull_request(opened・synchronize・reopened)は、「承認待ち」(approval-required)の状態で実行が作られます(公式の説明)。

GITHUB_TOKEN に無い権限が要るときは、GitHub App を作って、workflow の中でトークンを作ります。または、personal access token を secret に入れて、${{ secrets.SECRET_NAME }} で使います(公式の説明)。

他人の action は SHA で固定すれば安全?

「固定すれば安全」とは言い切れません。公式は、action を完全な長さのコミット SHA に固定することを、action を「変わらないリリース」として使う 唯一の方法 と呼び、悪意のある人が裏口を足す危険を減らせる、と書いています。ただし、固定すると大事なバグの修正やセキュリティの更新も自動では入らず、Dependabot の脆弱性の通知も出なくなります。この章では、固定の仕方と、固定だけでは足りない点を説明します。

なぜ他人の action に気をつける?

公式の「安全に使うためのリファレンス」は、こう説明しています。workflow の中の 1 つの action が乗っ取られると、その action は、リポジトリに設定した secret を全部 使えます。GITHUB_TOKEN でリポジトリに書き込めるかもしれません。だから、GitHub 上の第三者のリポジトリから action を持ってくるのには、大きな危険があります(公式のページ)。

タグ・SHA・ブランチの違い

uses で action の版を指定する方法は、タグ・SHA・ブランチなどがあります。公式の説明を表にします(公式のページ)。

指定の仕方書き方の例公式の説明
タグactions/checkout@v6、actions/[email protected]大きな版・小さな版を切り替える時期を自分で決められる。ただし、保守する人が動かしたり消したりできる
SHAactions/checkout@<40 文字のコミット SHA>変わらないので、タグやブランチより確か。ただし、大事なバグの修正やセキュリティの更新も自動では入らない。短くせず、完全な値を書く
ブランチactions/checkout@mainそのブランチの今の版がいつも動く。壊れる変更が入ると困る

「完全な長さ」の SHA は、40 文字の 16 進数です(Git の文書では「完全な SHA-1 のオブジェクト名」。Git の文書)。

公式の入門はタグ、安全のページは SHA

ここに、公式の中の食い違いがあります。公式の文書は、場所によって勧めが違います(2026年10月10日時点)。

公式のページ書いてあること
クイックスタート例は actions/checkout@v6(タグ)
workflow の構文(uses)版を書くよう強く勧める。書かないと、作者の更新で workflow が壊れたり、思わない動きをしたりする。リリースした版の コミット SHA が、安定と安全のためにいちばんよい
安全に使うためのリファレンスSHA に固定するのが、変わらないリリースとして使う唯一の方法。タグで指定するなら、作った人を信頼できるときだけ
action の探し方とカスタマイズ第三者の action には SHA を使うよう勧める。ただし、Dependabot が脆弱性の通知を出すのは、セマンティックバージョン(v1.2.3 の形)を使っている action だけ

入門の例はタグで書いてあります。第三者の action を使う workflow では、安全のページの勧め(SHA)も合わせて考えます。

SHA の調べ方

action の版(タグ)が指すコミットの SHA は、git ls-remote で調べられます。次は、2026年10月10日に、actions/checkout の v7.0.1 のタグを調べた結果です(macOS・git 2.39.3)。

git ls-remote https://github.com/actions/checkout refs/tags/v7.0.1 refs/tags/v7.0.1^{}
3d3c42e5aac5ba805825da76410c181273ba90b1	refs/tags/v7.0.1

この SHA を uses に書き、同じ行のコメントに版のタグを残します。

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

調べるときの注意は、2 つです。

  • SHA を選ぶときは、フォークではなく、action のリポジトリのものか確かめます。 記憶や、ほかのサイトに載っていた SHA を、そのまま写さないでください。
  • タグは動かせます。 上の SHA は、2026年10月10日の値です。公式の入門の例の actions/checkout@v6 も、同じ日は d23441a48e516b6c34aea4fa41551a30e30af803 を指していました。actions/checkout の最新のリリースは、同じ日の時点で v7.0.1(2026年7月20日)でした。版は動くので、使うときは、自分で最新の版と SHA を確かめてください。

タグには、タグそのものの ID と、タグが指すコミットの ID が別に出るもの(注釈つきのタグ)があります。次は cloudflare/wrangler-action の v4.1.3 の例で、^{} が付いた行が、タグの指すコミットです。固定するのは、コミットのほうです。

git ls-remote https://github.com/cloudflare/wrangler-action refs/tags/v4.1.3 refs/tags/v4.1.3^{}
2ef9f398b9175c68f953e40d679493850d640a85	refs/tags/v4.1.3
953926a2e2182532811c01a25e53647d93bf07c0	refs/tags/v4.1.3^{}

このブログの CI での固定

このブログのサイトチェックの workflow(site-check.yml)は、使う部品(action)6 か所すべてを、40 文字のコミット SHA で書き、同じ行のコメントに版のタグを書いています(2026年10月10日時点)。次は、そのファイルから、別々の step の uses の行だけを抜き出したものです(このままでは動きません)。

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
- uses: cloudflare/wrangler-action@953926a2e2182532811c01a25e53647d93bf07c0 # v4.1.3

この workflow に permissions と SHA での固定を入れたのは、2026年10月10日です。それまでは actions/checkout@v4 のようなタグで、permissions は書いていませんでした。さらに、scripts/check_site.py が .github/workflows/*.yml を読み、permissions: が無いとき、または uses: が @ と 40 桁の 16 進で終わらないときに、チェックが落ちるようにしています。

固定すれば安全? 固定だけでは足りない点

公式が書いていることを並べると、固定には役目と限りがあります。

  • 役目: SHA で固定すると、悪意のある人が action のリポジトリに裏口を足すには SHA-1 の衝突(別の中身から、同じ SHA を作り出すこと)を作る必要があり、危険を減らせます。タグは、action を置いたリポジトリに悪意のある人が入ると、動かしたり消したりできます。信頼できる作者のタグでも、この危険は残ります。
  • 限り①: 固定すると、大事なバグの修正やセキュリティの更新が、自動では入りません。
  • 限り②: Dependabot の脆弱性の通知(alerts)は、セマンティックバージョンを使っている action にだけ出ます。SHA で固定した action には出ません(公式のページ)。
  • 足りない点: action のソースを読んで、リポジトリの中身や secret を思ったとおりに扱っているか確かめます。たとえば、意図しない宛先に secret を送っていないか、ログに出していないかです。GitHub Marketplace の "Verified creator" のバッジは、GitHub が身元を確かめたチームが書いた action だという目印になります。

更新を追う助けとして、Dependabot の 版の更新(version updates)があります。公式の手順では、リポジトリの .github に dependabot.yml を置き、package-ecosystem に "github-actions"、directory に "/"、schedule.interval を書きます(3 つとも必須)。そうすると、古い action を見つけたときに、版を上げる pull request を出します(公式の手順)。公式の例は次のとおりです(コメント行は略しました)。

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

この版の更新は、actions/checkout@<commit> の形にも対応していて、同じ行のコメント(actions/checkout@<commit> #<tag or link>)の版の書き込みも直す、と公式は書いています(公式のページ)。コミットがどのタグにも付いていないと、最新のリリースではなく、最新のコミットに上げます。

過去にあった例:tj-actions/changed-files

タグが付け替えられた例が、GitHub のアドバイザリ(GHSA-mrrh-fwg8-r2c3、CVE-2025-30066)に載っています。アドバイザリによると、tj-actions/changed-files で、いくつもの版のタグが、あとから悪いコミットを指すように書き換えられました。 CI/CD の secret が、workflow のログに出ました。期間は 2025年3月14日から15日で、v46.0.1 で直っています(GitHub のアドバイザリ)。

タグは動かせる、という公式の説明と合う例です。使っている部品を経由した攻撃(サプライチェーン攻撃)への備えは、npm・yarn・pnpm の違いでも、npm のパッケージについて書いています。

固定を必須にする設定と、固定した部品の更新

リポジトリや organization の設定で、"Require actions to be pinned to a full-length commit SHA" をオンにすると、完全なコミット SHA での固定を 必須 にできます。オンにすると、organization の action も GitHub が作った action も、SHA で固定しないと使えません。再利用できる workflow(reusable workflow)は、タグのままでかまいません(公式の説明)。この設定は 2025年8月15日の GitHub の変更履歴で入りました。固定していない action を使う workflow は失敗します。同じ回に、! を頭に付けて特定の action や版を止める(ブロックする)設定も入りました(GitHub の変更履歴)。

固定した部品は、自分で版を上げないと古いままです。たとえば、Node 20(JavaScript を動かす実行環境 Node.js の版の 1 つ)は 2026年9月23日に GitHub Actions の runner から外れ、JavaScript で書かれた action は Node 24 で動きます。JavaScript の action を使うなら、Node 24 に対応した最新の版に上げるよう、公式は書いています(GitHub の変更履歴)。

このブログのサイトチェックの workflow も、固定していた checkout・setup-python・wrangler-action の版が Node 20 向けで、実行のたびに "Node.js 20 is deprecated" の警告が出ていました。2026年10月10日に、Node 24 向けの版(checkout v7.0.1・setup-python v7.0.0・wrangler-action v4.1.3。どれも同じ日の最新のリリース)へ上げたあとの実行では、この警告は 0 件でした。

ほかに気をつけることは?(入力・pull_request_target・セルフホステッドランナー)

公式の「安全に使うためのリファレンス」には、ここまでのほかにも注意があります(公式のページ)。

信用できない入力を、スクリプトに直接埋めない

信用できない入力、たとえば pull request のタイトル(${{ github.event.pull_request.title }})を、run: のスクリプトに直接埋めてはいけません。公式の勧めは、いったん環境変数(env:)に入れてから使うことです。こうすると、式の値はメモリの中に変数として入り、スクリプトを作る処理とは交わりません(公式のページ)。公式の例は、次のとおりです(job の steps の中の 1 つの step です)。

      - name: Check PR title
        env:
          TITLE: ${{ github.event.pull_request.title }}
        run: |
          if [[ "$TITLE" =~ ^octocat ]]; then
          echo "PR title starts with 'octocat'"
          exit 0
          else
          echo "PR title did not start with 'octocat'"
          exit 1
          fi

pull_request_target は、要らなければ使わない

pull_request_target と workflow_run の event は、信用できない pull request のコードを checkout(取ってくること)すると、リポジトリが乗っ取られる道になりえます。公式は、必要がなければ pull_request_target を使わないよう書いています。pull_request_target で動くと、公開のフォークからでも、GITHUB_TOKEN に読み書きの権限が付きます(workflow の構文)。

公開リポジトリでは、セルフホステッドランナーはほぼ使わない

GitHub ホステッドランナーは、使い捨てのきれいな仮想マシンの中で動きます。セルフホステッドランナーには、その保証がありません。workflow の中の信用できないコードに、ずっと乗っ取られたままになることもあります。だから公式は、セルフホステッドランナーは、GitHub の公開リポジトリでは ほぼ使わない よう書いています。誰でも pull request を開いて、環境を乗っ取れるからです(公式のページ)。

workflow のファイルの変更にレビューを要る形にする

CODEOWNERS(ファイルごとの担当者を決めるファイル)に .github/workflows を入れると、workflow のファイルの変更に、決めたレビュー担当者の承認が要るようにできます(公式のページ)。

料金と無料枠は? runner の種類は?(2026年10月10日時点)

料金や無料枠、runner の版は、動きます。この章の数字は、2026年10月10日に開いた公式のページの値で、米ドルのままです。使うときは、公式の最新のページを見てください(課金のページ)。

無料で使えるもの

次は無料です。

  • 公開(public)リポジトリ で、標準の GitHub ホステッドランナーを使うとき
  • セルフホステッドランナー を使うとき

標準の GitHub ホステッドランナーの利用は、公開リポジトリのほか、GitHub Pages と Dependabot でも無料です。ただし、大きいランナー(larger runners)は、公開リポジトリでも、プランの無料枠が残っていても、いつも有料です。

非公開リポジトリの無料枠

非公開(private)リポジトリ では、アカウントのプランごとに、無料の分数・成果物(artifact。workflow が作ったファイルの保存)の容量・キャッシュの容量が付きます。超えた分は、アカウントに請求されます。分は、リポジトリの持ち主に付きます(workflow を動かした人ではありません)。公式の表の値は、次のとおりです。

プラン1 か月の無料の分成果物の保存キャッシュ(リポジトリごと)
GitHub Free2,000 分500 MB10 GB
GitHub Pro3,000 分1 GB10 GB
GitHub Free for organizations2,000 分500 MB10 GB
GitHub Team3,000 分2 GB10 GB
GitHub Enterprise Cloud50,000 分50 GB10 GB

成果物の容量は、GitHub Packages と共有です。この表の分数は、非公開リポジトリの話です。公開リポジトリの標準のランナーは無料なので、「月 2,000 分しか使えない」とは限りません。

無料枠を使い切ったときの動きは、支払い方法を登録しているかで変わります。登録していないアカウントは、無料枠を使い切ると、そこで止まります。登録していれば、予算(budget)で上限を決められます。無料枠の 90% と 100% に届いたときに、メールの通知を受けることもできます。リポジトリへの書き込みの権限がある人は誰でも action を動かせて、その費用はリポジトリの持ち主に請求されます。

無料枠を超えた分の値段

無料枠を超えた分の、1 分あたりの値段(標準のランナー)は、次のとおりです(ランナーの値段のページ)。

runner1 分あたり(米ドル)
Linux 1 コア$0.002
Linux 2 コア(x64)$0.006
Linux 2 コア(arm64)$0.005
Windows 2 コア(x64・arm64)$0.010
macOS 3 コアか 4 コア(M1 か Intel)$0.062

分は、job ごとに 1 分単位に切り上げます。公式の使い方の例では、Linux で 10 分かかる workflow は、持ち主の枠を 10 分使います。5 分で失敗して、直して流し直し、成功したときは、合わせて 15 分です。

料金の動き

  • 2026年1月1日に、GitHub ホステッドランナーの値段が最大 39% 下がりました(機械の種類によります)。無料の分数は変わりません。公開リポジトリの標準のランナーは、無料のままです(GitHub の変更履歴)。
  • 2025年12月16日に、「2026年3月1日からセルフホステッドランナーに 1 分 $0.002 をかける」と発表されましたが、その後、延期して考え直す、と書き足されました。2026年10月10日時点の公式の課金のページは、セルフホステッドランナーを無料と書いています(GitHub の変更履歴)。
  • 2026年6月1日から、Copilot のコードレビューも、非公開リポジトリでは Actions の分を使います。公開リポジトリは無料のままです(GitHub の変更履歴)。

runner の種類と ubuntu-latest

標準の GitHub ホステッドランナーは、runs-on に書くラベルで選びます。公式の表から、ラベルの例と大きさを並べます(GitHub ホステッドランナーのページ)。

OSラベルの例公開リポジトリ非公開リポジトリ
Linuxubuntu-latest、ubuntu-24.04、ubuntu-22.04、ubuntu-26.044 CPU・メモリ 16 GB・SSD 14 GB2 CPU・メモリ 8 GB・SSD 14 GB
Windowswindows-latest、windows-2025、windows-20224 CPU・メモリ 16 GB・SSD 14 GB2 CPU・メモリ 8 GB・SSD 14 GB
macOSmacos-latest、macos-14、macos-15、macos-26M1・3 CPU・メモリ 7 GB・SSD 14 GB公開と同じ

-latest のラベルは、GitHub が出す最新の 安定した イメージで、OS の最新版とは限りません。

2026年10月10日時点で、ubuntu-latest は Ubuntu 24.04 です。GitHub の告知によると、2026年10月19日から数週間かけて Ubuntu 26.04 に移し、11月19日までに終える予定です(runner-images の告知)。ubuntu-latest のままにしていると、この日付のあと、使われる Ubuntu の版が変わります。

よくある質問

GitHub Actions は無料で使える? 料金は?

公開リポジトリで標準の GitHub ホステッドランナーを使うときと、セルフホステッドランナーを使うときは、無料です。非公開リポジトリは、アカウントのプランごとに無料の分数があり、超えた分が請求されます。たとえば GitHub Free は 1 か月 2,000 分、GitHub Pro と GitHub Team は 3,000 分です(2026年10月10日時点)。くわしくは「料金と無料枠は? runner の種類は?」の章にまとめています。

無料枠はいつリセットされる?

公式の課金のページには、言い方が 2 つあります。前半に「無料の分は、請求の周期(billing cycle)の始めに全部に戻る」という文があり、表の前に「毎月の始めに、アカウントで使った分がゼロに戻る」という文があります(2026年10月10日時点)。この記事では「請求の周期の始め」と書きます。自分のアカウントの周期は、請求の情報で確かめてください。

workflow の YAML を置いたのに、Actions に出ない・手動実行のボタンが出ないときは?

次を順に確かめます。

  1. 置き場と拡張子。 workflow のファイルは、リポジトリの .github/workflows に置き、拡張子を .yml か .yaml にします。
  2. 手動実行のボタン。 手動で動かすには、on に workflow_dispatch を書きます。Run workflow のボタンは、workflow のファイルが既定のブランチにあるときに出ます。
  3. Actions のタブ。 リポジトリ名の下に Actions のタブが出ないときは、そのリポジトリで Actions が無効になっているのかもしれません。

secrets が取得できない(空になる)ときは?

作っていない secret を参照すると、エラーにならず、空の文字列になります。また、フォークから動いた workflow には GITHUB_TOKEN 以外の secret が渡らず、Dependabot の event で動いた workflow も secret を使えません。secret は if: の条件に直接は書けないので、job の環境変数に入れてから、その環境変数で条件を書きます。

cron(schedule)が動かない・遅れる・日本時間で動かしたいときは?

schedule は、混んでいると遅れることがあります。毎時 0 分ごろが混むので、時刻をずらすと遅れにくくなります。また、workflow のファイルが既定のブランチにあるときだけ動きます。公開リポジトリで 60 日間動きがないと、自動で無効になります。時刻は、既定では UTC(協定世界時)です。timezone に IANA のタイムゾーン名を書くこともできます(公式の例は America/New_York)。

まとめ

  • GitHub Actions は、ビルド・テスト・デプロイの流れを自動にできる CI/CD の仕組みです。リポジトリの .github/workflows に YAML の workflow を置くと、event(push・pull request・予定・手動など)をきっかけに、runner の上で job の step が動きます。
  • 最初の workflow は、公式のクイックスタートに沿って、GitHub の画面から作れます。結果は、リポジトリの Actions から開いて、各 step のログで見ます。
  • secrets は、workflow に書いたときだけ読まれます。リポジトリへの書き込みの権限を持つ人は、そのリポジトリの secret を全部読めます。平文で書かず、漏れたら取り替えます。
  • GITHUB_TOKEN の権限は、permissions で絞ります。1 つでも書くと、書かなかった権限は全部 none になります。workflow のファイルに書いておけば、リポジトリの既定がどちらでも同じ権限になります。
  • 他人の action は、公式の安全のページの勧めでは、完全な長さのコミット SHA で固定します(公式の入門の例はタグです)。固定しても、修正は自動では入らず、Dependabot の脆弱性の通知も出ません。ソースを読む、版を上げる、の手間は残ります。
  • 料金は、公開リポジトリの標準のランナーとセルフホステッドランナーが無料で、非公開リポジトリはプランごとの無料枠を超えた分が請求されます(2026年10月10日時点)。ubuntu-latest は、2026年10月19日から Ubuntu 26.04 へ移る予定です。

参考資料

公式の日本語版のページには、英語版と語が入れ替わった箇所や、手順の番号が崩れた箇所があります(2026年10月10日時点)。この記事の手順と注意は、英語版にもとづいています。リンクは日本語版のページです。

GitHub Docs:しくみと最初の workflow

GitHub Docs:secrets・GITHUB_TOKEN・安全に使う

GitHub Docs:料金と runner

GitHub のブログ・変更履歴・アドバイザリ・告知

Git

※この記事は、公式の資料をもとに AI(Claude)で下書きし、2026年10月10日時点の公式の資料と照らして確かめてから公開しています。誤りに気づいたらお問い合わせからお知らせください。

PR
PR
タイトルとURLをコピーしました