💨

Cloudflare PagesをGitHub Actionsでデプロイするようにしてみた

2024/11/02に公開

TL;DR

  • GitHubから詳しいデプロイ状況見られるようにするため、GitHub Actionsでのデプロイに切り替えてみたよ
  • Cloudflare PagesへのデプロイはGitHub Actionsからでもできるよ
  • トークンの取得など事前作業がちょっとだけ必要だよ
  • Cloudflare Pagesで設定するのか、GitHub Actionsを使うのかは好きに決めてね
  • 正直ここまで頑張らなくてもいいと思ったよ

経緯

ホームページをCloudflare Pagesでホスティングしています。

Cloudflare PagesにGitHubリポジトリを連携して自動デプロイ設定をしていますが、
詳細なデプロイ状況を確認するのにCloudflareに毎度ログインする必要があるので、それが煩雑に感じてしまいました。
(ざっくりとしたデプロイ状況はGitHubからでも確認できるのですがね…。)
また、GitHub Actionsの学習も兼ねてデプロイ方法をCloudflare Pagesの自動デプロイからGitHub Actionsに変更してみることにしました。

実際にやってみた

Cloudflare APIトークンを取得する

CloudflareにログインしてAPIトークンを取得します。
「マイ プロフィール」→「API トークン」と進んでいくと、「トークンを作成する」ボタンからユーザーAPIトークンを取得できます。
images
いろいろテンプレートが用意されていますが、テンプレートを使用しないでカスタムトークンを作成します。
images
自分が識別できる名前をつけて、アクセス許可にCloudflare Pagesの編集を設定しました。
Cloudflare Pagesへのデプロイに必要なため、編集権限を付与しています。
images
※なお、キャプチャしたあとにアカウントリソースをしれっと更新しました…。
「トークンを作成する」ボタンで晴れてAPIトークンを作成できます👏
images

トークンが発行されると、トークンをテストするcurlコマンドが画面に表示されるので、ターミナルから実行しておきましょう。

curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
     -H "Authorization: Bearer 作成されたAPIトークン" \
     -H "Content-Type:application/json"
コマンド実行結果の例
% curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
    -H "Authorization: Bearer 作成されたAPIトークン" \
    -H "Content-Type:application/json"
{"result":{"id":"xxxxxxxxxxxxxxxxxx","status":"active"},"success":true,"errors":[],"messages":[{"code":10000,"message":"This API Token is valid and active","type":null}]}

また、GitHubリポジトリのシークレットに忘れず登録しておきましょう。

Cloudflare PagesのアカウントIDを確認する

これはCloudflare Pagesの管理画面に行っていただければすぐに見つかります。
これもGitHubリポジトリのシークレットに登録しておきましょう。

GitHub Actionsを作成する

いよいよ本題。ホームページはAstroで構築していますがSSGとしているので、不定期ながらもちょくちょくビルドが走ります。

ホームページのデプロイは大きく分けて2通りです。(まあ、2環境あるので当然と言えば当然なのですが…。)

  • 開発デプロイ
  • 本番デプロイ

ソースコードが変更され、特定のブランチにプッシュがあったときにビルドが走りデプロイされるわけです。


デプロイソースコード修正以外にももう一つトリガーがあります。それはヘッドレスCMSで記事が作成されたとき。
Webhookでのデプロイにも対応させなければなりませんので、作成するGitHub Actionsは全部で4つとなります。

  • ソースコード修正による開発デプロイ
  • ヘッドレスCMSに更新があったことによる開発デプロイ
  • ソースコード修正による本番デプロイ
  • ヘッドレスCMSに更新があったことによる本番デプロイ

ソースコード修正による開発デプロイ

まずは開発側から作成していくのがセオリー。
とりあえず.github/workflows/deploy-dev.yamlとして作成していきます。

ワークフローのベーシックな設定

前段としては以下のとおりです。任意の名前をつけて、トリガーとジョブの実行環境を定義しています。

.github/workflows/deploy-dev.yaml (抜粋)
name: 開発環境へのデプロイ

