GithubActions初心者が調べたこと(Android)
はじめに
GithubActionsを初めて使うことになり、そのときに調べたことをまとめます。
このときの私
- Androidエンジニア
- Bitbucket pipelinesでymlを書いたことがある
- shellスクリプトはたまに使う
目的
- aabのアップロードがしたい。PlayConsole, DeployGate, FirebaseAppDistributionなど
- 結果をDangerとかSlackとかで通知したい
基本事項
ライブラリを使う
usesで使うことが出来る。
バージョンは@
文字列で指定できる
例えば、@v1
や@v2
、@v2.3.5
、リリース前であれば@コミット番号ということもある
ライブラリに引数を渡す場合は、withを用いる
- name: Checkout code
uses: actions/checkout@v4
- name: Install Ruby
uses: ruby/setup-ruby@v1.154.0
with:
ruby-version: '3.2'
bundler-cache: true
指定したブランチをチェックアウトして、Androidをビルドする
手動実行のActionsを例にする
on:
workflow_dispatch:
inputs:
ref:
description: 'branch name|tag name|commit SHA'
required: true
default: main
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Check out
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.ref }}
inputでrefを指定することで、ユーザーが実行時に入力できる。
それをactions/checkoutにrefという引数で渡す。
このrefはブランチ名、タグ名、コミットSHAでも指定できる。
その後Androidのビルド環境などを設定し、下記などでビルドが出来る
run: ./gradlew assembleDebug
お世話になった記事
複数のトリガーを設定する場合
プルリクエストの起動トリガーには、開いた時、更新された時など複数の値が設定できる。
それは、[]
で指定できる。
on:
pull_request:
types: [opened, synchronize, reopened]
一つのときも[]
を付けても良い。
on:
pull_request:
types: [opened]
対象のブランチ名を取得する
アクションのトリガーによって異なる。
pushの場合は${{ github.ref_name }}
、pull_requestの場合は${{ github.head_ref }}
。
マージ先やissue番号も取れる。
詳しくは下記で。
ジョブの待ち合わせ
needsを使って、ジョブを指定する。
例えば、ユニットテストが通ったら、apkを生成するとか。
jobs:
unit-test:
name: unit-test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Unit test
run: ./gradlew testDebugUnitTest --continue
build-aab:
name: build-aab
needs: unit-test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Execute Gradle assemble
run: ./gradlew bundleRelease
needsを複数指定することも出来る
needs: [unit-test, lint-check]
並列実行
厳密には、同じような操作の並列実行で、matrixを使うと実現できる。
jobに対して指定するもので、stepの途中で並列とかは出来ない(?)
外部ファイルに切り出せば出来るのかもしれない(?)
詳しい人がいたら教えていただきたい。
jobs:
unit-test:
name: unit-test
runs-on: ubuntu-latest
strategy:
matrix:
variant: [ Debug, Release ]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Execute Gradle test
run: ./gradlew test${{ matrix.variant }}UnitTest --continue
${{ matrix.matrix名 }}
で呼び出せる
この例の場合、 testDebugUnitTest
とtestReleaseUnitTest
が並列で実行される
ライブラリのアウトプットを使う
idを付けることで、steps.id.outputs.xxxで参照できる
- name: Upload aab to Firebase App Distribution
id: firebase_app_distribution
uses: wzieba/Firebase-Distribution-Github-Action@1.7.0
- name: Set firebase url to env
run: echo "FIREBASE_URL=${{ steps.firebase_app_distribution.outputs.TESTING_URI }}" >> $GITHUB_ENV
これは、FirebaseAppDistributionのライブラリのアウトプットを環境変数に入れている。
環境変数
環境変数には種類があり、呼び出せる場所・呼び出し方が変わる。
下記の記事にお世話になった。
ifと環境変数
環境変数については、ifを交えた下記記事にもお世話になった。
つまづき
matrixを動的に指定したい
配列のjsonを生成し、後続ジョブに渡すことで実現できる
name: Deploy
on:
push:
branches:
- master
- develop
- 'release/**'
jobs:
prepare-matrix-values:
runs-on: ubuntu-latest
outputs:
matrix_values: ${{ steps.set-matrix.outputs.value }}
steps:
- name: make matrix
id: set-matrix
run: |
if [[ ${{ github.ref_name }} == release/* ]]; then
MATRIX=[\"rc\",\"release\"]
else
MATRIX=[\"rc\"]
fi
echo "value=$(echo "$MATRIX" | jq -c)" >> $GITHUB_OUTPUT
deploy:
needs: prepare-matrix-values
name: deploy
runs-on: ubuntu-latest
strategy:
matrix:
variant: ${{ fromJson(needs.prepare-matrix-values.outputs.matrix_values) }}
steps:
- run: echo ${{ matrix.variant }}
...
ジョブ間で値を直接受け渡したい場合は、文字列しか出来ない
needsで待ち合わせしたジョブで、前ジョブで生成したファイルを使いたかったが、ファイルは渡せない。
文字列であればoutputに設定することで渡せる。
ファイルを渡したい場合は、uploadArtifactでGithubActionsにアップロードする必要がある。
例えば、aabを生成して複数サービスにアップロードする場合とか。
毎回ビルドしても実現できるが、時間もお金もかかる。
GithubActionsのsecretにjsonを使いたい
GithubActionsのsecret自体は文字列を指定できるのでjsonをそのまま入れられる。
しかし、Actions実行時にsecretからファイルを生成したい場合にechoで展開するのが難しい。(要エスケープな文字があるので)
また、秘匿できないケースもある模様。
そのため、base64を使うのが良い。
secretにはbase64エンコードした文字列を登録し、それをstep内でjsonにする。
run: echo "${{ secrets.BASE64_JSON }}" | base64 --decode > hoge.json
Rubyのbundle installが失敗する
下記のようなメッセージが出る場合
Your bundle only supports platforms..
Gemfile.lockのPLATFORMSに記載が足りないため、エラーに言われたplatformを追記する。
ghコマンドをインストールしたい
GithubCliのページにOSごとのインストールガイドがある。
例えばLinux。
ghコマンドの使い方
マニュアルページがある。
例えばcreateでは別リポジトリのissueを作ることも出来る。
if内で関数を使う場合の注意点
前述のifと環境変数
の記事でも書かれているが、注意点がある。
# OK
if: ${{ !startsWith(github.event.inputs.from_branch, 'release/') }}
# NG
if: !startsWith(github.event.inputs.from_branch, 'release/')
# OK
if: ${{ startsWith(github.event.inputs.from_branch, 'release/') }}
# NG
if: startsWith(${{ github.event.inputs.from_branch }}, 'release/')
GithubActionsに付随して調べたこと(メモ)
sed関連
sedでファイルのテキスト置換を行う
例えば下記のようなテキストファイルを用意し、日付を後から置換する
### リリース日
{date}
sed -i -e "s/{date}/$(date '+%Y\/%m\/%d')/g" sample.txt
### リリース日
2023/10/13
sedで改行を扱う
sedで改行を置換したい場合は、-zオプションを利用する
sed -i -z 's/\n/@@/g' sample.txt
gh関連
ghコマンドでテンプレートからissueを選び、置換して作成したい
仕様上、作成済みのテンプレートから選ぶだけで、テンプレートを選んだ上で置換するのは難しい。
そういうことがしたい場合は、Githubのテンプレートからではなく、自前でtxtを用意し、置換した上で--body
に指定するのが良さそう。
前述のsedと合わせると下記のようになる。
- name: Prepare issue body
run: |
sed -i -e "s/{date}/$(date '+%Y\/%m\/%d')/g" sample.txt
- name: Create release note
run: gh issue create -t "sample" -b "$(cat sample.txt)" > issue_output.txt
なお、gh issue create
のアウトプットには、作成されたissueのURLが入っている。
Androidに関して
FirebaseとPlayConsoleへのアップロードで、下記の記事にお世話になった。
FirebaseAppDistributionへのアップロード
PlayConsoleへのアップロード
おわりに
今回は、GithubActions初心者のときに調べたことについてまとめました。
色々な記事にお世話になりました。
エラーになったときに何が悪いのか調べるのが大変で苦労しましたが、分かることが増えるに連れ徐々に開発スピードが上がっていきました。
この記事も、誰かの助けになれば幸いです。
Discussion