技術記事

GitHubActionsでRubyのMinitestを実行する

これは「フィヨルドブートキャンプ Advent Calendar 2020 Part1」23日目の記事です。


Part2も行われています。


昨日はmhさんの「FjordBootCampの歩み方 ~Tips編~」でした。

はじめに

以前チラッとこのブログでも書いたのですが
私は2020年の8月頃からFjordBootCamp(以下フィヨルド)という
プログラミングスクールに参加しました。


現在はプログラミング言語「Ruby」を学ぶカリキュラムを行っています。


今回のアドベントカレンダーの参加にあたり、フィヨルドで学んだ中から、発展編として何か挑戦してみようと思いました。

色々調べた結果、GitHubの機能「GitHubActions」を使って、
Ruby学習で書いた「Minitest」のテストコードを動かせたら面白いのではないかと思い、挑戦してみることにしました!

あじたま

試行錯誤部分も含めて
とても楽しかったヨ!

GitHubActionsって何?

GitHUbActions公式

GitHubの機能の一つで、GitのCommit時や、push時など、
様々な操作が行われたタイミングでワークフローというイベントを動作させることができるようです。

今回GitHubActionsでやりたいこと

まずは予め調べて、やりたいことを図にまとめてみました!
Minitestに加えてRubocopも動かしてみようと思います(フィヨルド仕様のものを使用)。
slack通知までできたら面白そうだなと思いました。

  1. リポジトリーにコードをプッシュ
  2. ワークフローが動き、タスクを実行
  3. rubocopでコードの記述チェック
  4. Minitestでコードを自動テスト
  5. テストの結果をslackに連携
あじたま

GitHubActionsはもっと沢山のことができるみたいだけど
今回はシンプルにテストが走って結果が分かればいいかな?

事前準備

事前準備が膨大になり、ボリュームが増え、
読むのが大変になったため、準備編は別記事にしました。

GitHubActionsでRubyのMinitestを実行する #事前準備編 この記事は「フィヨルドブートキャンプ Advent Calendar 2020 Part 1」 23日目の記事で書いた下記記事の内容が...

GitHubActionsのみ興味がある方は飛ばしていただいて結構です。

事前準備でコードとテストコードを、リモートにプッシュしてあります。

事前準備の状況

事前準備編でリモートリポジトリにlib,testのディレクトリ
そしてFizzBuzzのコードとテストコードを準備しました。
現在のリポジトリは下図のようになっています。

【GitHub】ワークフローファイルを作成する

GItHubActionsではリポジトリー毎に設定されたAction定義に沿ってワークフローが動き、jobを実行していきます。
基本的にはjobは並列実行です。


Action設定を行うにはリポジトリのActionsタブを開きます。

ワークフローファイルが存在していない場合は、リポジトリのコードなどから設定ファイルを表示してくれるようです。
今回使うリポジトリにはRubyのファイルがあるので、Rubyが出ていました。

まずはこの設定ファイルを元に設定してみます。
Set up this workflow を押してファイルを作成します。

設定ファイルがリポジトリ内にできました。

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Ruby

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  test:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby
    # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
    # change this to (see https://github.com/ruby/setup-ruby#versioning):
    # uses: ruby/setup-ruby@v1
      uses: ruby/setup-ruby@21351ecc0a7c196081abca5dc55b08f085efe09a
      with:
        ruby-version: 2.6
    - name: Install dependencies
      run: bundle install
    - name: Run tests
      run: bundle exec rake


デフォルトの設定は以下の内容で書いてあります。

ドキュメントを読んで整理してみると

name: Ruby

ワークフローの名前を決めます。

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

「on:」の下にイベントを発火させるためのトリガーを書きます。
これはmasterにpushかpullされた時が指定されています。

トリガーのリストは下記公式ドキュメントを参照すると書いてあります。
GitHubのイベントと同じものは使うことができるようです。

jobs:
  test:

    runs-on: ubuntu-latest

jobsの下にのidを書きます。

runs-onは起動するUbuntuのバージョン指定です。
この書き方にすると最新版で起動するようです。

steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby
    # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
    # change this to (see https://github.com/ruby/setup-ruby#versioning):
    # uses: ruby/setup-ruby@v1
      uses: ruby/setup-ruby@21351ecc0a7c196081abca5dc55b08f085efe09a
      with:
        ruby-version: 2.6

実行内容が書かれています。

    - name: Install dependencies
      run: bundle install
    - name: Run tests
      run: bundle exec rake


図の右側のようにjob毎にstepが実行されていきます。
-name はstep名です。
-run は実行するコマンドを書きます。

【ローカル】ワークフローファイルを書いてみる

冒頭で書いたやりたいことは2つのjobに別れそうです。
job1:rubocopでコードをレビュー
job2:テストを自動で実行
それぞれのjobの実行結果をslackに通知します。

まずはslack連携は置いておいて、RubocopとMinitestのみを記述してみました。

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Ruby

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  rubocop-test:
    name: Rubocop
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby 2.7
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: 2.7.2
    - name: Install Rubocop-fjord
      run: gem install rubocop-fjord
    - name: Check code
      run: rubocop

  test:
    name: Minitest
    needs: rubocop-test
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby 2.7
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: 2.7.2
         
    - name: Run tests
      run: ruby test/fizzbuzz_test.rb 


jobは2つで「rubocop-test」と「Run tests」です。
並列実行したくないので「needs:」のオプションをつけました。

「rubocop-test」の終了後、testディレクトリ配下の「fizzbuzz_test.rb」を起動します。

また、rubocop-fjordの設定ファイル「.rubocop.yml」も用意しました。
コマンドが実行される階層に配置しました。

【GitHub】実行結果を見てみよう

実行結果を見るにはActionsタブを再度クリックします。
最近の実行結果の一覧を見ることができます。

×がついているので何かに失敗しているようです。
クリックでサマリーを見ることができます。

左のjobsにちゃんとRubocopとMinitestがありますね。
Rubocopを12秒ほど実行し、エラーになっているようです。

jobの名前をクリックするとさらに細かくstepごとの実行結果を見ることができます。

おお!
Check codeのstepでしっかりコードのエラーを検出していますね!!

MInitestの方はRubocopが失敗しているのでjob自体がskipになったようです。
「needs」オプションがしっかり効いている証拠ですね。

Minitestの結果もみたいのでエラーを解決して先に進んでみます。

(解決までに4回もpushする羽目に・・・)
Minitestも突破したので「×」が「✔︎」マークに変わりましたね。
残すところslack連携だけとなりました!

【slack】slackに連携アプリを入れよう

slack連携にはIncoming WebHooksというアプリケーションを使いました。
Slackの左下にあるアプリ追加から「Incoming WebHooks」を検索します。

設定画面で発行されるURLは他人に知られると危険が及ぶ可能性が高いです。

絶対に直接ワークフローファイルに記述しないでください。
次の手順で正しい書き方を書いています。

設定画面でアクセスするためのURLを発行します。

設定画面にある「WebHookURL」を使ってGitHubActionsから通信します。

とりあえずURLをコピーしておきます。
一番下の設定を保存するを押し忘れないようにご注意ください。

【GitHub】GitHubSercletにWebhookURLを登録しよう

URLをそのままワークフローファイルに記載してしまうと、悪用される危険性しかないので、GitHubが提供している「GitHubSercret」を使います。

これは、keyと一緒に登録しておくことで、あとで変数として呼び出すことができるので、大切な情報をGitHubに公開してしまうのを防ぐことができます。

登録は各リポジトリのsettingタブから行うことができます。

「New repository sercret」 を押して登録の画面に進みます。

ワークフローファイルで使うkey名と、先ほどコピーしたslackのURLをvalueに記載してadd sercret ボタンを押します。

これで安全にURLを呼び出す準備が整いました。

余談ですが、過去に誤って公開したために、AWSで痛ましい事件が起きたことを知りました。

皆さんも本当にお気をつけください。

【GitHub】ワークフローファイルにslack連携を書こう

