0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GCP + ネイティブアプリでのGitLab flow構築

Last updated at Posted at 2022-07-17

はじめに

これは今さらな2021年振り返りカレンダーの2日目の記事です.
トゥイターも良かったらフォローしていただけると嬉しいです🐦

前回はCloud Run上で動くサービス用にGitHub flowでのCD環境を構築する話でした.

前回の最後やいろんな記事で述べられているとおり,GitHub flowは審査が必要なネイティブアプリなど,アプリケーションの
リリースタイミングをこちら側でコントロールできないケースで不都合が発生します(モノレポ想定です).

例えばあるアプリについて,後方互換のない新機能が入ったバージョンv2がmainにマージされ,stg環境に
上がっているとします.
この時,prdのネイティブ以外の部分でなんらかのバグが見つかり,すぐに修正を行いたいとき,通常のサービスならば,
修正PRをmainにマージし,新規機能とともにリリースすることができます.
しかしネイティブアプリの場合,アプリの審査がリリース前に挟まれるため,修正をデプロイするには,
審査を待つか,既にmainに入っている新機能をrevertするしかありません.

対策としては,ネイティブアプリのレポジトリを分けることが考えられますが,
自分のいたチームでは全員が機能開発に対してバックエンド,アプリを両方書いていたため,
PRの管理やリリースバージョンの統一が面倒になるなど別の問題が想定されました.

そこで,今回はGitHub flowをやめ,GitLab flowを採用することとしました.
GitLab flowの詳細については以下に詳しく書いてあります.

要点をまとめると以下のような感じです.

  • mainブランチに加え,環境(stg, prdなど)ごとにブランチを用意する.
  • 新規の変更はmainからブランチを切って,mainにマージする.
  • 検証環境にデプロイする際はmainをそのブランチへマージし,デプロイする
  • 検証が終わったら,検証ブランチを本番ブランチにマージし,デプロイ
  • 本番に近いブランチは,必ずその前の全ての検証ブランチを通っているようにする

仕様

今回はクライアントはiOSアプリ,バックエンドはCloud Runに乗せている形を想定します.
また,環境は一旦stg環境とprd環境の2つとします.

そして,仕様は次のような形です.

  1. 新規の変更はmainブランチから切り,mainブランチにマージ.また,検証用ブランチとしてstaging,本番ブランチとしてprductionを用意
  2. 常にmainからstgへのPRを生成し,リリースのタイミングでそれをstagingへマージし,リリースコマンドを打つ.このタイミングで,stagingからproductionへのPRを生成.
  3. staging上での検証が終わったら,stgからprdへのPRをマージ.アプリをビルドし,審査へ提出.審査にapiの変更が必要な場合はこのタイミングでデプロイ.
  4. 審査が通ったら,必要に応じてmigrationを行い,apiをデプロイ.

また,hotfixの流れは以下のような形です,

  1. stgからhotfixブランチを切り,stgにマージし動作確認.確認が終わったら,ブランチをmainとstgにマージ.
  2. stgをprdにマージし,審査&デプロイ.

実装

ディレクトリ構成は前回と同じです.
CDフローに必要なファイルなどは,release下に,環境ごとに用意します.

root/
├── .github/workflows
│  ├── release.yaml
│  ├── hotfix.yaml
│  └── prerelease.yaml
├── api
├── ui
├── release
│  ├── dev
│  └── prd
└── release.sh

新しいバージョンのリリースとstagingへのデプロイ

新規バージョンのリリースの際はまず,mainからstgingブランチへ差分をマージします.
この差分PRを常時生成するために,
git-pr-releaseを用いました.

git-pr-releaseでは,ブランチ同士を比較して,
差分がある場合はPRの自動生成と差分コミットの詳細を作ってくれます.

設定ファイルは以下のような感じです.
GIT_PR_RELEASE_BRANCH_STAGINGにはマージ元を,GIT_PR_RELEASE_BRANCH_PRODUCTIONにマージ先を設定します.
また,GIT_PR_RELEASE_TEMPLATEには生成するPRのテンプレートを設定することができます.

# prerelease.yaml
on:
  push:
    branches: [main]

jobs:
  create-release-pr:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Setup Ruby
        uses: actions/setup-ruby@v1
        with:
          ruby-version: 2.7.x

      - name: Create Staging release pull Request
        env:
          GIT_PR_RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GIT_PR_RELEASE_BRANCH_PRODUCTION: staging
          GIT_PR_RELEASE_BRANCH_STAGING: main
          GIT_PR_RELEASE_LABELS: staging
          GIT_PR_RELEASE_TEMPLATE: .github/workflows/prerelease_template
        run: |
          gem install -N git-pr-release -v "1.9.0"
          git-pr-release --no-fetch --squashed

