🔥
GitHub Actionsで複数環境へのデプロイを最小構成で実現する
はじめに
GitHub Actionsを使って、開発環境(dev)、ステージング環境(stg)、本番環境(prod)など複数の環境にデプロイする際、各ブランチに応じて、リソース名の環境部分(dev/stg/prod)だけを切り替えたいと思いました。
力技でやるなら各環境ごとにworkflowのファイルをつくればいいが、やっていることは共通なのでいいかんじにより少ないファイルで実現できないか?といろいろ考えて実現した方法を紹介します。
最初に結論
ワークフローは、1つの deploy.yaml と共通処理用の _deploy.yaml の2ファイルで管理するようにしました。
各ブランチに応じて使用する変数の値を切り替える方法です。
ファイルの内容
実際のファイルの中身です。
GoogleCloud用ですが、この記事では各ブランチごとに違う変数を使っているよねが伝われば幸いです。
deploy.yaml(環境ごとの呼び出し)
name: Deploy
on:
push:
branches:
- feature/sample-feature
pull_request:
branches:
- develop
types:
- closed
workflow_dispatch:
permissions:
id-token: write
contents: read
jobs:
dev:
if: github.ref == 'refs/heads/feature/sample-feature'
uses: ./.github/workflows/_deploy.yaml
with:
ENV: dev
PROJECT_ID: sample-dev
PROJECT_NUMBER: 123456789012
APP_REPOSITORY: sample-dev-app
stg:
if: github.ref == 'refs/heads/develop' && github.event.pull_request.merged == true
uses: ./.github/workflows/_deploy.yaml
with:
ENV: stg
PROJECT_ID: sample-stg
PROJECT_NUMBER: 234567890123
APP_REPOSITORY: sample-stg-app
prod:
if: github.ref == 'refs/heads/main'
uses: ./.github/workflows/_deploy.yaml
with:
ENV: prod
PROJECT_ID: sample-prod
PROJECT_NUMBER: 345678901234
APP_REPOSITORY: sample-prod-app
_deploy.yaml(共通処理の本体)
name: _Deploy
on:
workflow_call:
inputs:
ENV:
type: string
required: true
PROJECT_ID:
type: string
required: true
PROJECT_NUMBER:
type: string
required: true
APP_REPOSITORY:
type: string
required: true
env:
REGION: us-central1
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Auth
uses: google-github-actions/auth@v2
with:
create_credentials_file: true
project_id: ${{ inputs.PROJECT_ID }}
workload_identity_provider: projects/${{ inputs.PROJECT_NUMBER }}/locations/global/workloadIdentityPools/${{ inputs.PROJECT_ID }}/providers/${{ inputs.PROJECT_ID }}
service_account: github-action-deployer@${{ inputs.PROJECT_ID }}.iam.gserviceaccount.com
- name: Fetch secrets
run: |
gcloud secrets versions access latest --secret=${{ inputs.PROJECT_ID }} > ./app/.env
- name: Configure Docker
run: gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet
- name: Build and Push App Docker image
run: |
docker build --target runtime -t ${{ env.REGION }}-docker.pkg.dev/${{ inputs.PROJECT_ID }}/${{ inputs.APP_REPOSITORY }}/app-image ./app
docker push ${{ env.REGION }}-docker.pkg.dev/${{ inputs.PROJECT_ID }}/${{ inputs.APP_REPOSITORY }}/app-image
ファイル構成と役割
まずはざっくり、それぞれのファイルはこのように役割です。
- deploy.yaml :どのブランチならどのパラメータで共通処理を呼び出すか
- _deploy.yaml :実際のデプロイ処理を集約し、環境ごとの差分は
with:
で渡された変数に任せる
deploy.yaml(環境ごとの振り分け)
ここでは if:
と uses:
を使って、ブランチ名やマージ条件に応じて処理を分岐しています。
-
feature/sample-feature
に push →ENV=dev
として実行 -
develop
への pull_request が merged →ENV=stg
として実行 -
main
に merged+手動 →ENV=prod
として実行
環境ごとの差分は、定数として with:
に渡すだけなので、
「処理内容を環境ごとに書き分ける」という無駄な重複が発生しません。
_deploy.yaml(共通処理の本体)
こちらは「デプロイ手順をひたすら書くだけのテンプレート」です。
-
inputs:
でENV
/PROJECT_ID
/PROJECT_NUMBER
/APP_REPOSITORY
を外から受け取り -
gcloud auth
やdocker build/push
の中で${{ inputs.* }}
を使用
結論
この書き方をすることで重複した記述がなくなり、変更が発生した場合も環境ごとに手を動かさずに済むようになりました。
We're Hiring!
DELTAではチームの一員になっていただける仲間を募集中です!
下記フォームよりお気軽にご連絡ください!
Discussion