📆

GitHub ActionsでZenn記事の予約投稿を実現する

3 min read

「Zenn で記事の予約投稿が出来ると便利だなー」と思って調べてたら GitHub Actions を使って実現できたので紹介します。

仕組み

予約投稿の仕組みは記事追加のプルリクエストの日時指定のマージです。
その実現のためにMerge Scheduleという GitHub Action を利用します。

https://github.com/marketplace/actions/merge-schedule

動きとしては以下の通りです。

  1. ブランチを切り、公開したい記事を追加。プルリクエストを作成
  2. GitHub Actions が起動し、Merge Schedule が登録
  3. 日時指定でプルリクエストがマージされて master が更新
  4. Zenn で記事が公開

詳細

GitHub Actions の登録

Zenn の記事管理リポジトリに移動して GitHub Actions のディレクトリを作ります。

$ mkdir -p .github/workflows

次に workflows に以下merge-schedule.ymlを作成します。

name: Merge Schedule
on:
  pull_request:
    types:
      - opened
      - edited
      - synchronize
  schedule:
    - cron: 0 * * * *

jobs:
  merge_schedule:
    runs-on: ubuntu-latest
    steps:
      - uses: gr2m/merge-schedule-action@1ef6893192811edbec08113370a9d973922e84c7
        with:
          time_zone: "Asia/Tokyo"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

そして変更をコミット & プッシュします。
これでスケジュール投稿の準備が整いました。

上記コードではgr2m/merge-schedule-actioのバージョンをコミット指定にしています。このコミットは私が gr2m/merge-schedule-actio に送った Time Zone 対応の PR がマージされたときのコミットです。2020/11/23 時点で、このコミットが最新のリリースに取り込まれていないので、このような指定としています。
(この変更がないと UTC 標準時での時刻指定が必要になります)。
https://github.com/gr2m/merge-schedule-action/pull/29

プルリクエストの作成

ローカルでプルリクエスト作成用のブランチを切ります。

$ git checkout -b introduce-xvim2

このブランチ上で記事を作成します。記事ファイルの公開指定はpublished: trueとしてください。
作成が完了したらコミットしてプルリクエストを作成します。

$ git add introduce-xvim2.md
$ git commmit -m "feat: introduce-xvim2"
$ git push --set-upstream origin introduce-xvim2

そして、プルリクエスト 作成の際の Descriptions に以下のように ISO 形式で公開したい日時を入力してください。これがマージ実行日時(記事公開日時)となります。

/schedule 2020-11-21T20:00

この状態でプルリクエストをオープンし、起動されている GitHub Actions をみてみます。ワークフローが起動していますね。

詳細をみると先ほど指定した公開日時でスケジュールされているのがわかります。

あとは、その指定時間がくるとプルリクエストがマージされ記事が投稿されます。
便利!

注意点

merge-schedule の GitHub Actions がどのように動いているのかを確認したら、以下のようになっていました。

https://github.com/gr2m/merge-schedule-action/blob/master/lib/handle_schedule.js

注目するのは以下処理です。

const duePullRequests = pullRequests.filter(
  (pullRequest) => new Date(pullRequest.scheduledDate) < localeDate()
);

どうやら、cron での GitHub Actions 実行時点で、description 記載の実行日時を経過しているプルリクエストを抽出してマージ実行対象とするようです。

なので、厳密に Descriptions に記載した日時にマージされるのではなく、cron での CI 実行時間により左右されます。

もし分単位の公開指定をしたい場合は、GitHub Actions の cron の指定を変える必要があります。
サンプルの例だとcron: 0 * * * *で、1 時間に 1 回しか実行されません。
例え/schedule 2020-11-21T20:45と、20 時 45 分に実行を指定しても、それは2020-11-21T21:00前後に実行されます。

もし、ほぼ 45 分に実行して欲しい場合は merge-schedule.ymlの cron の指定を45 * * * *とするか、0/15 * * * *, * * * * *実行などに変更する必要があります。

ただ、このような指定とするとその分 GitHub Actions が実行されるので、 予約投稿日時によっては GitHub Actions の実行時間の無料枠を超過する可能性がある ことに注意してください。

現実的な設定は、予約投稿するであろう 11-12 時、 18-22 時に cron の起動を限定して
0 3,4,9-12 * * *とかにするのが良い
と思います(cron は UTC 日時なので、-9 時間で設定)。

おわりに

以上「GitHub Action で Zenn の予約投稿を実現する」でした。
こういう応用が効くのも Zenn の良さですね。

自分のライフサイクル的に朝に記事を書きあげることが多いので、予約投稿はとても欲しかった機能でした。来月からスタートするアドベントカレンダーでも使っていきたいです。

Discussion

ログインするとコメントできます