iimon TECH BLOG

iimonエンジニアが得られた経験や知識を共有して世の中をイイモンにしていくためのブログです

GitHub Actionsでリリース作業を簡略化した!

こんにちは。

GitHub Actions を使ってリリース作業を改善しました。 すぐにできるだろうと思っていたのですが、詰まることもあったため、備忘録も兼ねて記事にしました。

はじめに

Chrome拡張機能のリリース作業で、以下のような課題がありました。

  • manifest.json のバージョンを手作業(シェル)で更新していた
  • リリースタグを作成するため、mainやdevelop ブランチへの直プッシュを許可していた

これらの課題を解決して全体の安全性を高めつつ、リリース作業も簡略化することがゴールになります。


自動化の処理フロー(順序と連携)

  1. manifest.jsonのバージョン更新
    GitHubActionsで対象プロダクトとバージョンを選択し、manifest.jsonを更新

  2. テストの実行
    manifest.json更新用のブランチであれば即成功

  3. プルリクの自動承認とマージ
    テスト成功後、自動で承認→マージ→ブランチ削除

  4. mainへのマージ時にタグを作成
    mainブランチにマージされたタイミングで、manifest.jsonの差分があるプロダクトを確認バージョンを確認し、タグ作成


1. manifest.jsonのバージョンをGitHub上から実行可能

以下の仕様で対応

  • GitHub Actions の workflow_dispatch により、GitHub上から実行可能
  • 更新対象(賃貸、売買、両方)を選択
  • バージョン未指定時は、現在のバージョンのビルド番号を自動インクリメント
  • バージョン指定時に、古いバージョンや同じバージョンを設定するとエラーで終了
  • manifest.json更新用のauto/workflow-update-manifest ブランチを作成し
  • プルリクを自動生成・自動承認

実際の画面

プルリク作成

 - name: プルリク作成
  id: create_pr
  run: |
    echo "現在のブランチ: $(git rev-parse --abbrev-ref HEAD)"
    echo "変更内容:"
    git status
      PR_URL=$(gh pr create \
      --base develop \
      --title "${{ env.COMMIT_MESSAGE }}" \
      --body "manifest.json更新のGitHub Actionsにより自動生成したプルリクです")

    echo "PR_URL=$PR_URL"
    echo "PR_URL=$PR_URL" >> $GITHUB_ENV
  env:
    GH_TOKEN: ${{ secrets.WORKFLOW_PERSONAL_TOKEN }}

プルリク承認

- name: プルリクを自動でapprove
  id: auto_approve
  run: |
    echo "Approve対象: ${{ env.PR_URL }}"
    gh pr review --approve "${{ env.PR_URL }}"
  env:
    # プルリク作成者と異なるアカウントのトークン
    GH_TOKEN: ${{ secrets.APPROVE_WORKFLOW_PERSONAL_TOKEN }}

詰まづいた点

更新した manifest.json を develop ブランチに直接 push できれば良かったのですが、以下の理由により断念しました。

GitHub Actions から develop に push できない

リポジトリ自体は直プッシュ可能な設定でしたが、実際には push に失敗しました。

理由は、ブランチ保護ルール(例:1人以上の approve が必須 など)がある場合、 以下のどの方法で実施しても、保護ルールの制限によりpush は失敗しました。

  • GitHub Actions のデフォルトトークン(GITHUB_TOKEN)を使用
  • 自分の Personal Access Tokenを使用
  • 「特定ユーザーのみ直プッシュを許可」し、そのユーザーの Personal Access Tokenを使用

プルリクを作成する方式に変更

これらの制限を踏まえ、以下のフローで実施することにしました。

  1. 更新用のブランチ(auto/workflow-update-manifest)作成 ※ 毎回同じ
  2. そのブランチに manifest.json の変更を push
  3. develop ブランチに向けてプルリク作成
  4. CI実施後に自動承認・マージ
  5. 更新用のブランチを削除

この方法であれば、保護ブランチのルールを守りつつ、安全に変更を取り込むことができました なお、プルリクは「作成者と承認者が異なる必要がある」設定にしているため、
2つのアカウントのPersonal Access Tokenを使って、プルリクの作成者と承認者を分けるようにしました。

参考リンク

docs.github.com

docs.github.com


2. manifest.jsonの更新プルリクの場合は即時テスト成功に

概要

  • もともと存在していた CI テスト用ワークフローを改修しました。
  • テスト実行には待機時間が発生するため、manifest.json のみを更新する専用ブランチ(auto/workflow-update-manifest)では、テストをスキップし即時成功とするように変更しました。
    • このブランチでは manifest.json のみが対象ファイルであることが確定しているため、安全にスキップ可能です。
  • その他のプルリクについては、従来どおり通常のテストを実行します。

処理フロー概要

  1. 実行中のブランチ名を取得
  2. ブランチ名が auto/workflow-update-manifest かどうかを判定
  3. true → 即時 OK のダミーテストを実行
  4. false → 通常のテストを実行

ソース

