at backyard

Color my life with the chaos of trouble.

rebuild ep 339で話題にあったGitHub Actionsをcron代わりにする方法を試してみた

今日rebuildfmを聞いていたところ、GitHub Actionsでcron構文を用いて定期的にスケジュール実行する方法が紹介されていた。

rebuild.fm

ポッドキャストの中でも話していたが、ローカルPC内でcrontabなどを用いて定期実行するようなものをGitHub Actionsに移行できるのは、かなり便利だなと思ったので自身でも試してみた。

※下記は試してみたあとのツイート

GitHub Actionsでcron構文を用いてスケジュール実行を行う

公式のドキュメント内にcron構文を用いたスケジュール実行に関する記述があるので、こちらを参考にした。

https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule

例えば毎時0分に実行したい場合、.github/workflows/ 配下の yaml ファイルに下記のように記載すれば、毎時0分に特定の処理が実行されるようになる。

on:
  schedule:
    - cron: '0 * * * *'

jobs:
#  実行したい処理を書いていく

GitHub Actionsの実行タイミングは遅れる

ちなみに先に書いておくと、このようにGitHub Actionsのスケジュール実行を行う場合、実行される時刻は正確ではないことに注意する必要がある。 例えば、下記は 17:00 に実行されるように設定した処理だが、実際に動いたのは 17:25 頃となっている。
(一発目の実行でいきなりかなり遅れたが、他の人の記事を見ていると結構時間のばらつきはあるようで、数分後に実行されるケースなどもあるようだ)

17:00に実行されるはずが実際に通知が来たのは17:25頃

このように実行時刻についてはかなりアバウトな形のようなので、もしある程度時刻に対して正確さを求めるなら、例えば AWS lambdaCloudWatch Event を組み合わせたスケジュール実行などを検討してみるのが良い。
自身でもこの組み合わせで定期的に動かしている処理があるが、こちらは実行時間は指定通りに行われているように思える。
ちょっとした実行であれば料金も無料枠内に抑えられる。

逆に言うと1日に1回だけ実行したい、というようなケースではGitHub Actionsを用いたcron実行はかなり良いと思う。

以下のようにpublicリポジトリなら料金はかからないし、ちょっとした処理でもprivateリポジトリでも無料枠内を超える可能性は低そうだ。

https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions

publicリポジトリの場合、60日間活動をしないとスケジュール実行(cron)が無効になる

なお、publicリポジトリで行う場合、一点注意するポイントがある。

https://docs.github.com/en/actions/managing-workflow-runs/disabling-and-enabling-a-workflow

上記ページには以下のような記載がある。

To prevent unnecessary workflow runs, scheduled workflows may be disabled automatically. When a public repository is forked, scheduled workflows are disabled by default. In a public repository, scheduled workflows are automatically disabled when no repository activity has occurred in 60 days.

ここに書かれているように60日間何もしていないとワークフローは無効化されるため、その点のみ考慮する必要がある。
privateリポジトリにはそのような記載はないので、無料枠で収まることを見越してprivateリポジトリでやるか、例えば1月に一回何らかのactivityとなるようなことをする(そしてそれを自動化する)などするような対抗策が考えられる。

まあ、ここについてはまた必要に迫ったときに考えてみようと思う。

Slack通知をGitHub Actionsのスケジュール実行を通じて行うサンプル

今回このcronを用いたスケジュール実行のサンプルとして、定期的にSlackに通知を送るだけのプログラムをDenoを使って書いてみた。

実際に作成したプログラムは下記。

github.com

今回の場合Slackのincoming webhookのURLを用意する必要があるが、publicリポジトリのため当然見えるところには置いておきたくない。

というわけで、GitHub側で用意されているscretsの仕組みを利用している。

https://docs.github.com/en/actions/security-guides/encrypted-secrets

詳細は上のドキュメントを参照するのが確実だが、これを使えば、例えば上のリポジトリであればownerである私だけが管理できるsecretsを追加できる。
ここにincoming webhookのURLを設定しておけば、外側にはもれずに値を利用することが可能。
(ちなみにOrganizationリポジトリの場合は admin での権限が必要になるらしい)

実際にsecretsを参照する際は下記のように呼び出して環境変数にセットしている。
(プログラム内ではこの環境変数の値を呼び出して処理を実行している)

env:
  SLACK_INCOMING_WEBHOOK_URL: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }}

※具体的な処理は上に貼ったリポジトリを参照してみてください

というわけで、GitHub Actionsの活用方法を知れてハッピーな日でした。rebuildfmに感謝。