on:
  push:
    branches:
      - develop # `develop`ブランチにプッシュされたのをトリガーとする

jobs:
  deploy-dev:
    runs-on: ubuntu-latest

    steps:
    # この先はこのあと実装していきます

このあと実施しなければいけないのは、

  • リポジトリのチェックアウト
  • ホームページのビルド
  • ホームページのデプロイ

くらいでしょうか。

リポジトリをチェックアウトする

リポジトリのチェックアウトはactions/checkoutを使っておくのが無難でしょう。

.github/workflows/deploy-dev.yaml (抜粋)
jobs:
  deploy-dev:
    runs-on: ubuntu-latest

    steps:
      - name: コードのチェックアウト
        uses: actions/checkout@v4

ホームページをビルドする

ここからホームページをビルドするわけですが、Node.jsのセットアップをしておきましょう。
この場合には、actions/setup-nodeを利用します。

.github/workflows/deploy-dev.yaml (抜粋)
jobs:
  deploy-dev:
    runs-on: ubuntu-latest

    steps:
      - name: コードのチェックアウト
        uses: actions/checkout@v4

      - name: Node.jsのセットアップ
        uses: actions/setup-node@v4
        with:
          node-version-file: .node-version # ファイルはプロジェクトルート直下に配置してください。

バージョンが変わらないということであれば、ハードコーディングでもいいかもしれませんが、
今回はnode-version-fileを指定することで、Node.jsのバージョン指定を外部ファイルで定義してハードコーディングを回避します。
Cloudflare Pagesの自動デプロイでも.node-versionファイルが使えるので、
ビルド時にNode.jsを任意のバージョンで固定したいという場合は作成しておくといいのかもしれませんね。

.node-versionの内容 (Node.jsのバージョンが書いてあるだけですが)
.node-version
22.11.0

お次はパッケージマネージャーのコマンドを走らせるだけなのでさらりと流しておきます。

.github/workflows/deploy-dev.yaml (抜粋)
jobs:
  # 中略
    steps:
      # 中略
      - name: ライブラリのインストール
        run: npm ci

      - name: ビルド
        run: npm run build

npm installではなくてnpm ciを利用します。
詳細は下の記事をご覧ください。

CI/CDで使うからciなのかと思ったのですが、Clean Installの略みたいですね。

ホームページをデプロイする

ビルドができたのでいよいよデプロイします。
デプロイにはcloudflare/wrangler-actionを用います。

.github/workflows/deploy-dev.yaml (抜粋)
jobs:
  # 中略
    steps:
      # 中略
      - name: ライブラリのインストール
        run: npm ci

      - name: ビルド
        run: npm run build

      - name: デプロイ
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          accountId: ${{ secrets.CF_ACCOUNT_ID }}
          command: pages deploy dist --project-name=my-homepage

ビルド後のファイルがdistディレクトリに出来上がるので、このようなコマンドとなります。
なんとこれだけでプロダクションとプレビューを自動で判別してくれるみたいです。すごい…!!
(デフォルトブランチであればプロダクション、そうでなければプレビューと判定するのだそう。)

全体像は以下のとおりです。

開発環境へのデプロイワークフローの全体像
.github/workflows/deploy-dev.yaml
name: 開発環境へのデプロイ

on:
  push:
    branches:
      - develop # `develop`ブランチにプッシュされたとき

env:
  TZ: Asia/Tokyo
  NODE_ENV: development
  CONTENTFUL_SPACE_ID: ${{ secrets.CONTENTFUL_SPACE_ID }}
  CONTENTFUL_TOKEN: ${{ secrets.CONTENTFUL_TOKEN_DEV }}

jobs:
  deploy-dev:
    runs-on: ubuntu-latest

    steps:
      - name: コードのチェックアウト
        uses: actions/checkout@v4

      - name: Node.jsのセットアップ
        uses: actions/setup-node@v4
        with:
          node-version-file: .node-version

      - name: ライブラリのインストール
        run: npm ci

      - name: ビルド
        run: npm run build

      - name: デプロイ
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          accountId: ${{ secrets.CF_ACCOUNT_ID }}
          command: pages deploy dist --project-name=my-homepage

