Webhook / GitHub Actions でビルドを起動
SSGで作ったサイトは、コンテンツを更新しただけでは公開ページに反映されません。ShareDan CMSの外部連携を使うと、投稿やFAQの更新をきっかけにCIを起動し、ビルド・デプロイまでを自動化できます。このガイドでは、GitHub Actionsでの再ビルドと、汎用Webhookを自前のエンドポイントで受ける方法の両方を扱います。
1. 外部連携を有効にする
管理画面の「サイト設定 › 外部連携」で、サイト単位に次の3種類の連携先を設定できます。配信はキューで非同期に実行され、失敗時はリトライし、配信ログに最終ステータスが記録されます。
- Webhook:設定した
webhook_urlへイベントのJSONをPOSTします。任意の受け口(自前のAPIサーバーやサーバーレス関数)で受けられます。 - GitHub Actions:保存したリポジトリ・ワークフロー・ブランチに対して
workflow_dispatchを実行します。 - Slack:Incoming Webhookでチャンネルに通知します。
2. 通知されるイベント
Webhook / GitHub Actions で選べる、再ビルド向けのイベントは次の11種類です(実際に選べる範囲は、サイトの「利用するコンテンツ」設定でさらに絞り込まれます)。
3. GitHub Actions を起動する
ビルド・デプロイを行うワークフローに on: workflow_dispatch: を必ず追加してください。これがないとCMS側からは起動できません。
name: Deploy
on:
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm run build
- run: npm run deploy
対象イベントが発生すると、CMSは保存済みのトークンを使って、GitHubの workflow dispatch API を
{ "ref": "<branch>" } を添えて呼び出します。
POST /repos/{owner}/{repo}/actions/workflows/{workflow}/dispatches HTTP/1.1
Host: api.github.com
Authorization: Bearer <保存済みトークン>
Content-Type: application/json
{"ref":"main"} github_auto_dispatch)がOFFになっていると、対象イベントが発生しても自動では起動しません。自動再ビルドを期待する場合はONにしてください。
4. 汎用Webhook と署名検証
汎用Webhookでは、次の形のJSONが webhook_url へPOSTされます。eventは発生したイベント名、triggerは発火経路(コンテンツ更新などによる自動発火は auto、画面からの手動実行・テスト送信は
manual)です。resourceはイベントに紐づくリソースがない場合は null になります。
{
"event": "post.published",
"trigger": "auto",
"site": {
"code": "demo-cms",
"name": "デモサイト",
"url": "https://demo.example.com"
},
"resource": {
"type": "post",
"id": 42
},
"occurred_at": "2026-09-08T09:30:00+09:00"
}
シークレットを設定している場合、リクエストには X-ShareDan-Signature ヘッダーが付与されます。値は sha256= に続けて、生ボディを webhook_secret鍵でHMAC-SHA256した16進文字列です。受信側では、JSONへパースする前の生ボディで同じ計算をし、定数時間比較で検証してください。
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post(
'/webhooks/sharedan',
express.raw({ type: 'application/json' }), // 生ボディをBufferで受け取る(JSONパース前)
(req, res) => {
const signature = req.header('X-ShareDan-Signature') ?? '';
const expected =
'sha256=' +
crypto.createHmac('sha256', process.env.CMS_WEBHOOK_SECRET!).update(req.body).digest('hex');
const ok =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok) {
return res.status(401).send('invalid signature');
}
const payload = JSON.parse(req.body.toString('utf8')) as { event: string };
// payload.event を見て CI を起動するなどの処理
res.status(204).end();
},
);
app.listen(3000); このページはお役に立ちましたか?
改善要望・不具合・ドキュメントの分かりにくい点など、お気軽にお寄せください。いただいた内容は今後の改善に役立てます。
お寄せいただきありがとうございます。今後の改善に役立てます。