Fringe81 アドベントカレンダー2020の15日目の記事です。
これまで何かのプログラムを定期実行させるときは、AWS LambdaとAWS CloudWatchを使ってましたが、GitHub Actionsだけでできそうだなと思ったのでやってみました。
GitHubにサンプルコードを公開しています。
実装
以下のようなYAMLファイルを${root}/.github/workflows
ディレクトリに配置し、${root}/main.go
に実際に処理したいGoプログラムを配置します。
on:
push:
schedule:
- cron: "*/5 * * * *"
jobs:
run:
name: run
runs-on: ubuntu-latest
steps:
# GOPATH等のセットアップ
- name: Set Up
uses: actions/setup-go@v2
with:
go-version: ~1.15
# repositoryの中身にアクセスするためにチェックアウト
- name: Checkout
uses: actions/checkout@v2
# 実行
- name: Run
run: go run main.go
env:
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
定義ファイルの設定
詳しくはこちら
- on: ワークフローをトリガーするGitHubイベントの名前
- 上記ファイルの場合は、リポジトリにpushした時と5分に1回イベントが発火する。
- jobs: 各jobを設定
- 上記ファイルの場合は、以下のようなjobを設定した。
- セットアップ
- repositoryの中身に移動
- 実行(secretsから環境変数に代入し、プログラム側では
os.Getenv()
で実際の値を取得)
- 上記ファイルの場合は、以下のようなjobを設定した。
実装時にはまったこと
onの設定
サンプルコードでは、push
とschedule
を設定しました。
pushはどのブランチでも実行されますが、scheduleはデフォルトまたはベースブランチの直近のコミットで実行されるので、デフォルトまたデフォルトまたはベースブランチ以外で作業している場合は注意が必要です。
環境変数の設定
今回はサンプルとして、Slackにメッセージを送信するプログラムを用意しました(Slackにメッセージを送信するだけならcurlで良いが、今回はGoプログラムを実行したのであえてGoプログラムを用意した)。
Slackにメッセージを送信するためには、Webhook URLが必要になるが、このURLのように外部に公開したくない変数を用いる場合は、リポジトリの暗号化されたシークレットの作成を参考に環境変数を設定し、os.Getenv()
を使う。
定期実行できる最短の間隔は、5分に1回であり、厳密には設定できない
これはめっちゃハマった。
デバッグしようと思ってpushして10分たっても実行されずプログラムがおかしいのかなと思って時間を溶かしてしまった、、、
定期実行するためにはcron構文を使う(参考)が、docにも記載がある通り、5分に1回よりも短く設定することはできません。また、5分に1回と設定(*/5 * * * *
)しても、5分に1回実行されるわけではありません(なんで?最大18分遅延した)。
感想
時間を厳密にする必要のない場合は、コードの管理とcronの設定を同一リポジトリで行えるので便利だなと思いました。
cronの時間が厳密でない理由をどなたかご存知でしたら教えてください