13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub Action の workflow_dispatchを用いたmonorepoの部分デプロイ

Last updated at Posted at 2024-12-09

はじめに

この記事は Wano Group Advent Calendar 2024 の10日目の記事です。

本稿では、私たちのチームが GitHub Actions を使用してどのようにデプロイを実施しているかについて記載します。

Goのモノレポ構成について

私たちのチームでは、Go言語を中心として利用しており、モノレポ(monorepo)で管理しています。この構成に至るまでには様々な試行錯誤があり、以下のような特徴を持つ構成へと発展させてきました。

リポジトリの基本構造

projectフォルダの下に各モジュールが並んでいます。
それぞれgo.modを持っています。

project
├── README.md
├── zzzz
├    ├── go.mod
├── yyy
└── zzzz

マイクロサービスを進めていたり分散モノリス化してしまっているわけではなく、純粋にデプロイライフサイクルの違うアプリケーション群をある程度の論理的な塊感を持って分けています。

業務ドメインロジックとの関わりが深いものに関しては、npmモジュールやPythonなどの非Goプロジェクトも含むこともあります。
(あまりにもデプロイライフサイクルの違うものや、非機能的な非ドメイン要素に属するものは別のリポジトリで管理しています。)

workflow_dispatchとは

デプロイにはGitHub Actionsの機能であるworkflow_dispatchGitHub CLI経由で実行しています。

workflow_dispatchは、GitHub Actionsの機能の一つで、手動でワークフローを実行できる仕組みです。この機能の特徴は、

  • 実行時にパラメータを渡すことが可能
  • 特定のブランチやタグを指定してデプロイできる
  • 複数のワークフローを連携させやすい

この柔軟性により、モノレポ内の特定のプロジェクトを選択的にデプロイすることが可能になります。

実際のデプロイフロー

実際のデプロイは、GitHub CLIを使用して以下のように実行しています。

gh workflow run deploy -r <branch/tag> --field env=<production/stage> --field app=<対象の傘下プロジェクト>

例えば、ABCという3つのデプロイ論理単位があり、Aだけデプロイする場合、以下のようにデプロイします。

gh workflow run deploy -r feature/add-emoji-deploy --field env=stage --field app=A

このコマンドにより、特定のブランチから特定の環境に、選択したプロジェクト群のみをデプロイしています。

GitHub CLIで発火されているものはなにか

上記のコマンドを受けるworkflow側では、以下のように、親/イベント起点となるdeploy.ymlとそれによって呼ばれる_call.deploy_A.ymlのようなデプロイ単位によって別れています。

どれを発火させるか決めるのはdeploy.ymlであり、_call.deploy_A.ymlなどは個別のデプロイジョブの単なる集合体となっています。

.github
├── actions
│   └── shared-action
├── pull_request_template.md
└── workflows
    ├── _call.deploy_A.yml
    ├── _call.deploy_B.yml
    ├── _call.deploy_C.yml
    ├── _call.deploy_OTHER.yml
    ├── deploy.yml
    ├── set-aws-deploy-secrets-dispatch.sh
    └── test-result-slack.yml

親となるGitHub Action

.github/deploy.yml
name: 'deploy'
run-name: デプロイ ${{ github.event.inputs.env }} by @${{ github.actor }} ( ${{ github.event.inputs.app }} )

on:
  workflow_dispatch:
    inputs:
      env:
        description: 'production / stage'
        required: true
      app:
        description: 'デプロイ対象'
        default: 'A,B,C,OTHER'

env:
  # 組織シークレット
  ...


