LoginSignup
8
8

【github actions】共通するワークフローにはreusable workflowを使おう

Last updated at Posted at 2023-10-30

概要

普段CI/CD何使ってますか?
私はgithub actionsを使うことが多いのですが、その機能の中でreusable workflowという読んで字の如く、ワークフローを再利用できるものがあります。

よく使っているシーンとしては、開発環境と本番環境へそれぞれデプロイするのに、ワークフローは同じだけど環境変数が違うような場合です。
共通の部分(ワークフローの骨組み)だけをテンプレート化しておいて、必要な部分(環境変数)は呼び出し元で与える形になります。
ちょうどプログラムの関数と引数のようなイメージですね。

使い方の例

.envの内容が開発環境と本番環境で違うのはよくあることだと思います。
開発環境用と本番環境用に次のようにenvファイルを用意します。
秘匿情報であるDB_PASSWORDの値はgithub actionsのRepository secretsで指定するため、ファイル内には記載していません。

.env.dev
# 開発環境用
DB_MS=mysql
DB_HOST=192.168.10.11
DB_NAME=test_dev
DB_USER=dev
DB_PASSWORD=
.env.prd
# 本番環境用
DB_MS=mysql
DB_HOST=192.168.10.11
DB_NAME=test_prd
DB_USER=prd
DB_PASSWORD=

開発環境にデプロイする時は.env.devを、
本番環境にデプロイする時は.env.prdを使います。

呼び出される側

で、早速テンプレート(呼び出される側)です。

.github/workflows/_cd_template.yaml
name: Deploy Template

on:
  workflow_call:
    inputs:
      ENV_FILE:
        type: string
        required: true
    secrets:
      DB_PASSWORD:
        required: true

jobs:
  test-job:
    runs-on: ubuntu-latest

    steps:
      - name: Setup .env
        run: |
          cp ./${{ inputs.ENV_FILE }} ./.env
          sed -i -e 's/DB_PASSWORD=.*/DB_PASSWORD=${{ secrets.DB_PASSWORD }}' ./.env

まぁデプロイテンプレートと書きつつ、デプロイに関する内容は一切書いてないんですが、大事なのは再利用できるワークフローなのでそこは目を瞑ってもらって。
やっている内容は単純で、呼び出し元から指定されたenvファイルを.envという名前でコピーして、
.env内のDB_PASSWORD=を、呼び出し元から指定されたsecretsの値が含まれた形に置換します。

最初のこの部分が関数でいうところの言わば仮引数にあたります。
ワークフローの呼び出し元から、これらの値が渡されてjobsの中で使用されます。

on:
  workflow_call:
    inputs:
      ENV_FILE:
        type: string
        required: true
    secrets:
      DB_PASSWORD:
        required: true

呼び出す側

呼び出す側は開発環境と本番環境で2つあります。

.github/workflows/CD_dev.yaml
name: Dev Deploy

on:
  push:
    branches:
      - dev

jobs:
  CD:
    uses: ./.github/workflows/_cd_template.yaml
    with:
      ENV_FILE: .env.dev
    secrets:
      DB_PASSWORD: ${{ $secrets.DB_PASSWORD_DEV }}
.github/workflows/CD_prd.yaml
name: Prd Deploy

on:
  push:
    branches:
      - main

jobs:
  CD:
    uses: ./.github/workflows/_cd_template.yaml
    with:
      ENV_FILE: .env.prd
    secrets:
      DB_PASSWORD: ${{ $secrets.DB_PASSWORD_PRD }}

両者の内容は実行するブランチとテンプレートに渡す値が違うだけです。
下記の部分が関数でいうところの言わば実引数にあたります。

    with:
      ENV_FILE: .env.dev
    secrets:
      DB_PASSWORD: ${{ $secrets.DB_PASSWORD_DEV }}

ここでDB_PASSWORDgithub actionsのsecretsから読み込んだ値になるため、今回の場合はRepository secretsにDB_PASSWORD_DEVDB_PASSWORD_PRDを設定しておけば、それらを読み込んで、テンプレート上では同名のDB_PASSWORDという変数名で統一できます。

まとめ

ワークフローに追加や削除などの修正をしたい時、テンプレートにまとめておくことで、そのファイルのみの修正で済みます。

またAWSやGCPにデプロイするとなると、途端に環境別の変数が増えます。
CloudRunへのデプロイで言えば、プロジェクト名、リージョン、サービスアカウント、dockerイメージ名、CloudRun名などなど。
呼び出し元では「テンプレートを呼び出す」「引数を渡す」だけにしておけばそれらの見通しも良くなります。

補足

今回はRepository secrets前提でDB_PASSWORD_DEVDB_PASSWORD_PRDを設定するような形にしていますが、Environment secretsを使うことで、命名を分けずともDB_PASSWORDという同名にすることもできます(サンプル)。

またCIもテンプレート化しておいて、CD前に必ずCIを実行するというようなCI/CDパイプラインも見通しが良くなります。

jobs:
  CI:
    uses: ./.github/workflows/_ci_template.yaml
  CD:
    needs: [CI]
    uses: ./.github/workflows/_cd_template.yaml
    with:
      ENV_FILE: .env.prd
    secrets:
      DB_PASSWORD: ${{ $secrets.DB_PASSWORD }}

お試しあれ。

8
8
0

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
8
8