GithubActionsでVersionに沿ったTAG付けを自動化する
開発バージョンを固める時にcommitにTAGを打つと思いますが、あれって結構面倒ですし、 開発内容に直結しない作業なので手動管理だと忘れがちです。 でも打っておかないと後々問題があって遡る時に辛かったりします…つまりは、自動化したい作業です。
今回はこの作業をGithubActionsで自動化したのと、その際のActionやTipsの紹介です。
自動化したいこと
今回はPRで特定のブランチ(Releaseブランチとか)に変更点をマージした際、以下のことを自動的にやってほしいと思いました。
- Release用のapkをbuildする
- versionName(versionCode)でTAGを打つ
- この際、ReleaseNotes(事前に作成してGithubで管理している)の内容をコメントに転記する
- TAGの位置(GithubのRelease)にbuildしたapkをアップロードする
使用するAction
上記の内容を行うために、公式及びGitHubMarketplaceからの以下のActionを使用します。 なお、build環境の構築などは割愛します。
- GitHub - actions/create-release: An Action to create releases via the GitHub Release API
- ReleaseTAGを作る公式のAction
- GitHub - actions/upload-release-asset: An Action to upload a release asset via the GitHub Release API
- 上記Releaseの位置にアセットをアップロードする公式のAction
- Get Apk Version · Actions · GitHub Marketplace · GitHub
- apkファイルからversionName, versionCodeなどを取得するActions
- Slack Incoming Webhook · Actions · GitHub Marketplace · GitHub
- Slack連携用のAction、成否結果とリンクを通知するために使用
- Slack連携のActionは探すと色々あるので、好みのものを使用すると良いと思います
- Slack通知用のWebHookURLは先に取得してGithubのSecretに保存しておきましょう
(余談)バージョン名管理で悩んだ事
今回上記の get-apk-version
が大いに役立ちました。
これがあったからTAGの自動化に踏み切れたと言っても過言ではありません。
というのも、アプリのバージョン管理はあくまでもgradleファイルの中で管理していることであり、 なおかつ変数管理してnameとcodeを作る等の処理が入っているので、GithubActionsの環境下からどうやってそれを取得すれば良いか迷ったからです。
調べてみると、GithubActionsの中でバージョンを管理するためのActionなんかも有りましたが、 元々gradleで管理しているものをGithubActionsに移管するのは違うだろうと思い、これは辞めました。 (CircleCIもまだ併用中で、CI環境に依存する事はしたくなかった等の理由もあります)
では別途読み込ませるためのファイルを管理するか…とも思いましたが、それも面倒ですし、逆に手間が増えてしまうので、 あくまでも現状の開発フロー内でどうにか出来ないかと考えていた所、上記Actionを見つけたという経緯です。
これなら現状の開発フローに更に手作業を増やすことはなく、GithubActionsにバージョンを持ってくることが出来ました。
コマンド結果を変数に入れて活用する
get-apk-version
を使用する際に問題が発生しました。
build時にapkファイル名にバージョンを入れて出力する設定をしていたため(「v202010-release.apk」の様な感じ)、「バージョンを取得するためのActionにファイル名を入れるためにバージョンが必要」という状況が発生したのです。
これは同僚氏から「findすれば行けるのでは」とコマンド例をもらったことで解決出来ました。 最終的には以下のようにパスを変数に格納することで、他のActionに取り回せるようになりました。
- name: get file path id: find_path run: | APK_PATH=`find app/build/outputs/apk/production/release/ -name \*.apk | head -n 1` echo "::set-output name=PATH::${APK_PATH}" - name: Get Apk Version id: apk uses: JantHsueh/get-apk-info-action@1.0 with: apkPath: ${{ steps.find_path.outputs.PATH }}
変数の活用については以下のドキュメント辺りを参照すると良いと思います。 - GitHub Actionsのワークフローコマンド - GitHub Docs
Actionを使いつつ、痒いところにはコマンドを併用することで、大抵の事は出来るようになる気がします。
完成したAction
これまでの事を活用することで、build〜Slack通知までを、以下のように書くことができました。
# build - name: build apk run: | ./gradlew assembleProductionRelease # APKからバージョンを取得 - name: get file path id: find_path run: | APK_PATH=`find app/build/outputs/apk/production/release/ -name \*.apk | head -n 1` echo "::set-output name=PATH::${APK_PATH}" - name: Get Apk Version id: apk uses: JantHsueh/get-apk-info-action@1.0 with: apkPath: ${{ steps.find_path.outputs.PATH }} # Tagの作成 - name: Create Release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: v${{ steps.apk.outputs.versionNum }}(${{ steps.apk.outputs.versionCode }}) release_name: Release v${{ steps.apk.outputs.versionNum }}(${{ steps.apk.outputs.versionCode }}) body_path: LastReleaseNotes.md # apkのUpload - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ${{ steps.find_path.outputs.PATH }} asset_name: ${{ steps.apk.outputs.versionCode }}-production-release.apk asset_content_type: application/vnd.android.package-archive # Slack通知、成功時 - name: Slack Notification on SUCCESS if: success() uses: tokorom/action-slack-incoming-webhook@main env: INCOMING_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} with: text: "Release Actions Succeeded!" attachments: | [ { "color": "good", "fields": [ { "title": "GitHub Actions URL", "value": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" }, { "title": "TAG URL", "value": "${{ steps.create_release.outputs.html_url }}" } ] } ] # Slack通知、失敗時 - name: Slack Notification on FAILURE if: failure() uses: tokorom/action-slack-incoming-webhook@main env: INCOMING_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} with: text: "Release Actions Failed..." attachments: | [ { "color": "danger", "fields": [ { "title": "GitHub Actions URL", "value": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" } ] } ]
これによって、Assetを含んだReleaseTAGが自動で作成できました。
また、リンク付きのSlack通知も出来ました。(アイコンは失敗時と分けたほうが良いかも…)
この様な既存Actionが簡単に使用できる他、Slack通知に使用しているようなGithub上のリンクも取得しやすいのがとても助かる点です。失敗時のリンクを貼っておくとすぐに確認しにいけて便利で特にオススメです。
今回の事例では、Acitonとコマンドの併用について学べたのが、個人的に特にプラスになった点です。 更になんとかしたい点としては、ReleaseNotesの更新漏れをどうにか検知できないかといった点があります。これについてはおいおい考えていきたい所です。
皆さんも、GithubActionsで細かなCI課題を解決していきましょう。