497
423

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GitHub Actionsって何?触ってみて理解しよう!入門・逆引きリファレンス

Last updated at Posted at 2022-07-18

ある日のこと

「さーて、今日もGitHubにコミットをプッシュしていくぞ〜〜」
「ローカルでコミットした変更をgit push origin mainして、、」
github.comのレポジトリを見にいくと、、お!反映されているな!Initial Commitってちゃんと出ているぜ!」
「そういえば、いつも気にしていなかったけどActionsタブってのがあるな?これってなんだ?」

image.png

これがGitHub Actionsです。レポジトリごとに用意されていて、Actionsタブから管理、確認することができます。

「ほ〜。GitHub Actionsっていうのか・・なんのためにあるんだろう?ここで何ができるの?」

GitHub Actionsとは

GitHub ActionsはGitHubがサービスの一環として提供する、ワークフロー自動化サービスです。

簡単に言えば、「開発している時にやりたいことを、GitHub上で自動化できるサービス」です。

「なるほど・・つまりGitHubをコード置き場として使うだけじゃなくて、手元でやるような、よくある手順をGitHub側で自動で実行できるんだ?」
「なんか便利そうだけど、自動化って難しそうだし、あんまり役立つことのイメージがつかないなあ」

触ってみよう

簡単にGitHub Actionsに触れてみましょう!

先ほど触っていたレポジトリにGitHub Actionを導入するところから始めてみます

まず、Actionsタブを開きます。レポジトリになにもGitHub Actionsが設定されていない場合、次のような画面が出てきます。既に何かしらのワークフローが存在する場合は左上のNew Workflowから同じような画面を開くことができます。

image.png

下の方にある簡単設定ボタンを使ってもいいのですが、今回はset up a workflow yourselfを押してみましょう。

image.png

このような画面が出てきて、何やらyamlファイルを編集する画面になります。とりあえず中身は読み飛ばして、コミットしてみましょう。

image.png

適切なコミットメッセージを追加し、Commit new fileを押すと、GitHub上で新しいコミットを追加することができます。

こうすることで、始めてのGitHub Actionを走らせることに成功しました!
Actionsタブを改めて開いてみましょう!

image.png

先ほど定義したアクションが無事に動いていることがわかります。

「なんかよくわからないけど、思ったより簡単にワークフローを作れたみたいだ」
「何が起こっているのかはよくわからないけど、左の緑のチェックマークが気持ちいい!」
「中で何が起こっているのかもうちょっと詳しく見てみたいな」

中身の概要

先ほど読み飛ばしたmain.ymlの中身を見てみましょう!

image.png

コード
.github/workflows/main.yml
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the "main" branch
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v3

      # Runs a single command using the runners shell
      - name: Run a one-line script
        run: echo Hello, world!

      # Runs a set of commands using the runners shell
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.

このyamlファイルは大まかに分けると二つのパートで構成されています。

  1. ワークフローについての情報を定義するパート
  2. ワークフローの中身を定義するパート

ワークフローについての情報を定義するパート

具体的には
image.png

ここの部分が該当します。

name:ではワークフローの名前を定義しています。ここで定義した名前がActionsタブにも表示されます。

