cron-job.org で GitHub Actions を正確な時刻に実行する

2026.01.30 09:00
2026.03.16 13:32
cron-job.org で GitHub Actions を正確な時刻に実行する

前回の記事では、GitHub Actions の cron と Chatwork API を使って出退勤メッセージを自動化しました。

仕組み自体はうまく動いていたんですが、しばらく運用していると気になる問題が出てきたんですよね。

cron の実行時刻がズレる。

GitHub Actions の cron は、混雑時に数分〜数十分ほど遅延することがあります。朝 8:55 に設定しているのに、実際にメッセージが届くのが 9:10 だったり、ひどいときは 9:20 過ぎだったり。

出退勤メッセージって、9:00 ちょうどに届いてほしいんですよね。遅れて届くと「寝坊したのかな?」みたいな印象を与えかねないので。

そこで、外部の cron サービス cron-job.org から正確な時刻に GitHub Actions の workflow_dispatch を叩く方式に変えてみました。

cron-job.org とは

cron-job.org は、無料で使える外部 cron サービスです。

指定した URL に HTTP リクエストを定期的に送ってくれるサービスで、1分単位でスケジュールを設定できます。無料枠でもかなり使えるので、今回のような用途にはぴったりですね。

  • 無料で利用可能
  • 1分単位のスケジュール設定
  • HTTP リクエスト(GET / POST など)を送信できる
  • ヘッダーやボディのカスタマイズも可能

GitHub Personal Access Token(Fine-grained)の作成

cron-job.org から GitHub Actions のワークフローを起動するには、GitHub の Personal Access Token が必要です。

今回は Fine-grained token(きめ細かいトークン)を作成します。classic token でも動きますが、必要最小限の権限に絞れる Fine-grained の方が安心ですね。

  1. GitHub の Settings → Developer settings → Personal access tokens → Fine-grained tokens を開く
  2. Generate new token をクリック
  3. Token name: わかりやすい名前をつける(例: cron-job-dispatch
  4. Expiration: 有効期限を設定(後述の注意点を参照)
  5. Repository access: Only select repositories で対象リポジトリのみ選択
  6. Permissions → Repository permissions → Actions: Read and write に設定
  7. Generate token をクリックしてトークンをコピー

このトークンはあとで cron-job.org の設定に使うので、どこかにメモしておいてください。

workflow_dispatch トリガーの追加

前回の記事で作ったワークフローを修正します。schedule トリガーを削除して、workflow_dispatch だけにする構成にしてみました。

name: Chatwork Scheduled Message

on:
  workflow_dispatch: # cron-job.org から呼び出される

jobs:
  send-message:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Resolve message
        id: resolve
        run: |
          pip -q install pyyaml
          MESSAGE=$(python scripts/resolve-message.py messages/calendar.yml) || exit 0
          {
            echo "message<<__EOF__"
            echo "$MESSAGE"
            echo "__EOF__"
          } >> "$GITHUB_OUTPUT"
          echo "should_send=true" >> "$GITHUB_OUTPUT"

      - name: Send Chatwork Message
        if: steps.resolve.outputs.should_send == 'true'
        run: |
          curl -s -X POST \
            -H "X-ChatWorkToken: ${{ secrets.CHATWORK_API_TOKEN }}" \
            --data-urlencode "body=${{ steps.resolve.outputs.message }}" \
            "https://api.chatwork.com/v2/rooms/${{ secrets.CHATWORK_ROOM_ID }}/messages"

変更点は on: の部分だけです。schedule を消して workflow_dispatch だけにしました。

これで、外部から API を叩くことでワークフローを起動できるようになります。もちろん GitHub の Actions タブからの手動実行もこれまで通り可能です。

workflow_id の調べ方

cron-job.org の設定で使う workflow_id を調べておきます。GitHub CLI が入っていれば、以下のコマンドで確認できます。

gh workflow list

出力例:

Chatwork Scheduled Message  active  12345678

この 12345678 の部分が workflow_id です。

GitHub CLI がない場合は、API でも確認できます。

curl -s -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.github.com/repos/{owner}/{repo}/actions/workflows

もしくは、ワークフローファイル名(chatwork-scheduled-message.yml)をそのまま workflow_id の代わりに使うこともできます。この場合、URL は以下のようになります。

https://api.github.com/repos/{owner}/{repo}/actions/workflows/chatwork-scheduled-message.yml/dispatches

cron-job.org の設定

ここからが本題ですね。cron-job.org でジョブを作成していきます。

アカウント作成

cron-job.org にアクセスして、アカウントを作成します。メールアドレスだけで登録できます。

朝の出勤メッセージ用ジョブ

ログインしたら「Cron Jobs」→「Create Cron Job」で新しいジョブを作ります。

設定内容は以下の通りです。

  • Title: Morning Message(わかりやすい名前をつける)
  • URL: https://api.github.com/repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches
  • Method: POST
  • Schedule: 毎日 8:55 JST(= UTC 23:55 ※前日扱い)

Headers タブで以下の3つを追加します。

Authorization: Bearer ghp_xxxxxxxxxxxxxxxxxxxx
Accept: application/vnd.github+json
Content-Type: application/json

Request Body に以下の JSON を設定します。

{"ref": "main"}

ref にはワークフローを実行するブランチ名を指定します。通常は main でOKです。

夕方の退勤メッセージ用ジョブ

同じ要領で、夕方用のジョブも作成します。

  • Title: Evening Message
  • URL: 朝と同じ
  • Method: POST
  • Schedule: 毎日 18:05 JST(= UTC 9:05)
  • Headers: 朝と同じ
  • Request Body: 朝と同じ

これで朝と夕方の2つのジョブが設定できました。

実際にやってみた結果

しばらく運用してみた結果をまとめます。

GitHub Actions の cron だけだったとき

  • 設定時刻から 5〜15分の遅延が頻繁に発生
  • たまに20分以上遅れることも
  • 朝のメッセージが 9:10 や 9:15 に届いてしまう

cron-job.org 経由に変えたあと

  • ほぼジャストタイムで実行される(誤差は1分以内)
  • メッセージが 8:56〜8:57 頃に届くようになった
  • 安定して毎日同じ時刻に届く

体感としてはかなり改善されましたね。出退勤メッセージのように「時刻が重要」な用途では、この差は大きいです。

注意点

トークンの有効期限

Fine-grained token に有効期限を設定している場合、期限が切れるとワークフローが起動しなくなります。期限切れの前にトークンを再生成して、cron-job.org 側のヘッダーも更新するのを忘れないようにしましょう。

カレンダーにリマインダーを設定しておくと安心ですね。

cron-job.org の無料枠の制限

無料プランには以下のような制限があります。

  • ジョブ数の上限あり(ただし今回のように2〜3個なら問題なし)
  • 最短実行間隔は1分
  • 実行履歴の保持期間に制限あり

普通に使う分には無料枠で十分ですね。自分は朝と夕方の2ジョブだけなので、まったく問題なく運用できています。

まとめ

  • GitHub Actions の cron は混雑時に遅延するため、正確な時刻での実行には向いていない
  • cron-job.org から workflow_dispatch を叩く方式にしたら、ほぼジャストタイムで実行されるようになった
  • 設定は「トークン作成 → ワークフロー修正 → cron-job.org でジョブ作成」の3ステップだけ
  • 無料枠で問題なく運用できている

前回の記事で作った出退勤メッセージの自動化が、これでより実用的になりました。同じように GitHub Actions の cron のズレに困っている方の参考になれば嬉しいです。

今回は以上です!