GitHub Actions

GitHub Actions &
GitHub Pages 完全ガイド

静的サイトからフレームワークビルドまで、実用的なYAMLテンプレートと設定解説を網羅したリファレンスです。

14 パターン · トラブルシューティング付き · コピペ対応
01

基本概念と全体像

GitHub Actions を使った Pages デプロイは「ビルド」と「デプロイ」の2段階で構成されます。まずこの流れを理解しておくと、あらゆるフレームワークに応用できます。

ワークフローの流れ

  1. トリガー(push / tag / PR など)でワークフロー開始
  2. Checkout でリポジトリを Runner に取得
  3. Setup(Node / Hugo / Python など環境構築)
  4. Build で静的ファイルを生成
  5. Upload artifact で成果物を一時保存
  6. Deploy で GitHub Pages に公開

必須 permissions

以下の3行はほぼすべての Pages ワークフローに必要です。

permissions:
  contents: read
  pages: write
  id-token: write
  • contents: read — リポジトリ読み取り
  • pages: write — Pages への書き込み
  • id-token: write — OIDC トークン発行(deploy-pages で必須)

主要アクション一覧

アクション役割備考
actions/checkout@v4リポジトリをチェックアウトほぼ必須
actions/configure-pages@v5Pages のベースURL等を設定ビルド前に実行
actions/upload-pages-artifact@v3成果物を一時アップロードpath に出力ディレクトリを指定
actions/deploy-pages@v4Pages にデプロイneeds で build に依存
actions/setup-node@v4Node.js 環境構築cache 指定で高速化
actions/jekyll-build-pages@v1Jekyll ビルドGitHub公式
peaceiris/actions-hugo@v3Hugo セットアップコミュニティ製
02

基本ワークフロー(静的ファイルそのまま)

ビルド不要な HTML/CSS/JS ファイルをそのままデプロイする場合。リポジトリルートがドキュメントルートになります。

推奨
name: Deploy to GitHub Pages

on:
  push:
    branches: ["main"]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Pages
        uses: actions/configure-pages@v5

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: '.'

      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
ポイント:path: '.' はリポジトリルート全体をアップロードします。path には index.html が存在するディレクトリを必ず指定してください。
03

Node.js ビルド & デプロイ

npm プロジェクトの汎用テンプレートです。Vite / React / Vue / 純粋なビルドツールなどに対応します。

汎用テンプレート
name: Build and Deploy

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

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

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Setup Pages
        uses: actions/configure-pages@v5

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: './dist'

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

各フレームワークの出力ディレクトリ

フレームワークpath備考
Vite./distデフォルト
Create React App./build
Vue CLI./dist
Next.js(static)./outnext.config で output: 'export' 必須
Astro./dist
Nuxt(static)./.output/public
SvelteKit(static)./buildadapter-static 必須
Docusaurus./build
Gatsby./public
Remix(static)./build/client
04

Next.js(Static Export)

Next.js を GitHub Pages で動かすには「Static Export」が必要です。SSR は Pages で直接動作しません。

next.config.js 設定

まず next.config.js を以下のように設定します。

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',
  distDir: 'dist',
  images: {
    unoptimized: true,   // Pagesでは必須
  },
}
module.exports = nextConfig
ワークフロー
name: Deploy Next.js

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - run: npm ci
      - run: npm run build

      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
制約:API Routes(app/apipages/api)は Static Export では生成されません。サーバー機能が必要な場合は Vercel や Cloudflare Pages を検討してください。
05

Astro

Astro はデフォルトで静的出力なので、設定が比較的シンプルです。

astro.config.mjs
import { defineConfig } from 'astro/config'

export default defineConfig({
  site: 'https://username.github.io',
  base: '/repo-name',   // プロジェクトサイトの場合のみ
})
ワークフロー
name: Deploy Astro

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
06

Vite(vanilla / React / Vue / Preact)

vite.config.js

プロジェクトサイト(username.github.io/repo-name)の場合、base の設定が必須です。

import { defineConfig } from 'vite'

export default defineConfig({
  base: '/repo-name/',   // 末尾スラッシュ必須
})
ユーザーサイト(username.github.io)の場合は base: '/' または省略可能です。
ワークフロー
name: Deploy Vite

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
07

Jekyll

公式アクション使用
name: Deploy Jekyll site to Pages

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Pages
        uses: actions/configure-pages@v5

      - name: Build Jekyll
        uses: actions/jekyll-build-pages@v1
        with:
          source: ./
          destination: ./_site

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
注意:GitHub Pages で使える Jekyll プラグインは許可リスト制です。カスタムプラグインを使う場合はローカルでビルドしてから _site ディレクトリをデプロイする方法を使ってください。
08

Hugo

Extended 版対応
name: Deploy Hugo

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true   # テーマがサブモジュールの場合必須
          fetch-depth: 0         # .GitInfo / Lastmod 用

      - uses: actions/setup-go@v5
        with:
          go-version: '1.22'

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'
          extended: true

      - name: Build
        run: hugo --minify

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: './public'

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
fetch-depth: 0 を忘れると .GitInfo やページの更新日時が正しく出力されません。テーマが Go Modules を使う場合は actions/setup-go も必要です。
09

Nuxt(Static)

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false,               // または prerender 設定
  nitro: {
    output: {
      publicDir: '.output/public'
    }
  }
})
ワークフロー
name: Deploy Nuxt

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npx nuxt generate   # 静的生成
      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./.output/public

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
10

SvelteKit(adapter-static)

