skip to content
notes.kinokonoko.io

Contentful の Webhook を GitHub Action をトリガーして、記事更新したらブログのリビルドを走らせる

/ 7 min read

Table of Contents

このブログは Astro で作成されたフロントエンドに合わせて、記事コンテンツは Contentful というヘッドレス CMS で管理しています。 ソースコードの管理やデプロイには、GitHub と GitHub Actions を使用しています。 Contentful を利用して静的サイトを構築することで、柔軟かつスケーラブルなコンテンツ管理を実現しながら、高速な静的サイトを構築できます。 ただし、コンテンツはビルド時に取得されるため、コンテンツを更新する際にはサイトの再ビルドが必要です。

Contentful には、コンテンツ更新時に Webhook を呼び出す機能があり、これを GitHub Actions の repository_dispatch 機能と組み合わせることで、自動的にリビルドを行うことが可能です!

GitHub Action を更新する

GitHub Actions を Webhook 経由で実行するには、対象のワークフローに repository_dispatch トリガーを設定する必要があります。 このブログのデプロイ用 GitHub Actions ワークフローのトリガー設定は以下の通りです:

name: Deploy to GitHub Pages
on:
push:
branches:
- main
workflow_dispatch:
repository_dispatch:
types: [contentful_publish]

設定されたトリガーは、次の 3 つです:

  • main ブランチへのプッシュ時
  • マニュアル実行(workflow_dispatch)
    • 特定のワークフローに対して手動実行できます
  • Webhook による実行 (repository_dispatch)
    • レポジトリ全体に対してイベントを発行することで、対象のワークフローが実行されます

repository_dispatch では、特定の types を指定することができます。Webhook を呼び出す際に event_type を指定すれば、ワークフローを特定のイベントにだけ反応させることが可能です。 なお、types を設定しない場合、そのワークフローはすべての repository_dispatch イベント(event_type を含むまたは省略されたもの)に反応します。

GitHub の Personal Access Token を用意する

Webhook を使って GitHub Actions を実行するには、認証用のトークンが必要です。 このトークンには、GitHub アカウントで発行した Personal Access Token(PAT) を使用します。 以下の手順で、細分化されたスコープを持つ Fine-grained Personal Access Token を作成します。

GitHub のメニューから GitHub > Settings > Developer Settings > Personal access token にアクセスし、 Generate new token をクリックして新しい Tokens (fine-grained) を作成します。

次の内容を設定します:

  • リポジトリのアクセス権限
    • 対象リポジトリを選択(すべてのリポジトリを選ぶことも可能ですが、必要なリポジトリのみに限定する方が安全です)
  • Repository permissions から
    • Actions: Read and Write
    • Metadata: Read-only
    • Workflows: Read and Write
    • Content: Read and Write

Fine-grained Personal Access Token とは、その名の通り「アクセス権限を細かく制限できるトークン」であり、セキュリティを高めたい場合に推奨されます。 トークンを作成したら、その場で必ずコピーしてメモしておきましょう。セキュリティ上の理由から、トークンは一度しか表示されません!

Contentful の Webhook を設定する

まず、Contentful の スペース設定(Settings) から Webhooks にアクセスします。(右上のユーザーアイコンの横にある「歯車マーク」から入ります)

新規 Webhook を作成して、下記の設定を行います:

  • Name: わかりやすい名前をつけてください
  • URL:
  • Content Events:
    • Webhook を発火させるコンテンツイベントを選択します
    • 一般的には以下のイベントで問題ありません
      • Publish, Unpublish, Archive, Unarchive, Create, Save
    • 公開済みコンテンツは「Unpublish」してからでないと「Delete」できないため、Delete ではサイトのリビルドは不要と考えてよいです
  • Headers:
    • (Add Custom Header)カスタムヘッダーを追加
      • Accept
        • application/vnd.github.everest-preview+json
      • User-Agent
        • contentful-webhook (任意の識別名)
    • (Add secret header)シークレットヘッダーを追加
      • Authorization
        • token PAT
        • *token のあとにスペースを入れ、前述の PAT を設定します
  • Payload
    • Customize the webhook payload を選択
    • {“event_type”: “contentful_publish”} のように event_type を指定
      • event_type の値(例:contentful_publish)は、GitHub Actions 側の repository_dispatch に設定した types と一致している必要があります

Webhook を保存した後、同じ設定画面の「Activity Log」 タブからその中に発火履歴とリクエスト/レスポンス内容を確認できます。

これで設定が完了です!Contentful のコンテンツを更新して、Webhook が正しく動作し、GitHub Actions が実行されるか確認してみましょう。

なんで workflow_dispatch を使わないの?

実は、GitHub Actions のワークフローは workflow_dispatch を使って手動で実行できるだけでなく、 外部から API を通じて呼び出すことも可能です。

以下のエンドポイントに POST すればワークフローを発火できます:

https://api.github.com/repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches

workflow_dispatch を外部サービスから使うには、以下のような制約や注意点があります:

  • ワークフロー ID やファイル名の指定が必要
    • workflow_dispatch は 特定のワークフローファイルを直接指定しないと動作しません
    • 呼び出し側(Contentful)に設定するときに知っておく必要があります
    • また、ワークフロー ID が変わるたびにその設定を更新する必要があります
  • トリガーは柔軟性に欠ける
    • event_type を渡すことができず、トリガー条件の振り分けができません
    • マルチイベント対応には不向きです

どちらの方法も GitHub API 経由でトークン付きの認証が必要です。そのため、両方とも実装可能ですが、 Contentful のような外部サービスから使うには、シンプルで拡張性の高い repository_dispatch がより適しているというのが結論です。