次に,新規バージョンタグをプッシュした際の動きを実装します.
その際には以下を行います.

  • リリースノートの生成
  • stagingからproductionへのPR生成
  • staging環境へのデプロイ

リリースノートの生成は,前回と同様以下を用います.

stagingから,productionへのPR生成は,上記のrelease.yamlに以下の動作を追加し行います.

リリース用のブランチ(名前はrelease/v0.0.0)を生成したのち,そのブランチからproductionへ
向けたPRを生成しています.

# release.yaml

on:
  push:
    tags:
      - "v*"

name: Create Release

jobs:
  build:
    name: Create Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Get version
        id: get_version
        run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}

     ############### 省略 ###############
      
      # リリース用のブランチを生成
      - name: Create Release Branch
        id: create_release_branch
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          git checkout pre-production
          git checkout -b release/${{ steps.get_version.outputs.VERSION }}
          git push origin release/${{ steps.get_version.outputs.VERSION }}

     # 作成したリリースブランチからprdブランチへのPRを生成
      - name: Create Prd Release Pull Request
        id: create_release_pr
        uses: repo-sync/pull-request@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          pr_title: Production Release ${{ steps.get_version.outputs.VERSION }}
          pr_label: production-deploy
          destination_branch: production
          source_branch: release/${{ steps.get_version.outputs.VERSION }}

staging環境へのデプロイは,前回と同じく,cloud buildのトリガーを用います.
また,iosアプリの方のCDについてはまた次回以降で書く予定です.

productionへのデプロイ

productionへのデプロイは,以下の2つのステップに分かれています.

  • ネイティブアプリの審査提出
  • apiのデプロイ

ネイティブアプリの審査への提出は常に行われますが,apiのデプロイは
ケースによって審査に必須であったり必要なかったりします(バージョン整合のため).

なので,アプリの審査提出は自動化し,apiのデプロイは手動で行うこととします.

ネイティブアプリの審査提出に関しては,また次回以降で解説します.

apiのデプロイに関しては,前回と同様,release/prd下のスクリプトを叩くことで行います.

#!/bin/bash

function deploy() {
  gcloud beta builds triggers run --tag $2 service-prd-api-trigger
}

$1 $@
cd release/prd
sh deploy.sh deploy v0.0.0

これで通常のCDフローは完了です.

hotfix

次はhotfixへの対応です.
hotfixというprefixを持つブランチがpushされた時,自動でmainとstagingブランチへのPRを生成するようにします
(ぼーっとしてるとどっちかを入れ忘れるため).
コードは以下のような形です.

# hotfix.yaml
on:
  push:
    branches: ["hotfix/*"]

env:
  BRANCH_NAME: $(echo ${GITHUB_REF#refs/heads/})

jobs:
  create_hotfix_pr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Main Create Hotfix Pull Request
        id: main_create_hotfix_pr
        uses: repo-sync/pull-request@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          pr_title: "Main ${{ env.BRANCH_NAME }}"
          pr_label: "hotfix"
          destination_branch: main

      - name: Pre-Production Create Hotfix Pull Request
        id: preproduction_create_hotfix_pr
        uses: repo-sync/pull-request@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          pr_title: "Pre-Production ${{ env.BRANCH_NAME }}"
          pr_label: "hotfix"
          destination_branch: staging

これで全体の構築が完了です.

その他細かい知見など

  • git-pr-releaseはsquashマージと通常マージの両方に対応可能.
  • mainからstagingブランチへのマージをsquashにしてしまうと,リリースノートがsquashコミットだけになって
    差分の確認がしづらくなるので,ここは通常マージにしたほうが良い(めんどいので,もっといい方法ないかな...).
  • hotfixとmainでコンフリクトが起きた時の対処がよくわかっていない...

最後に

GitHub flowで起きる問題を解決した,GitLab flowの実装解説をしました.
といっても今回解説したのだと,stagingにアプリが上がってるときにhotfixが必要になった場合
またリバートしなくてはならないので,本当にこの問題を対策するときはstagingやmainへのマージを慎重に行ったり,apiデプロイするようにしたりなど追加の検討が必要そうです.
ただ柔軟性が高く拡張しやすいので,アプリならば最初から採用しておくのが楽かな〜という所感でした.

省略したアプリのCD周りなどについては,次回以降に書く予定です.

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?