This is IT

技術、日常

【Rails】GithubActionsで定期実行ができるworkflowを丁寧に解説させてください

はじめに

これは フィヨルドブートキャンプ Part 1 Advent Calendar 2024 の8日目の記事です。

昨日の記事は、kyokucho1989さんの時間とたたかうフィヨルドブートキャンプでした!

この記事は何?

この記事ではGithubActionsを利用した定期実行処理を行う方法を、手動テストも含めて解説していきます。

GithubActions自体の説明よりも、実装方法(workflowの書き方)に重点を置いた記事になりますのでご了承ください😅

GithubActionsとは?

とはいえ、GithubActionsを全く知らない人が読んでも「なんだこれ?」になってしまうと思うので、簡単に説明だけはさせてください!

GithubActionsはGithubが提供する、CI/CDのプラットフォームになります。

リポジトリに存在するファイル/コードを利用して、仮想環境内で色々な処理を行ってくれます。

www.sbbit.jp

docs.github.com

例えば、

  • ブランチにコミットをpushしたタイミングで、
  • テストを全て走らせる

といった自動テストや

  • PRがmainにマージされたタイミングで、
  • 運用環境にデプロイ

といった自動デプロイに用いられることが多いです。

今回はこれを利用して、定期実行「毎日〇時のタイミングで、ある処理を実行」を実現していきたいと思います😊

サンプルコード

今回は以下のサンプルコード(workflow)を利用して説明をしていきます。

name: Cron Saving Latest Events

on:
  schedule:
    - cron: "0 21 * * *"

jobs:
  saving-latest-events:
    runs-on: ubuntu-latest

    env:
      RAILS_ENV: development

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.3.0'

      - name: Install dependencies
        run: bundle install

      - name: Run rake fetch task
        run: rake fetch:events

一点注意点として、本記事では説明のために開発環境で実行しますが、実際の運用では本番環境で行うことが多いと思います😅

解説

環境は以下を利用します。

workflowの構造

workflowとはGithubActionsへの指示書です。

/.github/workflows/配下にyaml形式で格納をすることで、GithubActionsは指示を確認することができます。

構造の大枠は以下のようになっています。

  • name
    • workflowの名前
  • on
    • 処理を実行するタイミング(トリガー)を設定
  • jobs
    • 実行してもらう処理を設定

先ほどのサンプルコードを構造ごとにわけると以下のようになります。

# <<----------name part---------->>
name: Cron Saving Latest Events

# <<----------on part---------->>
on:
  schedule:
    - cron: "0 21 * * *"

# <<----------jobs part---------->>
jobs:
  saving-latest-events:
    runs-on: ubuntu-latest

    env:
      RAILS_ENV: development

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.3.0'

      - name: Install dependencies
        run: bundle install

      - name: Run rake fetch task
        run: rake fetch:events

一つずつ何をしているか見ていきましょう。

name

# <<----------name part---------->>
name: Cron Saving Latest Events

workflowの名前を表します。 ファイル名と同じものを記述するのが一般的かと思います。

ここで付けた名前がGithubに表示されます。

  1. Githubで自身のプロジェクトへ
  2. Actionsを押す
  3. All workflowsを確認する

image.png

image.png

上記画像のように

  • name: LintLint
  • name: RubyRuby

と、nameで設定した文字列が出力されています。

nameは省略が可能で、省略をした場合はリポジトリのルートから相対的なworkdlowのパスが表示されます。

今回だと

  • .github/workflows/cron_fetch_reading_clubs.yml

が該当します。

画像のように相対パスだと見切れてしまうことがあるので、name: xxxでworkflow名をしっかりと付けた方が他の人が見たときに分かりやすいかもしれませんね。

on

ここではworkflowの処理を実行するタイミング=トリガーを定義します。

# <<----------on part---------->>
on:
  schedule:
    - cron: "0 21 * * *"
  • on:トリガーの定義開始
  • schedule:ワークフローの時間スケジュールを定義
  • cronPOSIX cron 構文による時刻設定

cron構文は以下のような書き方をします。

分 時 日  月 曜日
*  *  *  *   *

qiita.com

今回の例だと、曜日や月・日を指定していない = 毎日21:00にこのworkflowを実行するといったトリガーになります😊

この時の注意点としてworkflowはUTCの時刻で解釈をすることが挙げられます。そのため、今回のscheduleを正確に表すと、

  • (UTC時刻で)毎日21:00にこのworkflowを実行する
  • (JTC時刻で)毎日09:00にこのworkflowを実行する

となります。

またこのトリガー設定だけだと手動実行による確認がとれません

「09:00まで待たないと動作確認できないなんて不安~」という方には後ほど説明します😋

(タイトルにも入っている定期実行はここの設定だけで終わりです笑)

jobs

jobsではGithubActionsに行ってもらう処理を記述します。 複数のジョブを設定でき、それぞれ独立して実行されます。

# <<----------jobs part---------->>
jobs:
  saving-latest-events:
    runs-on: ubuntu-latest

    env:
      RAILS_ENV: development

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.3.0'

      - name: Install dependencies
        run: bundle install

      - name: Run rake fetch task
        run: rake fetch:events
jobのid・実行環境の設定
jobs:
  saving-latest-events:
    runs-on: ubuntu-latest

GithubActionsは仮想環境で実行されるため、どの環境で実行してもらうかをruns-onで指定する必要があります。

