見出し画像

立ち上げたてのAndroid プロジェクトの CIツール に GitHub Actions を試してみた!


今回のエンジニアブログは、実際の業務で使える技術的な内容「GitHub Actionsを使用したコードの書き方」をご紹介します。

■Github Actions とは?

Github上で載っているCI/CDツールで、CI/CDに必要なプロセスをアクションして定義し、使い回すことができます。※同じようなサービス、プロダクトにはCircleCIやJenkinsがありあます。

■「CI 」とは?

「継続的インテグレーション」の略で、新しく書いたコードに対して自動的にテストやビルドを実行する機能があります。大抵はCD(継続的デリバリーまたは継続的デプロイ)とセットで扱われ、プロダクトの顧客への提供プロセスを自動化する働きをしています。


なぜ試してみようと思ったのか?

もともとはCircleCIを使っていたが、以下の点でGithub Actionsを試してみたくなりました。

①ファイルパスの指定にワイルドカード(*)が使える 
→プロジェクトが多いのでCircleCIで依存関係のキャッシュのハッシュキー 用に各モジュールのGradleスクリプトを指定するのがあまりに辛かった
②テスト結果をアーティファクトとして保存するのも同様につらかった
→ もっと軽くていいのではと思った。 CircleCIで提供されるコンピューティングオプションなどが必要なほど重いことや複雑なことをCIでやってない
③CIを回さなくていい条件を指定できる
→README.md書き換えただけのときとかに回ってほしくなかった

実際に試してみたこと

ワークフローの設定ファイルを下記にコピペします。




* .github/workflows/build-and-test.yml

```yaml
name: CI with Gradle

on:
push:
  paths-ignore:
    - './*.md'
    - '**/*.md'
    - './Makefile'
    - './scripts/*'
    - './.gitignore'
    - '**/.gitignore'

env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GRADLE_OPTS: '-Dorg.gradle.daemon=false'

jobs:
build:
  runs-on: ubuntu-latest

  steps:
    - uses: actions/checkout@v2
    - name: Set up JDK 11
      uses: actions/setup-java@v1
      with:
        java-version: 11

    - name: Gradle cache
      uses: actions/cache@v2
      with:
        path: ~/.gradle/caches
        key: ${{ runner.os }}-gradle-caches-${{ hashFiles('**/*.gradle.kts', './*.gradle.kts') }}
        restore-keys: |
          ${{ runner.os }}-gradle-caches-
    - name: Gradle wrapper cache
      uses: actions/cache@v2
      with:
        path: ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-wrapper-caches-${{ hashFiles('./gradle/wrapper/gradle-wrapper.properties') }}
        restore-keys: |
          ${{ runner.os }}-gradle-wrapper-caches-
   
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    - name: Build
      run: ./gradlew :app:assembleRelease
    - name: test
      run: |
        ./gradlew :app:testReleaseUnitTest
        ./gradlew :infra:testReleaseUnitTest
        ./gradlew :domain:test
        ./gradlew :application:test
        ./gradlew :util:test
   
    - name: Upload test result
      if: always()
      uses: actions/upload-artifact@v2
      with:
        name: test-results
        path: |
          **/build/reports/tests

``
■上記の説明​
1. `on > push` でこのワークフローがリポジトリへのPushで動くようにした。
2. `on > push > paths-ignore` で 特定のファイルのみの変更の場合にこのワークフローが動かないようにした。
3. `env` で 必要なリポジトリのシークレットを環境変数にセット。
4. `actions/cache@v2`のアクションを使用してGradle周りのキャッシュの保存と読み出しを行うようにした。
5. `actions/upload-artifact@v2`のアクションを使用してテストの結果を保存するようにした。

※補足①
 `Upload test result`で`if: always()`としているが、これは前のStepの成功の可否に関わらずこのステップを実行するために指定している。
ほかにも例えば、 `if: ${{ <expression> }}` で式を当てたり、他のStepの出力(例えば`actions/cache`でキャッシュヒットしたかどうかなど)を当てたりもできる。
※補足②
 `jobs > build > runs-on` で `ubuntu-latest` の[ホストランナー]を指定しているがこのランナーには[いろいろなツール]がデフォルトでインストールされている。
Android開発に必要なAndroidSDKやNDKなど諸々も含まれている(バージョンの指定など細かい融通が利かないが、最新のものに追いついておけばとりあえず問題なさそう)


■総括

​コードベースの管理とCI/CDの管理がすべてGithub上で済むのと既存のアクションをさっと使えるのが思ったより快適でした。​
CircleCIに比べれば細かい融通が利かないところがあるが、立ち上げたプロジェクトにとりあえず使うならとても便利で良いです。

ただ、既にCIがちゃんと回ってるならこれに乗り換えるほどの理由になる特筆すべき理由はないように感じました。 (個人的には上述通りいろいろと楽な点が多いので好みです​。)

参考資料

* https://docs.github.com/ja/free-pro-team@latest/actions
* https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
* https://github.com/actions/cache/blob/main/README.md