jobs:

  call_A:
    uses: ./.github/workflows/_call.deploy_A.yml
    if: contains(github.event.inputs.app, 'A')
    with:
      MY_ENV: ${{ github.event.inputs.env }}
    secrets: inherit

  call_B:
    uses: ./.github/workflows/_call.deploy_B.yml
    if: contains(github.event.inputs.app, 'B')
    with:
      MY_ENV: ${{ github.event.inputs.env }}
    secrets: inherit

  call_C:
    uses: ./.github/workflows/_call.deploy_OTHER.yml
    if: contains(github.event.inputs.app, 'OTHER')
    with:
      MY_ENV: ${{ github.event.inputs.env }}
    secrets: inherit

  call_OTHER:
    uses: ./.github/workflows/_call.deploy_C.yml
    if: contains(github.event.inputs.app, 'C')
    with:
      MY_ENV: ${{ github.event.inputs.env }}
    secrets: inherit

  on-request:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v4

      - name: Dump GitHub context
        env:
          GITHUB_CONTEXT: ${{ toJSON(github) }}
        run: echo "$GITHUB_CONTEXT"

      - name: Slack Notification
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_WEBHOOK: ${{ env.MY_SLACK_WEBHOOK_DEPLOY }}
          SLACK_TITLE: 🦾 A デプロイ開始  ${{ github.event.inputs.env }}
          SLACK_COLOR: '#6f7a72'
          SLACK_MESSAGE: |
            env : ${{ github.event.inputs.env }}
            app : ${{ github.event.inputs.app }}

  on-result:
    runs-on: ubuntu-20.04
    needs: [call_A, call_B, call_OTHER , call_C , ]
    if: ${{ always() }}
    steps:
      - name: checkout
        uses: actions/checkout@v4
      - name: Dump GitHub context
        env:
          GITHUB_CONTEXT: ${{ toJSON(github) }}
        run: echo "$GITHUB_CONTEXT"

      - name: Slack Notification
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_WEBHOOK: ${{ env.MY_SLACK_WEBHOOK_DEPLOY }}
          SLACK_TITLE: 🚀 A  ${{ github.event.inputs.env }} デプロイ結果
          SLACK_COLOR: '#42555c'
          SLACK_MESSAGE: |
            対象ワークフロー
            
            A: ${{ needs.call_A.result == 'success' && '✅' || needs.call_A.result == 'skipped' && 'skipped' || '🔥' }}
            B: ${{ needs.call_B.result == 'success' && '✅'  || needs.call_B.result == 'skipped' && 'skipped' || '🔥' }}
            OTHER: ${{ needs.call_OTHER.result == 'success' &&  '✅' || needs.call_OTHER.result == 'skipped' && 'skipped' || '🔥'  }}
            C: ${{ needs.call_C.result == 'success' && '✅' || needs.call_C.result == 'skipped' && 'skipped' || '🔥'  }}


if: contains(github.event.inputs.app, 'B') この if構文が特徴で、これによってGutHub CLIからのデプロイ命令をフィルタしています。

上記のdeployによって呼ばれる子YAMLは以下です。
workflow_callでいくつかのオプション等を受け取れる他は普通のjobの羅列ですので割愛します。

.github/workflows/_call.deploy_C.yml
name: _call.B

on:
  workflow_call:
    inputs:
      ENV:
        required: true
        type: string

env:
  REGION: ap-northeast-1          
....

jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 12
    env:
      GOCACHE: /tmp/.cache-go
    strategy:
      matrix:
        environment:
            - TITLE: (1) xxxxxx
              DEPLOY: |
....

最後に - GitHub Actions × モノレポの評価

1年ほどGitHub Actionでこのデプロイ方法を運用してきてどうだったか。

メリット

  1. コードの一元管理

    • 全てのプロジェクトが1つのリポジトリに集約され、依存関係の把握が容易
    • デプロイスクリプトの共通化が可能
  2. 開発効率の向上

    • プロジェクト間の変更の影響を即座に確認可能
    • 共通コードの更新が一括で行える

デメリット

  1. キャッシュの制限

    • エンタープライズプランでも1リポジトリあたり10GBという制限
    • 大規模なモノレポではすぐに限界に達する可能性
  2. 対策

    • 頻繁なリリースが必要なプロジェクトを特定し、優先的にキャッシュを活用
    • 必要に応じてキャッシュのクリーンアップを実施

...キャッシュ周りがなんかもうちょっとならないかなあ、という感想ですね。
簡単ですが本稿を終わります。

明日はnokaznさんです。乞うご期待。

13
0
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
13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?