GitHub Actionsによるビルド、デプロイに成功すると、Cloudflare Pagesのビルドログは以下のようになります。
images

ヘッドレスCMSに更新があったことによる開発デプロイ

もう一山超えていきましょう。
今度はヘッドレスCMSに更新があったことによる開発デプロイワークフローを作成していきます。
ただこのワークフローでやることはこれまでとほぼ変わらないのでjobsの設定はこれまでと同様でOKで、
このワークフローをどうトリガーするのかが問題です。

ワークフロートリガーの設定

これはrepository_dispatchで解決できます。

.github/workflows/preview-blog-entry.yaml (抜粋)
name: ブログ記事のプレビューデプロイ

on:
  repository_dispatch:
    types: [preview-blog]

jobs:
  deploy-dev:
    runs-on: ubuntu-latest

    steps:
    # この先はこのあと実装していきます

typesに任意の文字列を指定しましょう。

以下のようにGitHubリポジトリのAPIエンドポイントをたたくことで、ワークフローを起動できます。
なお、typesに指定した任意の文字列は、リクエストボディのevent_typeに指定しておきます。

curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer <YOUR-TOKEN>" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  -H "User-Agent: my-app" \
  https://api.github.com/repos/OWNER/REPO/dispatches \
  -d '{"event_type":"preview-blog"}'

Authorizationヘッダーに指定するトークンはあらかじめGitHubで取得しておきましょう。

取得したトークンは再表示されないので、このときにヘッドレスCMS側でWebhookの設定をしておくことをおすすめします。

ブランチに関係しないトリガーにおけるチェックアウト設定

さてトリガー自体は問題なく設定できましたので、jobsの実装をします。
これまでとほぼ同じで問題ないですが、開発デプロイではデフォルトブランチではないブランチをチェックアウトしたいので、
チェックアウトするブランチ名を明記しておきます。

.github/workflows/preview-blog-entry.yaml (抜粋)
jobs:
  deploy-dev:
    runs-on: ubuntu-latest

    steps:
      - name: コードのチェックアウト
        uses: actions/checkout@v4
        with:
          ref: develop # developブランチを明示

あとはこれまでとまったく同じでOKです。
全体像は以下のとおりです。

開発環境へのデプロイワークフローの全体像
.github/workflows/preview-blog-entry.yaml
name: ブログ記事のプレビューデプロイ

on:
  repository_dispatch:
    types: [preview-blog]

env:
  TZ: Asia/Tokyo
  NODE_ENV: development
  CONTENTFUL_SPACE_ID: ${{ secrets.CONTENTFUL_SPACE_ID }}
  CONTENTFUL_TOKEN: ${{ secrets.CONTENTFUL_TOKEN_DEV }}

jobs:
  deploy-dev:
    runs-on: ubuntu-latest

    steps:
      - name: コードのチェックアウト
        uses: actions/checkout@v4
        with:
          ref: develop # `develop`ブランチをチェックアウト

      - name: Node.jsのセットアップ
        uses: actions/setup-node@v4
        with:
          node-version-file: .node-version

      - name: ライブラリのインストール
        run: npm ci

      - name: ビルド
        run: npm run build

      - name: デプロイ
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          accountId: ${{ secrets.CF_ACCOUNT_ID }}
          command: pages deploy dist --project-name=my-homepage

本番ビルド

これまでの開発用変数を本番用に切り替えてしまうだけなので、特に書くことはありません🙇

おわりに

この備忘録を書きながら失敗しつつここまで来ました。公式ドキュメントや他の方の記事にとても助けられました。
またGitHub Actionsへの理解がほんの少しではありますが深まったように思います。
それぞれ状況は違うと思いますが、正直なところここまで頑張らなくてもいいのかなという本末転倒な結論でこの備忘録を締めたいと思います。

ありがとうございました。

(💭ブログ記事の見てくれを直すのが先決だったかもしれない…。)

参考にさせていただいたページ

以下のページを参考にさせていただきました。この場を借りて御礼申し上げます。

Discussion