name: Test

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
  push:
    branches-ignore:
      - 'develop'

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Check if manifest update branch
        id: branch_check
        run: |
          echo "HEAD_REF=${GITHUB_HEAD_REF}"
          if [[ "${GITHUB_HEAD_REF}" == "auto/workflow-update-manifest" ]]; then
            echo "IS_MANIFEST=true" >> $GITHUB_OUTPUT
          else
            echo "IS_MANIFEST=false" >> $GITHUB_OUTPUT
          fi

      - name: Dummy test for manifest branch
        if: steps.branch_check.outputs.IS_MANIFEST == 'true'
        run: |
          echo "Skipping tests for auto/workflow-update-manifest branch"
          exit 0


3. manifest.jsonの更新プルリクを自動承認・マージ

概要

  • テストワークフローが成功後、workflow_run イベントでこのワークフローが実行
  • ブランチ名が auto/workflow-update-manifest のプルリクの場合に以下の処理を実施

    • 自動承認
    • 自動マージ
    • ブランチ削除

ここまでの一連の流れで、manifest.json の更新をdevelopブランチに反映できるようになりました。

ソース

name: Auto Merge Manifest Update

on:
  workflow_run:
    workflows: ["Test"]
    types:
      - completed

jobs:
  auto-merge:
    runs-on: ubuntu-latest

    steps:
      - name: Check if manifest update branch
        id: branch_check
        run: |
          echo "HEAD_BRANCH=${{ github.event.workflow_run.head_branch }}"
          if [[ "${{ github.event.workflow_run.head_branch }}" == "auto/workflow-update-manifest" ]]; then
            echo "IS_MANIFEST=true" >> $GITHUB_OUTPUT
          else
            echo "IS_MANIFEST=false" >> $GITHUB_OUTPUT
          fi

      - name: Skip if not manifest update branch
        if: steps.branch_check.outputs.IS_MANIFEST != 'true'
        run: echo "Not a manifest update branch. Skipping."

      - name: Checkout
        if: steps.branch_check.outputs.IS_MANIFEST == 'true'
        uses: actions/checkout@v4

      - name: Merge PR
        if: steps.branch_check.outputs.IS_MANIFEST == 'true' &&
            github.event.workflow_run.conclusion == 'success'
        run: |
          PR_URL=$(gh pr list --head "auto/workflow-update-manifest" --state open --json url --jq '.[0].url')
          echo "Merging PR: $PR_URL"
          gh pr review --approve "$PR_URL"
          gh pr merge "$PR_URL" --merge --delete-branch
        env:
          GH_TOKEN: ${{ secrets.WORKFLOW_PERSONAL_TOKEN }}

4. 本番化のプルリクのマージ時にタグを作成

概要

ここからはmainに向けたプルリクエストのお話になります

  • mainブランチへのマージ( 本番化)をトリガーにワークフローが実行されます
  • 差分の中に manifest.json が含まれているかを確認し、賃貸・売買いずれかの変更があれば、それぞれの新しいバージョンでタグを作成します

詰まづいた点

GitHubActionsでgit tag && git pushでタグを作成したところ タグは作成できているものの、on: push.tags をトリガーとするワークフローが発火しなかった。

git tag v4.1.34-rent
git push origin v4.1.34-rent

これは GitHub Actions の仕様による制限でした

docs.github.com

この問題を回避するため、GitHub REST API 経由でタグを作成するようにしました。 この方法であれば、on: push.tags ワークフローを正しくトリガーできました

run: |
  TAG="v${{ env.rent_version }}-rent"
  curl -X POST -H "Authorization: token $WORKFLOW_PERSONAL_TOKEN" \
       -H "Accept: application/vnd.github.v3+json" \
       https://api.github.com/repos/${{ github.repository }}/git/refs \
       -d "{\"ref\": \"refs/tags/$TAG\", \"sha\": \"$(git rev-parse HEAD)\"}"

補足

GitHub Actions で git tag && git push のタグ作成で on: push.tags をトリガーに 他のワークフローを動かすことも、リポジトリの設定変更により可能でした。 ただ、以下のような 無限ループが発生する恐れがあると判断し、この方法は避けました。

  • ワークフロー A がタグを作成
  • on: push.tags をトリガーにワークフロー B が実行
  • ワークフロー B もタグを作成
  • 再びワークフロー A が発火 (以下ループ)

現状、このような構成にはなっていませんが、 今後の修正や変更で発生する可能性があるため却下しました。

まとめ

リリース作業や main ブランチへの直プッシュが可能な状態になっていた課題を、 改善することができてよかったです。

前回、今回とGitHub Actionsの記事を書きましたが、 徐々に理解が深まり、楽しくなってきました。 今後も改善できるポイントがないか考えていこうと思います。

最後まで読んでくださりありがとうございます!

この記事を読んで興味を持って下さった方がいらっしゃればカジュアルにお話させていただきたく、是非ご応募をお願いします。

Wantedly / Green

参考

保護されたブランチについて - GitHub Docs

自動トークン認証 - GitHub Docs

ワークフローのトリガー - GitHub Docs