🔥

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 authdocker build/push の中で ${{ inputs.* }} を使用

結論

この書き方をすることで重複した記述がなくなり、変更が発生した場合も環境ごとに手を動かさずに済むようになりました。

We're Hiring!

DELTAではチームの一員になっていただける仲間を募集中です!
下記フォームよりお気軽にご連絡ください!

https://docs.google.com/forms/d/e/1FAIpQLSfQuWNU1il5lq2rVdICM0tSK_jTsjqwc52LYEwUxBq7_ImtrQ/viewform

DELTAテックブログ

Discussion