12
16

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 Actionsで自動マージする運用

Last updated at Posted at 2025-04-21

はじめに

メグリ株式会社のモバイルアプリチームでは、以下のような Git flow もしくは GitHub flow を模したブランチ運用を採用しています。

mgre-branch.png

このブランチ管理では、main (古いリポジトリでは master) ブランチに、現在ストア公開されているアプリの内容が反映されていて、develop ブランチは開発中の最新情報が反映されるようにしています。

アプリを新しくストア申請する際には、まず releaseブランチを作成し、そのブランチ上で必要なアプリバージョンを設定して、申請用のアプリをビルドしています。

これまでアプリがストア公開された際には、releaseブランチを手動で main と develop にマージしていました。しかしリリースが頻繁になるにつれて、手動作業によるマージ漏れや遅延のリスクが無視できなくなりました。

特に、ビジネスサイドの制約でストア公開時期が変わるため、releaseブランチの作成タイミングと実際のストア公開のタイミングがズレることが頻繁にあり、マージ作業が忘れがちという問題がありました。

また、ストア公開したアプリに不具合があった場合は、mainブランチからhotfixのブランチを作成して対応するため、mainブランチは常に最新の内容が反映されている必要があります。

幸い、現在の開発フローでは、releaseブランチへのpushをトリガーとして、自動的に main ブランチへのPull Requestが作成される仕組みがあります。この仕組みをさらに発展させ、ストア公開をトリガーとして Releaseブランチを自動で main と develop にマージする運用をGitHub Actionsで実現しました。本記事ではその背景と実装の詳細を紹介します。

移行の背景と目的

移行前のフロー

手動マージには以下の課題がありました。

  • 時間的コスト: リリースの度にエンジニアや関係者の工数が発生
  • 人的ミス: マージ漏れ、タグ付け忘れ、ブランチ間違いなど
  • 属人化: 担当者による対応遅延や実施内容の差異

これらを解決するため、GitHub Actionsを利用してストア公開を監視し、対象ブランチを自動的にマージするなどのクロージング作業を自動化しました。

Play Console の API や App Store の API を利用してストア公開を検知する方法も検討しましたが、クライアントごとにアカウントの管理方法が異なり、統一的にAPIを利用することが難しかったため、定期的にストア情報をチェックする方法を採用しました。

ストア公開バージョンの取得方法

ストア公開されたアプリのバージョンを監視するため、AndroidアプリとiOSアプリのそれぞれについて、以下のようなPythonスクリプトを実装しています。

Androidアプリの場合(Google Play)

Pythonの google-play-scraper を利用して最新バージョンを取得します。

from google_play_scraper import app

def get_android_version(package_name):
    """
    Get app version from Google Play
    """
    result = app(package_name)
    return result['version']

latest_version = get_android_version('com.example.app')
print(latest_version)

iOSアプリの場合(App Store)

iTunes Search APIを利用して最新バージョンを取得します。

import requests

def get_app_version(bundle_id):
    """
    Get app version from App Store
    """
    base_url = "https://itunes.apple.com/lookup"
    params = {
        "bundleId": bundle_id,
        "country": "JP"
    }
    response = requests.get(base_url, params=params, timeout=(10.0, 10.0))
    data = response.json()
    if data["resultCount"] == 0:
        return "not_found"

    app_info = data["results"][0]
    return app_info["version"]

latest_version = get_app_version('com.example.app')
print(latest_version)

実装の詳細

実装した自動化の流れは以下の通りです。

  1. 定期的実行: 毎日決まった時刻にGitHub Actionsが起動
  2. ストアの最新バージョンを取得: 上記の方法でGoogle Play/App Storeから公開バージョンを取得
  3. releaseブランチ存在確認: 取得したバージョンのreleaseブランチのPRがGitHub上に存在するかを確認
  4. main へのマージ: 該当するPRがあれば自動でマージ
  5. develop へのマージ: main マージ成功後に自動マージ
  6. Slack通知: マージ結果をSlackに通知

主要スクリプト(概要)

自動マージの核となるスクリプト の要点は以下の通りです。

  • リポジトリをクローンして最新バージョン取得
  • 対応するreleaseブランチとPRの存在を確認
  • GitHub CLIでPRを自動マージ
  • マージ結果をSlackに通知

