営業時間外にインスタンスを止めるワークフローの書き方(on.schedule の if 制御) [GitHub Actions]

2022/05/29に公開

概要

営業時間外にインスタンスを止めたいときなどに on.schedule を使うと思いますが開始と停止でワークフローを分けるのも不便なので 1 つのワークフローに書く方法の紹介です。

ワークフロー

まずは全体のワークフローです。

.github/workflows/schedule.yml
name: Schedule

on:
  schedule:
    - cron: '0 1 * * 1-5' # 10:00 JST
    - cron: '0 10 * * 1-5' # 19:00 JST
  workflow_dispatch:
    inputs:
      job:
        description: 'Select job'
        required: true
        type: choice
        options:
          - ''
          - start
          - stop

jobs:
  start:
    if: github.event.schedule == '0 1 * * 1-5' || github.event.inputs.job == 'start'
    runs-on: ubuntu-20.04
    timeout-minutes: 5

    steps:
      - name: 開始コマンド
        run: aws ec2 start-instances --instance-ids <instance-1> <instance-2> ...

  stop:
    if: github.event.schedule == '0 10 * * 1-5' || github.event.inputs.job == 'stop'
    runs-on: ubuntu-20.04
    timeout-minutes: 5

    steps:
      - name: 停止コマンド
        run: aws ec2 stop-instances --instance-ids <instance-1> <instance-2> ...

on.schedule

時刻の指定は cron 形式で書くことができます。
後述しますがあくまで cron 形式であって cron そのものではないことに注意してください。

UTC なので 9 時間減らした時間を記載します。
右端は曜日なので月曜~金曜を示す 1-5 を指定します。
8 時始業の会社だと 0 23 * * 0-4 になるでしょうか。

実際は起動時間や残業の兼ね合いで営業時間の前後に少し余裕を持った方がいいと思います。

jobs

startstop のジョブを定義します。
それぞれの ifgithub.event.schedule の値を見ることで今どちらの時間で実行されているか判断しています。
cron の文字列をそのまま書かなければいけないのがやや冗長ですが Re-run を考えると現在時刻を date 等で取得して判定するよりはいいのかなと思います。

視覚的にもどちらが実行されたか分かりやすいです。

開始や停止のコマンドはお使いのプラットフォームに合わせてください。
GitHub ホストランナーの場合は OIDC などで認証も必要です。

schedule を使用する際の注意点

cron ではないので cron の代わりにしようとすると嵌ります。

営業時間に合わせてインスタンスを開始/停止するくらいなら問題にならない項目もあると思いますが、一般的に気を付けた方がいい点について記載しておきます。

遅延

GitHub ホストランナーの実行タイミングは混雑具合に依存するのでキリのいい時間など混み合う時間帯は 1 時間以上遅延することもざらです。
セルフホストランナーならほとんど遅延しないと思われますが、GitHub 側でトリガーされてランナーで実際にジョブが開始するまでに少し時間がかかるので正確な時刻に起動したい場合は避けた方がいいでしょう。

実行間隔

cron だと 1 分間隔ですが schedule では最短の間隔は 5 分ごとに 1 回です。

時間経過による停止

リポジトリに 60 日以上アクティビティがないと schedule ワークフローは停止されます。
コミットを足せば回避はできますが、仕様が変わるかもしれないので死活監視に使用するのは絶対にやめましょう

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

on.workflow_dispatch

トラブルや祝日など手動で実行したいときもあると思います。
ジョブを選択して実行できるようにしておきましょう。

本当は祝日も自動判定した方がいいとは思いますがここでは割愛します。

空文字列をデフォルト値にしておくと意図せぬ実行や無選択での実行を防げます。
空文字列を選択したときもこのエラーになります。

GitHub Enterprise Server (GHES) をお使いの方へ。
type: choiceGHES 3.4 以降で使用できます。

Discussion