Push時はCIのみ、Merge時はCIおよびCDを実行するGitHub Actionsを作る(Workflowの再使用)

2022.04.19

こんにちは、CX事業本部 IoT事業部の若槻です。

GitHubのPull Requestを使用した開発で、次のトリガーでCI/CDを実行するWorkflowをよく組みます。

  • BranchのPush時:CI(ビルドおよびテスト)のみ実行
  • Pull RequestのMerge時:CIおよびCD(デプロイ)を実行

今回は、Push時はCIのみ、Merge時はCIおよびCDを実行するWorkflowを、GitHub ActionsのWorkflowの再使用で作ってみました。

Workflowの再使用

Push時とMerge時に実行されるWorkflow fileをそれぞれ作ることになるのですが、同じCI処理をそれぞれで実行したい場合は、記述を分けると2重管理となってしまいます。処理の修正時に抜け漏れも発生しかねません。

このような場合にWorkflowの記述の2重管理を避ける方法として、Workflowの再使用という機能があります。

この機能は2021年11月にGAとなった機能です。

使い方としては、Workflowを再使用される側では、トリガーにworkflow_callを指定します。

on:
  workflow_call:
    inputs:
      username:
        required: true
        type: string
    secrets:
      envPAT:
        required: true

Workflowを再使用する側では、使用したいWorkflowファイルをパスで指定します。

jobs:
  reusable_workflow_job:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: ./.github/workflows/my-action
        with:
          username: ${{ inputs.username }}
          token: ${{ secrets.envPAT }}

これにより、「再使用する側」のWorkflowから「再使用される側」のWorkflowを呼び出して使用することができます。よって「再使用する側」をMerge時のみ、「再使用される側」をMerge時とPush時にトリガーされるようにすれば、記述の2重管理を回避できます。

やってみた

Workflow fileの作成

下記のような2つのWorkflow fileを作成します。ここではAWS CDkプロジェクトを管理するRepositoryを対象としたWorkflowです。

ci.yamlでは、Dependencyのキャッシュのリストア、Dependencyのインスール、テストを行います。トリガーは再使用時(on:workflow_call)またはmainブランチへのPush時(on:push branches-ignore:main)としています。

.github/workflows/ci.yaml

on: 
  workflow_call:
  push:
    paths-ignore:
      - '**/*.md'
    branches-ignore:
      - main

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Cache CDK Dependency
        uses: actions/cache@v3
        id: cache_cdk_dependency_id
        env:
          cache-name: cache-cdk-dependency
        with:
          path: node_modules
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}
          restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}-

      - name: Install CDK Dependency
        if: steps.cache_cdk_dependency_id.outputs.cache-hit != 'true'
        run: npm install

      - name: CDK Test
        run: npm run test

cd.yamlでは、AWSの認証、Dependencyのキャッシュのリストア、およびデプロイを行います。トリガーはmainブランチへのMerge時としています。

.github/workflows/cd.yaml

on: 
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

env:
  AWS_OIDC_ROLE_ARN: ${{ secrets.AWS_OIDC_ROLE_ARN }}
  AWS_REGION: us-east-1

jobs:
  ci-reuse:
    uses: ./.github/workflows/ci.yaml

  cd:
    runs-on: ubuntu-latest
    needs: ci-reuse
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Assume Role
        uses: aws-actions/configure-aws-credentials@v1
        with:
          role-to-assume: ${{ env.AWS_OIDC_ROLE_ARN }}
          aws-region: ${{env.AWS_REGION}}

      - name: Cache CDK Dependency
        uses: actions/cache@v3
        id: cache_cdk_dependency_id
        env:
          cache-name: cache-cdk-dependency
        with:
          path: node_modules
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}

      - name: Deploy
        run: npm run deploy

動作確認

Pushをすると、CIのみが実行されました!

Mergeをすると、CIおよびCDが実行されました!ci-reuse

ハマった箇所

Workflow fileのパス指定の記述

再使用する側のWorkflowを実行すると、次のようなエラーが発生しました。

invalid value workflow reference: no version specified

image

再使用したいWorkflow fileのパスの指定の記述が誤っていました。

誤ったパス指定

jobs:
  ci-reuse:
    uses: .github/workflows/ci.yaml

正しいパス指定

jobs:
  ci-reuse:
    uses: ./.github/workflows/ci.yaml

おわりに

Push時はCIのみ、Merge時はCIおよびCDを実行するWorkflowをGitHub Actionsで作ってみました。

今まで「Push時はCIのみ、Merge時はCIおよびCDを実行する」という処理を重複なく記述することは出来そうで出来なかった(頑張ればできた?)ため、仕方なく記述の2重管理をしていましたが、これからはWorkflowの再使用を活用してそれともおさらば出来ますね。

参考

以上