🥦

GitHub Actions入門

2024/05/12に公開
4

GitHub Actionsとは?

GitHub Actionsは、GitHubが提供する「スクリプトを動かしてあげるよ~」なサービスです。

具体的に言うと、リポジトリに以下のようなディレクトリを作って、その中に「こういうときにこれを実行してね」なYAMLファイルを設置しておくだけで、GitHubが「お!これを実行したらええんやな!」と認識してくれます。

📁.github
 └📁workflows
    └📄hoge.yml 👈これの中身が実行される

料金(2024年05月現在)

publicリポジトリだと無料で使い放題です。すごい。

privateリポジトリでも無料枠が2,000分/月もあります。

その前に:YAMLの書き方を予習する

先にYAMLの予習をしておくのがオススメです。

というのも、先にYAMLの書き方が分かっていないと「これはGitHub Actionsの機能なの?YAMLの機能なの?」と迷うからです。

学習としてオススメなのが、JSONでいろいろなデータを表現してみたあとに「これをYAMLで表現するならどう書けばいいか」をやってみることです👇

YAMLとJSONの相互変換による練習▲こんな感じで「このYAMLをJSONにするとどうなるか?」を想像する→JSONにしてみるを繰り返すだけでいい練習になります

基本的な書き方

まず以下のようなディレクトリとhoge.ymlというファイルを作ってください。

📁.github
 └📁workflows
    └📄hoge.yml

ちなみにファイル名は何でも大丈夫ですが、.githubworkflowsといったディレクトリ名は1文字でも違っていると動作しません!お気をつけください!

hoge.ymlには、以下のように書きます。

name: GitHub Actions Demo

on: [push]

jobs:
  echo_hello_world:
    runs-on: ubuntu-latest
    steps:
      - run: echo "hello world!!"

内容は「pushされたらechoしてね」になっています。
(詳しい内容は後から説明します)

実際にリポジトリを作ってmainブランチにpushすると、GitHubが「これを実行したらいいんだな」と解釈してくれて、勝手に実行してくれます👇

GitHub Actionsの実行ログ▲GitHubが実行してくれるGitHub Actionsのログは、リポジトリのActionsというタブから確認できます。

何を実行するか

echo "hello world!!"の部分は、コマンドなら基本何でも書けます。

ただしrun-onの部分で指定したOSで使えるコマンド限定です。この場合、Ubuntuを指定しているので、UNIX系のコマンドなら基本使えます。

たとえば👇のようにlsコマンドを実行したりもできますし

jobs:
  echo_hello_world:
    runs-on: ubuntu-latest
    steps:
      - run: ls

👇のように、「特定のURLにリクエストを送る」とかもできます。

jobs:
  echo_hello_world:
    runs-on: ubuntu-latest
    steps:
      - run: curl http://exmaple.com

複数コマンドを実行する

stepsの中にrunを増やしていくと、複数のコマンドを実行できます👇

jobs:
  echo_hello:
    runs-on: ubuntu-latest
    steps: 
      - run: echo "Nice to meet you!!"
      - run: echo "My Name is Taro!!"
      - run: echo "I love programming!!"

また、それぞれにname:をつけることもできます👇

jobs:
  echo_hello:
    runs-on: ubuntu-latest
    steps: 
      - name: "挨拶"
        run: echo "Nice to meet you!!"

      - name: "名前を言う"
        run: echo "My Name is Taro!!"

      - name: "趣味を話す"
        run: echo "I love programming!!"

stepsの中に書く1つ1つの要素のことを「ステップ」と呼びます👇
GitHub Actionsのステップ

基本的には👆のように「1つのステップ=1つのコマンドと名前」にすると分かりやすいです。

ちなみに、最初のコードは👇のようにも書けますが(これはYAMLの文法です)

jobs:
  echo_hello_world:
    runs-on: ubuntu-latest
    steps: 
      - name: "自己紹介"
        run: |
          echo "Nice to meet you!!"
          echo "My Name is Taro!!"
          echo "I love programming!!"

このように👆1つのステップで複数のコマンドを実行してしまうと、失敗したときに原因を特定するのが面倒になるので、基本的に「1ステップ=1コマンド」にするのが良いかもです。

用語

ここからは用語ベースで書きます。

ジョブ、ワークフロー、トリガーの違い▲こういうイメージ

ワークフロー🟩