主要コードの抜粋

# PR番号を取得
pr_number=$(gh pr list --base $main_branch --head release/v${version} --state open --json number --limit 10 2>/dev/null | jq -r '.[0].number // empty')

# PRが見つからなかった場合の処理
if [[ -z "$pr_number" || ! "$pr_number" =~ ^[0-9]+$ ]]; then
    echo "No valid PR found."
    exit 0
fi

# PRをマージ
if gh pr merge $pr_number --merge; then
    echo "PR $pr_number merged successfully."
else
    echo "Failed to merge PR $pr_number."
    exit 1
fi

スクリプト内で参照している変数versionは前述したストア公開バージョン取得のスクリプトを利用して設定しています。

GitHub Actionsワークフローの設定

ワークフローの具体例は以下です。

  • 毎日2回ほど定期実行
  • 手動実行にも対応
  • 対象リポジトリに対してBashスクリプトを実行

主要コードの抜粋

on:
  workflow_dispatch:
  schedule:
    - cron: '0 9,21 * * *' # JSTで18:00, 6:00

jobs:
  auto-pr-merger:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: merge release PRs
      run: |
        bash run.sh
      env:
        GH_TOKEN: ${{ secrets.GH_TOKEN  }}
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL  }}

移行後のフロー

運用してみての効果

実際の運用データ

自動化システムの運用から得られたreleaseブランチ作成からストア公開完了までのリードタイムデータを分析しました。

lead_time.png

  • 平均リードタイム: 17.6日
  • 中央値: 11.0日
  • 最短: 0.2日
  • 最長: 208.3日

期間別の分布は以下の通りです:

  • 1週間以内: 36.5%
  • 1ヶ月以内: 83.7%
  • 3ヶ月以内: 98.6%
  • 3ヶ月超: 1.4%

最長のケースでは、releaseブランチ作成から実際のストア公開まで約7ヶ月の期間を要していました。

自動化により、リードタイムの長さに関わらずストア公開と同時にマージが実行されるようになりました。

また、自動化に効果として、年間を通しておおよそ1〜2人月のエンジニア工数を削減することできました。

感想

この仕組みを導入したことで、以下のようなメリットがありました。

  • 工数削減: PRをマージするタスクがなくなった(ビジネスサイドによる公開の通知、それに伴うエンジニアの手動マージ作業など)

  • 人的ミス削減: 自動化による安定運用

  • 安定した開発フロー: 常に最新の状態を保持

対応前は、ストアへの公開後にもエンジニア・ビジネスサイドの双方で追加作業が必要となっていました。特に、ストア公開のタイミングは都度異なり、申請から公開まで時間が空くことも多かったため、「いつの間にか公開されていて手続きを忘れてしまった」「久しぶりに戻って作業するのでコンテキストスイッチが大きい」といった課題が発生していました。

対応後は、エンジニア・ビジネスサイドともに、それぞれ一度の作業で完結できるようになりました。ストア公開の完了を待つ必要がなくなり、公開後の手動作業や待ち時間も発生しません。その結果、全体の工数も削減でき、何よりも「いつ作業するのか」を気にするストレスや、再度作業に戻る際の心理的な負担が大きく軽減されたと感じています。

以下の記事にも記載しましたが、これらの自動化で各種アプリの最新バージョンを把握することが容易になりました。

以下のように社内ではDocbaseとGoogleスプレッドシートに情報を集約していますが、今回の対応によって、エンジニアに限らず関係者が簡単に最新アプリバージョンを把握することができるようになりました。

image.png

image.png

まとめ

GitHub Actionsを活用することで、煩雑な手動マージ作業を効率化し、より快適な開発環境を実現できました。今後も積極的にGitHub Actionsを活用して効率化を模索していこうと思います。

お知らせ(採用情報)

メグリでは、こうした開発環境の改善や自動化、生成AIの活用に興味があるエンジニアを募集しています。
GitHub Actionsを始めとする最新技術を活用した効率的な開発環境の構築に加えて、モバイルアプリ開発、サーバサイド開発に興味がある方はぜひ以下のページをご覧ください。

カジュアル面談も随時実施していますので、お気軽にお問い合わせください。

12
16
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
12
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?