📝

GithubActions初心者が調べたこと(Android)

2023/10/13に公開

はじめに

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でも指定できる。
https://github.com/actions/checkout

その後Androidのビルド環境などを設定し、下記などでビルドが出来る

ビルド
run: ./gradlew assembleDebug

お世話になった記事
https://qiita.com/hkusu/items/e48c3bebf6d15c2f126a

複数のトリガーを設定する場合

プルリクエストの起動トリガーには、開いた時、更新された時など複数の値が設定できる。
それは、[]で指定できる。

プルリクのトリガーを複数指定する
on:
  pull_request:
    types: [opened, synchronize, reopened]

一つのときも[]を付けても良い。

on:
  pull_request:
    types: [opened]

対象のブランチ名を取得する

アクションのトリガーによって異なる。
pushの場合は${{ github.ref_name }}、pull_requestの場合は${{ github.head_ref }}
マージ先やissue番号も取れる。
詳しくは下記で。
https://dev.classmethod.jp/articles/how-to-get-a-ref-branch-within-a-workflow-execution-in-github-actions/

ジョブの待ち合わせ

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]

https://blog.kondoumh.com/entry/2021/01/22/133427

並列実行

厳密には、同じような操作の並列実行で、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名 }}で呼び出せる
この例の場合、 testDebugUnitTesttestReleaseUnitTestが並列で実行される

ライブラリのアウトプットを使う

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のライブラリのアウトプットを環境変数に入れている。
https://github.com/wzieba/Firebase-Distribution-Github-Action

環境変数

環境変数には種類があり、呼び出せる場所・呼び出し方が変わる。
下記の記事にお世話になった。
https://qiita.com/chanhama/items/3f4c6461d28bdd1ae2d7
https://zenn.dev/hashito/articles/aef4de448f341b

ifと環境変数

環境変数については、ifを交えた下記記事にもお世話になった。
https://zenn.dev/matken/articles/github-actions-if-and-env

つまづき

matrixを動的に指定したい

配列のjsonを生成し、後続ジョブに渡すことで実現できる

master,developのときはrcをdeploy、releaseブランチのときはrcとreleaseをdeployする

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 }}
      ...

https://swfz.hatenablog.com/entry/2021/06/29/195359

ジョブ間で値を直接受け渡したい場合は、文字列しか出来ない

needsで待ち合わせしたジョブで、前ジョブで生成したファイルを使いたかったが、ファイルは渡せない。
文字列であればoutputに設定することで渡せる。
ファイルを渡したい場合は、uploadArtifactでGithubActionsにアップロードする必要がある。
例えば、aabを生成して複数サービスにアップロードする場合とか。
毎回ビルドしても実現できるが、時間もお金もかかる。

GithubActionsのsecretにjsonを使いたい

GithubActionsのsecret自体は文字列を指定できるのでjsonをそのまま入れられる。
しかし、Actions実行時にsecretからファイルを生成したい場合にechoで展開するのが難しい。(要エスケープな文字があるので)
また、秘匿できないケースもある模様。
https://kangetsu121.work/2023/do-not-register-structured-secret/
そのため、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。
https://github.com/cli/cli/blob/trunk/docs/install_linux.md

ghコマンドの使い方

マニュアルページがある。
例えばcreateでは別リポジトリのissueを作ることも出来る。
https://cli.github.com/manual/gh_codespace_create

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/')

https://github.com/orgs/community/discussions/26386

GithubActionsに付随して調べたこと(メモ)

sed関連

sedでファイルのテキスト置換を行う

例えば下記のようなテキストファイルを用意し、日付を後から置換する

sample.txt
### リリース日
{date}
sed -i -e "s/{date}/$(date '+%Y\/%m\/%d')/g" sample.txt
置換後のsample.txt
### リリース日
2023/10/13

https://open-groove.net/linux-command/sed-edit-files/

sedで改行を扱う

sedで改行を置換したい場合は、-zオプションを利用する

改行を@@に置換する
sed -i -z 's/\n/@@/g' sample.txt

https://webbibouroku.com/Blog/Article/sed-crlf-lf

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へのアップロード

https://qiita.com/tarumzu/items/432fc356580ebfab77d4
https://qiita.com/Slowhand0309/items/6e458dc5e5bec34e8ad5
https://zenn.dev/yass97/articles/e8d1e460ae6a59

PlayConsoleへのアップロード

https://techblog.zozo.com/entry/google-play-upload
https://zenn.dev/pressedkonbu/articles/github-actions-for-android

おわりに

今回は、GithubActions初心者のときに調べたことについてまとめました。
色々な記事にお世話になりました。
エラーになったときに何が悪いのか調べるのが大変で苦労しましたが、分かることが増えるに連れ徐々に開発スピードが上がっていきました。
この記事も、誰かの助けになれば幸いです。

Discussion