こんにちは。
GitHub Actions を使ってリリース作業を改善しました。 すぐにできるだろうと思っていたのですが、詰まることもあったため、備忘録も兼ねて記事にしました。
はじめに
Chrome拡張機能のリリース作業で、以下のような課題がありました。
- manifest.json のバージョンを手作業(シェル)で更新していた
- リリースタグを作成するため、mainやdevelop ブランチへの直プッシュを許可していた
これらの課題を解決して全体の安全性を高めつつ、リリース作業も簡略化することがゴールになります。
自動化の処理フロー(順序と連携)
manifest.jsonのバージョン更新
GitHubActionsで対象プロダクトとバージョンを選択し、manifest.jsonを更新テストの実行
manifest.json更新用のブランチであれば即成功プルリクの自動承認とマージ
テスト成功後、自動で承認→マージ→ブランチ削除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を使用
プルリクを作成する方式に変更
これらの制限を踏まえ、以下のフローで実施することにしました。
- 更新用のブランチ(auto/workflow-update-manifest)作成 ※ 毎回同じ
- そのブランチに
manifest.json
の変更を push develop
ブランチに向けてプルリク作成- CI実施後に自動承認・マージ
- 更新用のブランチを削除
この方法であれば、保護ブランチのルールを守りつつ、安全に変更を取り込むことができました
なお、プルリクは「作成者と承認者が異なる必要がある」設定にしているため、
2つのアカウントのPersonal Access Tokenを使って、プルリクの作成者と承認者を分けるようにしました。
参考リンク
2. manifest.jsonの更新プルリクの場合は即時テスト成功に
概要
- もともと存在していた CI テスト用ワークフローを改修しました。
- テスト実行には待機時間が発生するため、manifest.json のみを更新する専用ブランチ(auto/workflow-update-manifest)では、テストをスキップし即時成功とするように変更しました。
- このブランチでは manifest.json のみが対象ファイルであることが確定しているため、安全にスキップ可能です。
- その他のプルリクについては、従来どおり通常のテストを実行します。
処理フロー概要
- 実行中のブランチ名を取得
- ブランチ名が auto/workflow-update-manifest かどうかを判定
- true → 即時 OK のダミーテストを実行
- 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 の仕様による制限でした
この問題を回避するため、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の記事を書きましたが、 徐々に理解が深まり、楽しくなってきました。 今後も改善できるポイントがないか考えていこうと思います。
最後まで読んでくださりありがとうございます!
この記事を読んで興味を持って下さった方がいらっしゃればカジュアルにお話させていただきたく、是非ご応募をお願いします。