前回に引き続き、今回はNotionで書いた記事をGitレポジトリへ自動的に取り込み、Hugoでビルドしてデプロイするまでの流れで躓いた点をまとめる。今回が最終回だ。
Notionの変更からGitHub Actionsをトリガーしたい
まず思いつくのは Notion のデータベース更新からWebhookを受け取り、GitHub Actionsの repository_dispatch
トリガーに連携する方法だが、残念ながら今のNotionにはまだWebhook機能がない。
IFTTTやzapierのようなサービスを使うと(何故か)Notionのデータベース変更イベントからアクションできるが、この程度のために外部サービスを使うのも癪なので、愚直ではあるが GitHub Actions の schedule
トリガーで変更監視を定期実行するようにした。
また、最近のアップデートで workflow_dispatch
トリガーが追加され、GitHubのUI上から手動でワークフローを開始できるのでデバッグ用に追加して次のようなワークフローができた。
name: sync-with-notion
on:
schedule:
- cron: '0/10 * * * *'
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.x'
cache: yarn
- run: yarn install
- run: yarn notion:fetch
env:
NOTION_AUTH_TOKEN: ${{ secrets.NOTION_AUTH_TOKEN }}
DIffが生まれたらプルリクエストを作る
定期実行するワークフローで Notion API からMarkdownファイルを作成した結果、メインブランチと diff が発生したら、その変更を取り込むためのプルリクエストを自動生成する。これによりNotion の内容が(ほぼ)常にGitレポジトリへ一方的に同期される。
GitHub Actions で何らかのdiffを作ってプルリクエストを作るのは、 Create Pull Request
アクションが非常に便利だ。一般的なユースケースをカバーした上でいろいろカスタマイズできる。こうしたワークフローで頻発するベースブランチとのコンフリクトや outdated 化などにも自動的に対応してくれる。
https://github.com/peter-evans/create-pull-request
botが作ったプルリクエストは別のワークフローをトリガーしない
ところが落とし穴がひとつあった。GitHub Actionsで提供される secrets.GITHUB_TOKEN
を認証情報としてGitHub APIを呼び出すと、作成したプルリクエストは別のワークフローをトリガーしないことになっている。
When you use the repository'sGITHUB_TOKEN
to perform tasks, events triggered by theGITHUB_TOKEN
will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs.
プルリクエストが作成されたら Firebase Hosting のプレビューチャンネルへデプロイして表示確認できるようにしていたため、 Notion 記事反映のプルリクエストからプレビューが作られないのは問題である。
この問題を解決する方法も Create Pull Request
の作者はフォローしていて、ドキュメントにいくつかの選択肢を載せてくれている。
結局のところ、デフォルトで提供されている secrets.GITHUB_TOKEN
でさえなければ何でもいいので、今回はトークンのスコープを狭める観点からプライベートの GitHub Apps を使った方法を選んだ。詳細は書かないが、最終的に次のようなワークフローになった。
name: sync-with-notion
on:
schedule:
- cron: '0/10 * * * *'
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.x'
cache: yarn
# https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#authenticating-with-github-app-generated-tokens
- uses: tibdex/github-app-token@v1
id: generate-token
with:
app_id: ${{ secrets.WORKER_APP_ID }}
private_key: ${{ secrets.WORKER_APP_PRIVATE_KEY }}
- run: yarn install
- run: yarn notion:fetch
env:
NOTION_AUTH_TOKEN: ${{ secrets.NOTION_AUTH_TOKEN }}
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
token: ${{ steps.generate-token.outputs.token }}
commit-message: 'fix: apply changes from Notion'
branch: sync-with-notion
delete-branch: true
title: 'fix: apply changes from Notion'
body: '@lacolaco Review and apply changes from Notion'
これで、Notionで記事を書けば約10分後にはGitHubに取り込みプルリクエストが作成され、自動デプロイされたプレビュー環境で表示のチェックができるようになった。完成である。
NotionにWebhookができればもう少しスマートになるが、今のAPIの使い方でもレートリミットなどは問題なさそうなのでしばらくはこのまま運用する。
まとめ
3回に分けて、NotionをこのブログのヘッドレスCMSとして使えるようにするにあたって苦労した点をまとめた。ほぼ自分用の備忘録と、実際にNotionで記事を書けると捗るのかどうかの実験を兼ねたものだが、もし似たようなものを作ろうとする誰かの参考になるなら幸いである。