Github Actions の複合ステップアクションを利用してアクションを分離・再利用する

こちらのブログは個人ブログと同じ内容です

www.ritolab.com


Github が 2020 年 8 月 7 日に、複合ステップアクションという機能をリリースしました。

GitHub Actions: Composite Run Steps
https://github.blog/changelog/2020-08-07-github-actions-composite-run-steps/

なかなか便利そうだったのでこれを試してみたいと思います。

複合ステップアクション(Composite run steps actions)

複合ステップアクションとは、1つのアクション内で複数のワークフローの実行手順を組み合わせることができる機能です。

よく使うアクションを1つにまとめておいて、それを必要な箇所で使用(再利用)することができます。

ワークフローを切り出しておけば、例えば別のリポジトリで同じような環境で開発を行ったときにそれを再利用できるという感じです。

https://docs.github.com/en/actions/creating-actions/about-actions#composite-run-steps-actions

検証環境

今回は、Laravel で構築した PHP アプリケーションの CI を回す辺りを想定してこの機能を利用してみたいと思います。

また、Github Actions では以下のチェックを走らせようと思います。

ワークフローの定義

まずは、従来の方法でワークフローを定義してみます。

今回の場合、Github Actions で CI を回す場合に必要なのは、アプリケーションのセットアップとユニットテスト用の DB のセットアップ、そして各チェックの実行です。

各チェックごとにジョブを分けて実行するとして定義すると、例えば以下のような感じになります。

laravel/.github/workflows/ci.yml

name: App check

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

jobs:
  # 構文チェック
  lint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Install Dependencies
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: lint
      run: composer lint
  # 静的解析
  analyse:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Install Dependencies
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: analyse
      run: composer analyse
  # ユニットテスト
  tests:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Install Dependencies
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: Create Database
      run: |
        mkdir -p database
        touch database/database.sqlite
    - name: Execute tests (Unit and Feature tests) via PHPUnit
      env:
        DB_CONNECTION: sqlite
        DB_DATABASE: database/database.sqlite
      run: vendor/bin/phpunit

そして CI を回すとそれらは成功します。

f:id:ro9rito:20200816090231p:plain

ただし、この yml の書き方の場合、ジョブごとに同じアプリケーションのセットアップが記述されていて冗長です。

ここを、複合ステップアクションで共通化していきます。

複合ステップアクションの作成

詳細な手順は公式に案内があります。
https://docs.github.com/en/actions/creating-actions/creating-a-composite-run-steps-action
これに沿って進めていこうと思います。

複合ステップアクションを作成するには、リポジトリが必要です。まずは、切り出すアクションを設置するためのパブリックリポジトリを作成します。

リポジトリを作成したら、そこに設置するアクションを作成します。

(ちなみに、適当に v1 というブランチを切って進めています。)

master
 \
    v1

Laravel をセットアップするアクションを定義します。

action.yml

inputs:
  name:
    description: 'Setup Laravel'
runs:
  using: "composite"
  steps:
    - name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
      shell: bash
    - name: Install Dependencies
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
      shell: bash
    - name: Generate key
      run: php artisan key:generate
      shell: bash
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
      shell: bash

アクションを作成したらリモートリポジトリへ push します。

ラベルを付与する

リモートリポジトリへブランチを push したら、プルリクを作成して、そこで「v1」というラベルを付与(無い場合は作成)します。

f:id:ro9rito:20200816090524p:plain

これで準備は完了です。(ブランチを生かしておけばプルリクはマージしても大丈夫です。)

複合ステップアクションの利用

切り出したアクションを実際に利用してみます。

laravel/.github/workflows/ci.yml

name: App check

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

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: rito328/composite-run-steps-action-laravel-setup@v1
    - name: lint
      run: composer lint
  analyse:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: rito328/composite-run-steps-action-laravel-setup@v1
    - name: analyse
      run: composer analyse
  tests:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: rito328/composite-run-steps-action-laravel-setup@v1
    - name: Create Database
      run: |
        mkdir -p database
        touch database/database.sqlite
    - name: Execute tests (Unit and Feature tests) via PHPUnit
      env:
        DB_CONNECTION: sqlite
        DB_DATABASE: database/database.sqlite
      run: vendor/bin/phpunit

Laravel のセットアップの部分をまるっと以下に置き換えています。

- uses: rito328/composite-run-steps-action-laravel-setup@v1

「 rito328/composite-run-steps-action-laravel-setup 」はリポジトリ名で「 v1 」はラベルです。(v1 とか v2 とか以外が使えるかは試していません)

冗長な記述が無くなったのでとてもすっきりしました。

これを Github Actions で動かすと、複合ステップアクションが読み込まれ、アプリケーションのセットアップやチェックも行われている事が確認できます。

f:id:ro9rito:20200816090651p:plain

アクションを分離させて再利用できました。

まとめ

ドキュメント見ながらざっと試してみました。個人的な感想としては、

  • 切り出したアクションのリポジトリが private だと利用側で読み込めなかった。それはそうかという気持ち反面、同じオーナーなら許してほしい気持ち反面。
  • ラベルつけるのが面倒。ラベル(@v1)無しでもできないのかな。

といったところでした。

とはいえ、アクションを分離できて再利用できるのはとても有用だなと思います。

同じ環境のアプリケーションがどんどん増えていくような環境下だと、再利用が捗って活躍しそうですね。

ちなみにリリースはまだファーストステップみたいで、これからも機能強化が行われていくようです。 https://github.com/actions/runner/issues/646

現場からは以上です。