上記の例だと、

  • saving-latest-eventsのidを持つjobは、最新のubuntu環境で実行をする

といった指示を出しています。

また以下のように複数のjobを複数の環境で実行可能です。

jobs:
  job_name_1:
    runs-on: ubuntu-latest
    ...

  job_name_2:
    runs-on: windows-latest
    ...
環境変数の設定
env:
  RAILS_ENV: development

envを利用することで環境変数を設定することができます。

Railsアプリケーションはlocalに設定されている環境変数RAILS_ENVを見てどの環境で実行するかを決めます。 例えばRAILS_ENV=developmentとしていたら、database.ymlもdevelopment環境のものを確認しにいきますね。

一方GithubActionsにおいては仮想環境を新しく立ち上げてからworkflowの実行が行われるので、環境変数の設定は何もされていません。

そのため必要な環境変数は全てworkflow内で明記する必要があります。

(RailsアプリケーションはデフォルトでRAILS_ENV=developmentとして実行をしようとするので本来は必要ないですが明示しています)

stepsで処理指示

ここまではあくまで環境の設定です。 ようやくここから実際の処理の指示を出すことが出来ます😅

steps:
  - name: Checkout code
    uses: actions/checkout@v4

  - name: Set up Ruby
    uses: ruby/setup-ruby@v1
    with:
      ruby-version: '3.3.0'

  - name: Install dependencies
    run: bundle install

  - name: Run rake fetch task
    run: rake fetch:events

stepsでは実際にGithubActionsで行う処理を記述していきます。

  • name
    • 各stepの名前
    • ここで付けた名前がリポジトリの [アクション] タブに表示されます

image.png

  • uses
    • 三者もしくはGitHubが作成した処理を実行します
  • run
    • 仮想環境内で実行するコマンド
uses
- name: Checkout code
  uses: actions/checkout@v4

- name: Set up Ruby
  uses: ruby/setup-ruby@v1
  with:
    ruby-version: '3.3.0'

今回だとCheckout codeSet up Rubyでusesを利用しています。

前者は「GithubActionsの仮想環境用のディレクトリにリポジトリのクローン」を、後者は「Rubyのセットアップ」を行っています。

例えば「Rubyのセットアップ」なんかは、本来だったらrbenvを利用して必要なバージョンをインストールして指定して...といったくだりが必要で、コマンド実行で1からやろうとすると面倒くさいですよね😓

runsでは再利用可能な処理を第三者またはGitHubが公開してくれているので、それを利用することで処理のセットアップを楽に行うことが出来ます。

GitHub - actions/checkout: Action for checking out a repo

GitHub - ruby/setup-ruby: An action to download a prebuilt Ruby and add it to the PATH in 5 seconds

ちなみに今回は、一番最後にrun: rake fetch:eventsRailsで作成できるRakeタスク処理の指示を出しているので、RubyRailsのセットアップをしておく必要があります。

今回はuses: ruby/setup-ruby@v1Rubyのインストールを、後述のrun: bundle installでGemfileに記述してあるrailsをインストールします。

run

ここでは実際にコマンドとして打鍵してほしい処理を記述します。

- name: Install dependencies
  run: bundle install

- name: Run rake fetch task
  run: rake fetch:events

runで指定しているコマンドの通り、gemのインストールとrakeタスクの実行を行っています。

もう一度サンプルコードを見てみる

name: Cron Saving Latest Events

on:
  schedule:
    - cron: "0 21 * * *"

jobs:
  saving-latest-events:
    runs-on: ubuntu-latest

    env:
      RAILS_ENV: development

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.3.0'

      - name: Install dependencies
        run: bundle install

      - name: Run rake fetch task
        run: rake fetch:events

ここまでの解説でこのworkflowの目的が理解出来たでしょうか?

  • nameでworkflowの名前を設定
  • on.schedule.cronで定期実行の日時刻を設定
  • jobsで行ってもらう処理を設定
    • runs-onで環境の設定
    • envで環境変数の設定
    • stepsで具体的な処理を記述

動作確認がしたい

実は先ほどの設定では、onで設定した時刻が来るまでは動作確認ができません。 手動でworkflowの動作を確認したい場合は、onパートに以下を追加してください😊

on:
  workflow_dispatch:
  push:
      branches: [ your_branch_name ]
  schedule:
    - cron: "0 21 * * *"
  • workflow_dispatch

手動でworkflowの実行ができるようにします。

docs.github.com


  • push: branches: [ your_branch_name ]

workflow_dispatchの追記だけではまだGithub上でworkflowの確認が出来ません。 GithubのActionsで出力されるのは「実行されたworkflow」だけで、現状はまだ「手動で実行ができるようになる」設定を追記したからです。

そこでpush: branches: [ your_branch_name ]を記述することで、「push時にworkflowを実行する」の設定を追加できます。そのためすぐにGithub上でworkflowの確認を行えます。

Githubで表示されるようになり、push時/手動での動作確認もできたらworkflowはまた元に戻しておきましょう。

on:
  schedule:
    - cron: "0 21 * * *"

さいごに

フィヨルドブートキャンプのアドベントカレンダーを機に久々の記事を書いたのでとても疲れました😂

GithubActionsのドキュメントは中々難解だと思うので、おまじないとしてしか見ていなかった箇所もこの記事で少しでも理解を深められたらなと思います!

参考:

qiita.com

docs.github.com

docs.github.com