ワークフローファイルにslack連携の設定を追記します。
公式ドキュメントを参考にしました。

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

env:
  SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}

「secrets.【sercretで登録したKEY名】」で取得することができます。
SlackNotifyで必要なWebHookURLをSLACK_WEBHOOKに渡してあげます。

    # テスト成功
    - name: Slack Notification on Success
      if: success()
      uses: rtCamp/action-slack-notify@v2.0.2
      env:
        SLACK_CHANNEL: test
        SLACK_TITLE: rubocop Success
        SLACK_COLOR: good

    # テスト失敗
    - name: Slack Notification on Failure
      uses: rtCamp/action-slack-notify@v2.0.2
      if: failure()
      env:
        SLACK_CHANNEL: test
        SLACK_TITLE: Test Failure
        SLACK_COLOR: danger

肝心の呼び出しのところは if: success()if: failure()で分岐させています。
公式ドキュメントでは${{ failure() }} となっていましたが
if文では省略可能とのことです。

追記した状態でリポジトリにpushして動かしてみましょう。

Successのstepが動いているので成功していそうです。
では・・・slackをみてみましょう(どきどき)

やりました!!!!!!(やりました!!!!!)
分からないところから1から調べつつ、ここまで来ることができました!

最終的なワークフローファイルです。

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Ruby

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

env:
  SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}

jobs:
  rubocop-test:
    name: Rubocop
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby 2.7
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: 2.7.2
    - name: Install Rubocop-fjord
      run: gem install rubocop-fjord
    - name: Check code
      run: rubocop
      
    # テスト成功
    - name: Success
      if: success()
      uses: rtCamp/action-slack-notify@v2.0.2
      env:
        SLACK_CHANNEL: test
        SLACK_TITLE: rubocop Success
        SLACK_COLOR: good

    # テスト失敗
    - name: Failure
      uses: rtCamp/action-slack-notify@v2.0.2
      if: failure()
      env:
        SLACK_CHANNEL: test
        SLACK_TITLE: Test Failure
        SLACK_COLOR: danger
  test:
    name: Minitest
    needs: rubocop-test
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Ruby 2.7
      uses: ruby/setup-ruby@v1
      with:
        ruby-version: 2.7.2
         
    - name: Run tests
      run: ruby test/fizzbuzz_test.rb 
      
    # テスト成功
    - name: Success
      if: success()
      uses: rtCamp/action-slack-notify@v2.0.2
      env:
        SLACK_CHANNEL: test
        SLACK_TITLE: Test Success
        SLACK_COLOR: good

    # テスト失敗
    - name: Failure
      uses: rtCamp/action-slack-notify@v2.0.2
      if: failure()
      env:
        SLACK_CHANNEL: test
        SLACK_TITLE: Test Failure
        SLACK_COLOR: danger

これでコードがpush,pullされる度に自動でテスト&通知してくれます!

おわりに

文字数を確認したら合計6000字を超えていました。
結局準備編を分離することとなりました。

最後に感想を書かせていただきます。

初めてちゃんとした技術記事を書きました。
1から知らないものに挑戦して完走して、やりきった感があります。

GitHubActionsは奥が深くてかなり魅了されました。
正直寝る間も忘れて朝までいじったり調べたりしていました。
これからも学習を続けたいです。

フィヨルドに入って、勢いだけでアドベントカレンダーに参加して、
他の人の記事のレベルの高さにビビりながら題材をさがし、悩んだり焦ったり、奮闘したり
そんなドタバタも含めて参加して良かったなと感じています。

もし独学でやってたらこんな挑戦をしてみようとも、アウトプットを積極的にしようとも思わなかったと思います。

今年の良い締めくくりとなりました!
来年も挑戦とアウトプットを繰り返して成長していきたいと思います。

最後まで記事を見ていただきありがとうございました!


ABOUT ME
あじたま
趣味:ゲーム 投資活動 泳ぐこと、食べること! ゲーム大好きエンジニア。 PC関連ガジェットも大好き。 ゲームライフや投資記事を 日々綴っていきます。
YouTubeでも活動中!

チャンネル登録お願いします!!