on:では、どのタイミングでこのワークフローが走るかが定義されています。今回のワークフローでは

  1. 何かしらのコミットがGitHubに追加された時(push
     ・ただし、mainブランチのみ(branches: ["main"]
  2. 新しくプルリクエストが作成された時(pull_request)
     ・ただし、mainブランチのみ(branches: ["main"])
  3. 明示的に走って!とボタンを押したタイミング(workflow_dispatch

の三種類のタイミングで走るよ、と定義されています。

「なるほど、ここでタイミングが定義されているのか」
「さっき走っていたワークフローのrunをクリックしてみてみると・・」

image.png

「確かにmainブランチに対してのon: pushで走った、って書いてある!」
「つまり、GitHub Actionはyamlファイルの中身を読んで、該当するケースに当たったら処理を始めてくれるのね」

ワークフローの中身を定義するパート

ワークフローでどういう処理が行われるかはyamlの後半部分、

image.png

ここが該当します。

jobs:では一つのワークフローの中に含まれる一つ一つの一連の処理を定義します。現在のワークフローにはbuild:というジョブが一つ存在しています。

(ジョブ名):の中にそれぞれのジョブの設定、処理内容を書きます。

  • runs-on:では、どのような仮想環境でジョブの処理を動かすかを定義します。今回はubuntuの最新版を使う、となっています。

  • steps:に具体的な一つ一つの処理を書いていきます。全部で3つの処理をしています。

    • 最初のステップでは、外部で定義された別のアクションを呼び出しています。このステップではactions/checkout@v3つまり、自分自身のレポジトリのデータを読み込む、という処理が走っています。このステップから始まるワークフローが一番多いと思われます。(こういった外部呼び出しされるアクションはGitHubで公開されています→actions/checkout
    • 次のステップでは単一のシェルスクリプト(echo Hello, world)が走っています。
    • 最後のステップでは、複数のシェルスクリプトが走っています。

これらのジョブ、ステップはActionsタブから実行結果を確認することができます。

image.png
緑のチェックマークが付いている場所をクリックしてみるとこのような画面になります。
image.png

buildというジョブが見えますね。これをさらにクリックすると、このような画面が表示されます。
image.png

前後にセットアップ処理などが含まれていますが、ちゃんと定義した三つのステップが実行されているのが見えます。

「ふむふむ、一つのワークフローの中にはジョブというものとその中で動くステップというものがあるのか」
「ためしにジョブを一個増やしてみよう」
image.png
buildジョブの下に新しくhogeジョブを作ってみた!これでコミットしてみると、、」
image.png
「おお!ジョブが増えたぞ!しかも並列に実行されてるっぽい!」
「こうやって並列で動くジョブ順番に動くステップを組み合わせて一つのワークフローとまとめていくんだな。完全に理解した!」

GitHub Actionsでできることの紹介

「でもコミットごとにあいさつをしてもらっても、ちょっと、、って感じだな。。」
「具体的に何ができるのか知りたいな」

このパートでは、逆引き的にGitHub Actionsで達成できることを紹介していきます

この記事では例としてPythonを使ったプロジェクトでの解説を行いますが、Pythonに限らず他の言語でも共通して利用できるような内容にフォーカスしています

自動テストの実行

「最近、プロジェクトに自動テストが導入されたんだよな」
「手元で実行できるけど、これが自動的に動いてくれたら便利かも」

プロジェクトに自動テストが導入されると、コードの動作についての結果や品質を簡単に担保することができるようになります。この自動テストをローカルだけでなく、GitHub Actions上でも実行することで、継続的にコードの動作をモニタリングすることができるようになります。例として以下のような簡単なpythonのプロジェクトを考えてみます。

project/
  src/
    main.py
  tests/
    test_main.py
  pyproject.toml
src/main.py
src/main.py
import sys


def add(a: int, b: int) -> int:
    return a + b


def main():
    if len(sys.argv) <= 2:
        print("a and b is required")
    _, a, b, *_ = sys.argv
    print(add(*map(int, (a, b))))


if __name__ == "__main__":
    main()
src/test_main.py
src/main.py
from unittest import TestCase

from src.main import add


class MainTestCase(TestCase):
    def test_add(self):
        self.assertEqual(5, add(2, 3))

この自動テストを実行すると、以下のようになります

image.png

これをGitHub Actionsに組み込んでみましょう!
test.ymlを作成してみます

.github/workflows/test.yml
name: Run Tests

on:
  push:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Python Setup
        uses: actions/setup-python@v1
        with:
          python-version: 3.7

      - name: Setup Poetry
        uses: Gr1N/setup-poetry@v7

      - name: Run poetry install
        run: poetry install

      - name: Run tests
        run: poetry run python -m pytest

これをプッシュすると次のように、Run Testsというワークフローが新しく実行されていることを確認できます。

image.png

中身をみると、正しくローカルで実行したものと同じ結果が得られていますね!

image.png

「おお〜!こうすれば手元で毎回実行しなくても、プッシュした時に毎回自動テストを走らせてくれるんだ!」
「これは便利だ」
「なるほど、手元で実行するときはセットアップが終わってるからコマンド一発だけど、GitHub Actionsだとまっさらな状態からスタートするから、事前準備が必要なんだね」
「まずレポジトリをチェックアウトして」 ...(1)
「Pythonをセットアップして」 ...(2)
「パッケージマネージャのPoetryをインストールしたら」 ...(3)
「プロジェクトに必要なパッケージをpoetry installで入れて」 ...(4)
「...最後にpytestを走らせているのね。面倒臭いけど、考えてみると当たり前のステップだね」
「新しいメンバーの環境構築を手伝ってあげている感覚かも」

プルリクエストにアノテーションをつける

「そういえば自動テストと一緒にリンターも導入されたんだよな」
「コードのフォーマットをみんなで統一してくれるすごいやつなんだけど、こいつを走らせられると便利かもな」
「あ〜でも、走らせて落ちたところでActionsの中身まで確認しに行ってどこに問題があるのか探すのは結構骨が折れるかも・・」

そんな悩みも解決できます。Annotationsという仕組みを使うことで、コードに対してコメントのような形でツールの処理結果を追加することができます。

先ほどと同じようにlint.ymlを作成します。Pythonのflake8というリンターを使い、コードの問題点をチェックするとします。

.github/workflows/lint.yml
name: Lint

on:
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Python Setup
        uses: actions/setup-python@v1
        with:
          python-version: 3.7

      - name: Setup Poetry
        uses: Gr1N/setup-poetry@v7

      - name: Run poetry install
        run: poetry install

      - name: Lint
        run: |
          echo "::add-matcher::.github/workflows/flake8-problem-matcher.json"
          poetry run python -m flake8 .

この時のpoetry run python -m flake8 .の実行結果は次のようになります。

$ poetry run python -m flake8 .
./src/main.py:9:24: E222 multiple spaces after operator
./src/main.py:9:31: E261 at least two spaces before inline comment

このように問題があるファイルと行番号・列番号とエラーの詳細を出力してくれますが、GitHub Actionsではこのチェックを自動化しつつ、Annotationsを使うことで問題のある箇所をコード上で確認できるようになります。

Problem Matcherという機能を使います。この機能は、出力されるメッセージをパースし、条件にあった場合にその行をハイライトした上で、Annotationsに変換してくれる、というものになります。

今回はこのようなファイルを用意します。

.github/workflows/flake8-problem-matcher.json
{
  "problemMatcher": [
    {
      "owner": "flake8",
      "severity": "warning",
      "pattern": [
        {
          "regexp": "^(.+?):([0-9]+?):([0-9]+?): ([A-Z][0-9]+) (.+)$",
          "file": 1,
          "line": 2,
          "column": 3,
          "message": 5,
          "code": 4
        }
      ]
    }
  ]
}

先ほどのエラーメッセージを正規表現でマッチさせ、ファイル名、行番号、列番号、メッセージ、エラーコードに当たる箇所をグループマッチの番号で指定します。

そして、次の行を足すことで、このmatcherを追加してね、という指示を出すことができます。

.github/workflows/lint.yml
      - name: Lint
        run: |
+         echo "::add-matcher::.github/workflows/flake8-problem-matcher.json"
          poetry run python -m flake8 .

これらを設定したものをプッシュし、新しいプルリクエストを開いてみた結果がこちらになります。

image.png

まず、Annotationsの中に、flake8のエラーの結果が含まれていることがわかると思います。さらに詳細を見てみましょう。

image.png

正しくflake8の出力結果がwarningとして解析されていることがわかります。そしてこの状態でプルリクエストのファイル一覧を開くと・・・

image.png

問題のある箇所が一目瞭然にコメントが付けられます。

「おおお!これを使えばActionの実行を意識しなくても、レビューするときに簡単に問題のある箇所を見つけられる!」
「これは自動テストとか静的解析にも応用できそう・・」

ここでは簡単にアノテーションを作成できることを示すためにProblem Matcherを利用しましたが、今回で言うと https://github.com/tayfun/flake8-your-pr など、既製のアクションが用意されている場合も多いので一度検索してみてください!

Artifactsの作成

テストカバレッジ
「自動テストが書いてあると、動作確認が楽だなあ〜」
「あれ?テストは通ってるのに新機能を使ってみたら落ちちゃった・・」
「どれどれ、うわ!新機能作ったはいいけどテストを書いてなかったんだ!」
「あちゃ〜、気づかなかったなあ〜」

こんなことは自動テストを書いていてもよく起こります。このような事態を回避するために使えるのがテストカバレッジです

「テストカバレッジ・・?そういえばテストを書くときにそんなことも言われていたような・・・」

テストカバレッジ(あるいは単にカバレッジとも)はテストを実行したときに、具体的にテストされるコードのどの部分が実行されたかを確認できる仕組みです。

$ poetry add -D pytest-cov
$ poetry run -m pytest --cov --cov-report=html

このように実行すると、テスト中にどこの処理が走ったかを可視化することができます

image.png

「おおお!こうすることでaddはちゃんとテストが通っているのにmulは通っていないことが一目瞭然だ!」
「掛け算を期待する場面なのに足し算のままになっているのね・・テストを書かなきゃ!」

GitHub ActionsのArtifacts
「でも、これを自動化しようとすると難しいよな・・」
「CIの実行画面でも見にくいだろうし、Annotationsだとちょっとたくさん書き出されすぎて、それも辛そう・・」
「できれば吐き出されるhtmlファイルをそのままみたいな〜」

という要望もArtifactsを使うと実現できます。Artifactsを使うことでJobの成果物をActionsの結果に紐づけて後からダウンロードできるようになります。

coverage.ymlを追加してみましょう

.github/workflows/coverage.yml
name: Collect Coverages

on:
  pull_request:

jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Python Setup
        uses: actions/setup-python@v1
        with:
          python-version: 3.7

      - name: Setup Poetry
        uses: Gr1N/setup-poetry@v7

      - name: Run poetry install
        run: poetry install

      - name: Collect Coverages
        run: poetry run python -m pytest --cov --cov-report=term --cov-report=html

      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: coverage
          path: htmlcov/

このように書くことで、pytestが生成してくれるhtmlcovというディレクトリをCI上でアップロードしてくれます。

image.png

「お、coverageっていうArtifactができてる!こいつをクリックすると...」
「zipファイルがダウンロードされた!」
「中身を見るとちゃんとさっき手元でテストを走らせたときに生成された内容と一致してる!」
「これによって、生成物がある処理もCI上で走らせて後からスイスイダウンロードできるんだ!めっちゃ便利!」

リリース作成・コミット追加

To Be Written

アクション・ワークフローの作成・呼び出し

To Be Written

まとめ

「なるほど、GitHub Actionsを使うことで、何回も走らせることになる処理人間の手によらずに効率的に回せるようになるんだ」
「そう考えるといろんな使い道が思いつくかも!」

とても簡単に導入できるCIサービス、GitHub Actionsを使いこなし、より快適な開発体験を作ってみましょう!

レポジトリ

今回使ったデモ用のレポジトリはこちらになります

497
423
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
497
423

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?