Github Actionでmainマージをフックにデプロイする

BASEにいたときmainマージフックでリリースを行いたかったが、当時はGithub Actionなんてなかったし、AWSの機能も今より足りない。やりたいことをやるにはある程度自前で頑張る必要があったんだが、僕は頑張りたくなかったのである程度自動化したいと考えた。そこでSREの業務の一環ででGithub Action相当の機能を持った自前CIツールをゼロから設計・開発して運用していた。

僕の作った自前CIツール が今でも使われているかはわからないが、自前CIツールの機能の一つとしてあったmainブランチへのマージ〜アプリケーションのデプロイ処理についてはGithub Actionに挿げ替えることができる。

手元で実装検証したので書き残しておく。

Git ブランチ運用

以下の形を想定。最近の会社はどこもこんな感じだと思う。以前は間にdevelopを挟んでたりもしたが、フリーランスになってからあちこちの現場をみてきたがどこもこんな感じだった

やることのイメージとしてはCI側ではステージングは自動で、本番のリリースタイミングは手動で制御したいので、デプロイボタンだけ用意してあげる。以下はAWS環境を想定しているが、GCPでもgcloudコマンドに変わるだけなのでそれほど大した差分があるわけではない。

フロー構成

実装

上の二つの図を参考に、Github Action側はmainへのマージをフックに「productionへ向かうreleaseブランチ作成&mainからのPR作成」「ステージングリリース」「releaseブランチマージをフックにproductionリリース」の三つのステップを行う。

まずはmainマージフックにreleaseブランチ作成のymlファイルは以下。

name: git-pr-release
on:
  push:
    branches:
      - main
  workflow_dispatch:
jobs:
  git-pr-release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-ruby@v1
        with:
          ruby-version: 3.1
      - run: gem install --no-document git-pr-release
      - run: git-pr-release --squashed
        env:
          TZ: Asia/Tokyo
          GIT_PR_RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GIT_PR_RELEASE_BRANCH_PRODUCTION: production
          GIT_PR_RELEASE_BRANCH_STAGING: main
          GIT_PR_RELEASE_LABELS: pr-release
          # @note テンプレートを使う場合は以下
          # GIT_PR_RELEASE_TEMPLATE: .github/git-pr-release.erb

リリースしたい情報はenv以下に書けばOK。

次にデプロイする処理を別ファイルでymlに書く

以下は本番。

name: Deploy to Production

on:
  push:
    branches:
      - production
  workflow_dispatch:
jobs:
  build-and-publish:
    name: Build Production Image And Publush
    uses: ./.github/workflows/deploy.yml
    with:
      app-version: ${{ github.sha }}
    secrets:
      xxx: xxxxx
      #~~環境変数を追記していく~~

手動でもデプロイしたいタイミングが来るのを想定して workflow_dispachを指定しておく。これを指定しておくとGithubのActionページからいつでも走らせられるので便利。

ステージングも同様に用意する。

name: Deploy to Staging

on:
  push:
    branches:
      - "main"
  workflow_dispatch:
jobs:
  build-and-publish:
    name: Build Staging Image And Publush
    uses: ./.github/workflows/deploy.yml
    with:
      app-version: ${{ github.sha }}
    secrets:
   xxxx: xxxx

こちらはmainにマージしたらそのままreleaseブランチを作って欲しいのでそのようにする。

最後に呼び出したい共通ファイルの./.github/workflows/deploy.ymlを実装しておしまいだ。

name: Deploy

on:
  workflow_call:
    # 引数でわたすものを書く
    inputs:
      xxxxxxx:
        description: コメントを書く
        type: string
        required: true
    # 環境変数として渡すものを書く
    secrets:
      xxxxxxxxxxx:
        description: 説明
        required: true

jobs:
  build-and-publish:
    name: Build and Push docker image
    runs-on: ubuntu-latest
    permissions:
      contents: "read"
      id-token: "write"

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - id: auth
# 〜〜〜〜〜〜デプロイ処理を書く〜〜〜〜〜〜〜〜〜〜〜

あとはこれを上のブランチフローに則ってまわせばリリースフローが回るはずだ。

AWSならデプロイの箇所にECSのリリースフローを行う実装をTerraformなりAWS CDKで書いておけば自動で実行してくれる。

当時やりたかったことが何枚かのymlかくだけでできるので、便利な世の中になった。

前職の技術ブログみてきたけど今でも使われているとのこと。あれ確かRails6だった気がするが、アップデートはされているのだろうか。BASEのSREのみんなは僕のツール脱出にむけて頑張って欲しい。

まとめ

Github Action最初は実は僕批判的だったけど、最近はこれないと生きていけない。