「こういうときにこれを実行してね」なYAMLファイルに書かれた処理をワークフローと呼びます。

「YAMLファイル=1つのワークフロー」という理解で良いと思います。

ジョブ🟦

複数のコマンドをまとめた単位のことをジョブといいます。

ジョブは複数定義することができます。
たとえば、👇のようにジョブを2つ書くこともできます。

jobs:
  echo_hello:
    runs-on: ubuntu-latest
    steps: 
      - name: "挨拶"
        run: echo "Nice to meet you!!"

      - name: "名前を言う"
        run: echo "My Name is Taro!!"

      - name: "趣味を話す"
        run: echo "I love programming!!"

  echo_goodbye:
    runs-on: ubuntu-latest
    steps: 
      - name: "別れの挨拶をする"
        run: echo "Good Bye!!"

ここで重要なのが、ジョブの中のステップは直列で実行されるが、それぞれのジョブは並列で実行されるという点です。

この場合、echo_helloecho_goodbyeはヨーインドン!で同時に並列で実行されます。

ジョブを増やすとGitHub Actionsの画面でも増える▲Actionsタブで見ても、ジョブが2つになっている

なので、たとえば「別れの挨拶をする」というステップは「趣味を話す」のステップの後に実行してほしいんだよな~という場合は、👇のように1つのジョブの中に書く必要があります。

jobs:
  echo_hello:
    runs-on: ubuntu-latest
    steps: 
      - name: "挨拶"
        run: echo "Nice to meet you!!"

      - name: "名前を言う"
        run: echo "My Name is Taro!!"

      - name: "趣味を話す"
        run: echo "I love programming!!"

      - name: "別れの挨拶をする"
        run: echo "Good Bye!!"

逆に、ステップAとステップBに依存関係がない限り、ステップAとステップBは別々のジョブとして定義したほうが良いです。その分だけ早く終わるからです。

また、ワークフローもジョブと同じでヨーインドン!で同時に並列に実行されます。

たとえば、👇のように複数のワークフローを作った場合、条件に合致するすべてのワークフローがヨーインドン!で同時に処理がスタートします。

📁.github
 └📁workflows
   ├🗒1.yml
   ├🗒2.yml
    └🗒3.yml

トリガー🟪

「どういうタイミングで実行するか」のことをトリガーと呼びます。

ymlファイルのonの部分でトリガーを指定できます。

たとえば👇のように書くと「15分ごとに実行してね」になります。

on:
  schedule:
    - cron: '*/15 * * * *'

👇のように書くと「プルリクエストが作られたら実行してね」になります。

on:
  pull_request:

👇のように書くと「手動で実行できるようにしてね」になります。

on:
  workflow_dispatch:

workflow_dispatchを指定すると手動で設定できるところを説明している画像
▲workflow_dispatchを指定すると、Actionsタブから手動で実行できるようになる

👇のように書くと「developブランチにpushされたら実行してね」になります。

on:
  push:
    branches:
      - develop

👇のように書くと「appsディレクトリ内のファイルに変更があって、かつ、developブランチにpushされたら実行してね」になります。

on:
  push:
    branches:
      - develop
    paths:
      - 'apps/**'

ほかにも色々なタイミングを指定できます。
公式ページにどういうタイミングを設定できるのか全部書いています👇

Workflow syntax for GitHub Actions - GitHub Docs

アクション

「誰かか作った処理をそのままワークフローの一部として使っちゃおう」ができる機能をアクションと呼びます。

話は変わりますが、GitHub Actions上では、リポジトリのソースはデフォルトでは含まれていません。
たとえばAというリポジトリで、GitHub Actionsを動かしたとしても、その実行環境の中ではAというリポジトリのソースは存在しません。自分で用意する必要があります。

え?じゃあ毎回git cloneする必要があるの?面倒くさ~!と思うかもですが、そういう面倒なことをしなくても良いように、GitHub公式が「これを使えば特定のリポジトリのソースを持ってこれるよ~」なアクションを用意してくれています👇

actions/checkout

さらに、GitHub Actionsでは、デフォルトでNode.jsが使えないので、Node.jsをインストールするためのアクションも用意されています👇

actions/setup-node

これらのアクションは、uses: アクション名という形で使用できます。

実際に、この2つを使って「GitHub Actionsで自作のindex.jsというスクリプトを動かしたい!」という場合は、👇のような感じで書けます。

