は WordPress などの動的なサイト生成ツールとは異なり、予約投稿機能がありません。
しかし、Netlify と GitHub Actions を使って予約投稿を実現できたので、その方法をご紹介します。
ほとんどはこちらのサイトと同じことをやっているのですが、
マークダウンファイル側や git まわりの準備も含めてお話したいと思います。
GitHub Actions とは
GitHub Actions は、ソフトウェアのビルドやデプロイを自動化する CI(継続的インテグレーション)、CD(継続的デリバリ)のようなサービスです。
GitHub ユーザならプライベートリポジトリでも Free プランから利用でき、
実行時間が毎月2000分(Windows なら1000分、macOS なら200分)までなら無料で利用できます。
ちなみに私の場合はの実行時間がだいたい0.5分なので、
macOS で一日12回実行しても大丈夫そうです。
Netlify でビルド用 URL を取得する
Netlify にアクセスして、Settings > Build & deploy > Build hooks > Add build hook
とします。
Build hook name
のところには任意の名前をつけます。
ここではscheduler
とします。
Branch to build
はmaster
のままで大丈夫です。
Save
を押すと、ビルドを引き起こす URL が得られます。
展開すると下にコマンドが出てくるので、こちらをコピーします。
定期実行の内容を表す yml ファイルを作成する
ローカルので
/.github/workflows/schedule.yml
を作成します(フォルダ名は変更不可、ファイル名は任意)。
これがワークフローを定義するファイルとなります。
/.github/workflows/schedule.yml1# 任意の名前2name: scheduler34# ワークフローを起動する条件5on:6# スケジュールに基づいて起動する7schedule:8- cron: '0 3 2-31/2 * *'910# 実行するジョブ11jobs:12# ジョブ名13build:14# ジョブを実行する環境を指定する15runs-on: ubuntu-latest1617steps:18- name: post build hooks19# コマンドを実行する20run: curl -X POST -d {} ${{ secrets.BUILD_HOOKS_URL }}
on.schedule
は、cron 構文というものを使用して指定した時間になると自動でjobs
を行ってくれます。
ただし時間は UTC(協定世界時)なので、日本の時間から9時間引き算する必要があります。
cron の指定は(分[0-59]) (時[0-23]) (日[1-31]) (月[1-12]) (曜日[0-7])
というふうに行い、
/2
をつけるとステップ値を指定できます。
0 3 2-31/2 * *
は、月や曜日に関係なく、偶数日の日本時間で正午に実行するという意味になります。
run:
の行にはさきほどのコマンドをペーストしたのち、URL 部分を${{ secrets.xxx }}
と書き換えます。
(xxx
の部分は任意の名前。ここではBUILD_HOOKS_URL
。)
これは GitHub の Secrets から呼び出すことができます。
一度 push しておきましょう。
git add .git commit -m "github actions: add workflow, scheduler"git push origin master
GitHub の Secrets を設定する
GitHub のリポジトリにアクセスし、Settings > Secrets > Add a new secret
から値を登録します。
Name
にはさきほどの変数名(xxx
)を入れ、Value
に Build hook の URL を入れます。
Add secret
で登録すると、これで指定した時間に Netlify がビルドしてくれるようになります。
予約投稿したい記事のマークダウンのフロントマターの日付を設定する
Netlify はデプロイをしてくれます。
デプロイは GitHub のリポジトリをもとに行われます。
つまり、あらかじめ公開したい記事を完成させた(draft
もfalse
にした)状態で push しておく必要があります。
そのまま push すると公開されてしまうので、
のdate
の日付を投稿したい日時に合わせます。
こうするとその日時になるまではいくら push しようがデプロイしようが、その日時がまだ存在しないので、
記事が存在しないものとして扱われて表示されません。
例えばある記事を翌日の20時に予約投稿したいなら、フロントマターのdate
の部分をその日時に合わせてから push すれば、
翌日の20時以降にデプロイされたときにはじめて記事が出現するというわけです。
このデプロイの時刻を GitHub Actions で同じ日時に指定してやれば、
翌日の20時05分ぐらいにはうまくいけばちゃんと記事が公開されるはずです。
(たまにデプロイが失敗することもあるようですが…)
記事以外の場合
記事でない場合でも、時間によって操作を変えることができます。
Hugo にはnow
という、地域の時間を返す関数が用意されています。
これを利用して、例えば時間帯によって条件分岐して表示させるものを変えることができます。
1{{- /* 朝(06:00-11:59)のとき */ -}}2{{- if in (seq 6 11) (int (now.Format "15")) -}}3おはよう!4{{- /* 昼(12:00-17:59)のとき */ -}}5{{- else if in (seq 12 17) (int (now.Format "15")) -}}6こんにちは!7{{- /* 夜(18:00-05:59)のとき */ -}}8{{- else -}}9こんばんは!10{{- end -}}
ワークフローのon.schedule
はこんな感じになります。
1// 6:00, 12:00, 18:00 に実行2cron: '0 6-18/6 * * *'
これで夜だけ背景色やデザインを変える、なんてこともできちゃいますよ。
なお、記事の場合で今回のやり方がうまくいかない(未来の日付の投稿が表示されてしまう)場合でも、
.Site.RegularPages
をいじればおそらく実装は可能です。
関係各所の調整がちょっと面倒かもしれないですが。
たぶんこんな感じになるかと思います。
次のコードを必ず通る場所に置きます。
1{{ range .Site.RegularPages }}2{{ if .PublishDate.Before now }}3{{ .Scratch.Add "existing_pages" (slice .) }}4{{ end }}5{{ end }}
これ以外のすべての.Site.RegularPages
を
.Scratch.Get "existing_pages"
に書き換えます。
予約投稿機能がないのは静的サイトジェネレータの弱点のひとつですが、
比較的簡単に、ほとんどの場合無料で実現できてしまいます。
この記事が参考になったら幸いです。
では