svelte.config.js
import adapter from '@sveltejs/adapter-static'

export default {
  kit: {
    adapter: adapter({
      pages: 'build',
      assets: 'build',
      fallback: undefined   // SPA の場合は 'index.html'
    })
  }
}
ワークフロー
name: Deploy SvelteKit

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./build

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
11

Docusaurus

docusaurus.config.js
const config = {
  url: 'https://username.github.io',
  baseUrl: '/repo-name/',
  organizationName: 'username',
  projectName: 'repo-name',
  deploymentBranch: 'gh-pages',   // 手動デプロイ時用(Actionsでは不要)
  trailingSlash: false,
}

module.exports = config
ワークフロー
name: Deploy Docusaurus

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./build

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
12

MkDocs(Python)

ワークフロー
name: Deploy MkDocs

on:
  push:
    branches: ["main"]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
          cache: pip

      - name: Install dependencies
        run: |
          pip install mkdocs mkdocs-material

      - name: Build
        run: mkdocs build

      - uses: actions/upload-pages-artifact@v3
        with:
          path: ./site

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/deploy-pages@v4
        id: deployment
mkdocs.ymlsite_dir を変更していない場合、デフォルトの ./site が出力先です

13

応用テクニック

タグデプロイ

リリース時のみデプロイ

on:
  push:
    tags:
      - 'v*'

バージョンタグを push したときだけ本番デプロイしmain への push ではステージングに出す、という運用に使えます。

手動実行

workflow_dispatch

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment'
        required: true
        default: 'production'
        type: choice
        options:
          - production
          - staging
環境変数 & Secrets

ビルド時に API キーや環境変数を渡す

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      VITE_API_URL: ${{ vars.API_URL }}
      VITE_API_KEY: ${{ secrets.API_KEY }}
    steps:
      - run: npm run build
  • vars — リポジトリ設定 > Variables で管理(非機密)
  • secrets — リポジトリ設定 > Secrets で管理(機密)
  • Vite の場合は VITE_ プレフィックスが必要です
  • Next.js の場合は NEXT_PUBLIC_ プレフィックスが必要です
カスタムドメイン

CNAME の扱い

方法1:ビルド後に生成

- run: npm run build
- run: echo 'www.example.com' > ./dist/CNAME
- uses: actions/upload-pages-artifact@v3
  with:
    path: ./dist

方法2:リポジトリに CNAME ファイルを置いてコピー

# public/CNAME または src/CNAME を
# ビルド時に dist/ へコピーする設定を各フレームワークで行う
GitHub Pages の Settings でカスタムドメインを設定しても、Actions デプロイのたびに上書きされることがあります。CNAME ファイルを成果物に含めるのが確実です。
キャッシュ戦略

ビルド高速化

Node.js(npm)

- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: npm

Hugo

- uses: actions/cache@v4
  with:
    path: ~/go/pkg/mod
    key: ${{ runner.os }}-go
concurrency

同時実行制御

concurrency:
  group: "pages"
  cancel-in-progress: true
  • group: "pages" — Pages デプロイジョブを1つに制限
  • cancel-in-progress: true — 新しい push が来たら古いビルドをキャンセル(節約)
  • cancel-in-progress: false — 古いビルドは最後まで実行(安全)
条件付きデプロイ

特定条件でのみ実行

jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    # または
    if: startsWith(github.ref, 'refs/tags/v')
    # または
    if: github.event_name == 'workflow_dispatch'
404 ページ

SPA / カスタム 404 の設定

GitHub Pages は 404.html を自動的にエラーページとして使います。SPA の場合は 404.htmlindex.html と同じ内容にするか、各フレームワークの推奨方法に従てください。

  • Vite SPA: dist/404.htmlindex.html のコピーにする
  • Vue Router(history mode): public/404.html にフォールバック用 HTML を配置
  • Next.js Static Export: not-found.tsx が自動で 404.html を生成
14

トラブルシューティング

Error: Ensure GITHUB_TOKEN

deploy-pages で失敗

permissionsid-token: writepages: write が不足しています。リポジトリ設定で「Read and write permissions」が有効になっているか確認してください。

404 after deploy

デプロイ後に 404

  • pathindex.html のあるディレクトリを指定しているか
  • プロジェクトサイトで base / baseUrl の設定を忘れていないか
  • Pages の Source が GitHub Actions に設定されているか
Assets 404

CSS/JS/画像が 404

プロジェクトサイト(/repo-name/)の場合、絶対パス(/assets/...)ではなく相対パス(./assets/...)または base 設定を使う必要があります。Vite / Astro / Next.js などの base 設定を確認してください。

Build succeeds, deploy fails

ビルド成功、デプロイ失敗

  • deploy ジョブに needs: build があるか
  • artifact の path が存在しないディレクトリを指していないか
  • 同時実行制限に引っかかっていないか(数分待って再実行)
Next.js images

Next.js Image コンポーネントが崩れる

Static Export では next/image の最適化サーバーが動作しません。images.unoptimized: truenext.config.js に追加してください。

Hugo themes

Hugo テーマが読み込めない

  • actions/checkout@v4submodules: true を設定
  • Git Submodule ではなく Go Modules を使っている場合は actions/setup-go を追加

よくあるディレクトリ構造

my-project/ ├── .github/ │ └── workflows/ │ └── pages.yml # ワークフロー定義 ├── src/ または app/ など # ソースコード ├── public/ # 静的アセット ├── package.json ├── vite.config.js など # ビルド設定 └── README.md