name: Run JavaScript in GitHub Actions

on:
  push:
    branches:
      - main

jobs:
  setup_and_run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4  #👈リポジトリのソースを持ってくる

      - name: Set up Node.js
        uses: actions/setup-node@v3  #👈Node.jsを使えるようにする
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm install

      - name: Run script
        run: node index.js

CI/CD

GitHub Actionsのようなサービスで、「このテストを実行してね」な処理を書くことをCIと呼びます。

「ここにデプロイしてね」な処理を書くことをCDを呼びます。
両方書くことをCI/CDと呼びます。

用語なんてどうでもいいのですが、開発の現場では当たり前のように「CIが~」「CI/CDが~」みたいに使われるので、覚えておいたほうが良いです。

ちなみに、日本語にすると👇のような意味になるらしいです。

  • CI:Continuous Integration(継続的インテグレーション)
  • CD:Continuous Delivery & Deployment(継続的デリバリー&デプロイ)

実務でどうやって使うか?

ここまでは簡単な例だったので、実際に実務でどうやって使えばいいのか?について書きます。

弊社でOSSとして公開している「LooksToMe」というアプリがあるのですが、こちらのアプリを例に紹介します!

LooksToMeというアプリで作成できる画像の例▲画像をアップして、こういう文字を合成できるアプリです

たとえば、CIは👇のコードで実現しています。

https://github.com/looks-to-me/looks-to-me/blob/preview/.github/workflows/pr-push-check.yml#L1-L62

具体的な内容を説明すると、👇の4つのジョブを含むワークフローが

  • Build(Next.jsなどのアプリのビルドが成功するか?)
  • Test(書いたテストが全部通るか?)
  • Lint(ESLintのチェックが全部通るか?)
  • Type(tsxの型チェックが全部通るか)

👇のときにトリガーされます。

  • プルリクがオープンしたとき
  • プルリクが再オープンしたとき
  • プルリクにpushされたとき

そして「これらのすべてのジョブが成功✅で終わらなかった場合、マージさせないぞ」という設定にしています👇
リポジトリのSettings→Branchesからマージさせない設定ができる▲リポジトリのSettings→Branchesから設定できる

ちなみにOSSとして公開しているので、だれでもGitHub Actionsの実行ログを確認できます!👇
GitHub Actionsのログ。誰でも見れる。
https://github.com/looks-to-me/looks-to-me/actions/runs/9032637645

弊社では、全プロダクトでこのようなCI/CDを構築しています。

また、👇のような便利なOSSを公開していたりもします。
ブランチ名をもとにPRに自動でラベルを貼るGitHub Actions

良さげな会社だな~と思った方は、ぜひカジュアル面談にご応募ください~!🙏

\ PR /

弊社では「中級エンジニアになろう!」なブートキャンプのメンバーを募集しています!

「3人1組でたくさんの課題に挑戦しよう!」なやつで、名前を「プラハチャレンジ」といいます。

期間限定募集です!

  • 応募締め切り:5月17日(金)の18時まで
  • 費用:9,800円/月(税抜き)

データベース設計やドメイン駆動設計と言った課題など色々あります。
GitHub Actionsの課題もあります!

興味のある方はぜひ~!!👇

🔹PrAha Challenge | 中級エンジニアを育てるブートキャンプ

PrAha

Discussion

44theworld44theworld

分かりやすい記事をありがとうございます。
PRのブートキャンプを見て昨日応募したのですが、事前テストの締め切りは今日までで合っていますか。
Webサイトでは今日までとあったのですが、Notionのカリキュラムだと昨日までと記載されていたので気になっています。

penpenpenpen

ありがとうございます!
今日までで合っています!
紛らわしくて申し訳ございません🙇‍♀

warabimochiwarabimochi

ここで重要なのが、ワークフローは上から順番に実行されるが、ジョブは並列で実行されるという点です。

この部分、ジョブは並列で実行されるが、ステップは直列で実行されるという書き間違いですかね?
複数のジョブ記述に対して正しい説明ではなさそう?と思いました。

penpenpenpen

ご指摘ありがとうございます!
おっしゃる通りでしたので、修正しました!

  • 修正前:ワークフローは上から順番に実行されるが、ジョブは並列で実行されるという点
  • 修正後:ジョブの中のステップは直列で実行されるが、それぞれのジョブは並列で実行されるという点