どうも、けいまです。 最近は日中の暑さも和らぎ、夜は窓を開けていると涼しくていい気候になってきましたね。
さて、今回はスマホアプリの開発チームの業務改善をした話をします。
重要だけど毎回気にするほどでもないので忘れがちなタスク
例えばOSSライセンス情報のような、重要だけど毎回気にするほどでもないので忘れがちなタスクってありますよね。 「アプリ内のOSSライセンス情報の更新」などがまさしくそういったタスクだと思います。 気の利くメンバーが「ライセンス情報更新した?」と聞いてくれて初めて「アッやべぇ」と思い出したり。。。 そういったタスクはCIにやらせましょう、というのは、モバイルアプリ開発においては定番の発想であったりします。
しかし、PRのたびにライセンス情報を精査してdiffがあればDangerで警告するような対応も、 まぁ出来なくはないですが、そこまでやるほど頻繁に起こることでもないので、ずっと対応が後手に回っていました。
せっかくなので、毎週末にCIにライセンス情報更新のPRを作るところまでやって貰えたら凄くハッピーだな、と思いました。
PRをつくるのって意外と難しい!
弊社ではBitriseを3並列で運用しています(並列数のアピールは、いちおうこういうところにおカネかけてますよアピールですっ)。 Bitriseには定期実行トリガーの機能があるので、この機能を使えば定期的な実行は実現できそうです。
ところが、BitriseのstepsにはGitHubにPRを作成するstepが存在しないようです。これは困った。 別の解決方法としてはfastlaneを使う方法があるのですが、Androidプロジェクトとの兼ね合いもありRubyに依存したくなかったので断念。。。
fastlaneなどの実装からBitrise stepsを作成することも考えたのですが、そこまでやる余力はありませんでした。
GitHub Actions リリース!
そんな最中に弊社リポジトリでもGitHub Actionsが解禁されました。 バックエンドはAzure Pipelinesベースなのだとか。
まぁBitriseを辞めることは今は考えていないものの、軽量なワークフローはActionsでやらせたいね~と情報収集していたところ、 まさにずっと探し求めていたPullRequestを作成するActionがありました!
(発見当初はLinuxコンテナベースでのWorkflowにのみ対応していました。よってmacOSコンテナやWindowsコンテナでは動作しませんでした。しかし現在はベータ版扱いとしてすべてのプラットフォームで動作するようになっています)
そんなわけでせっせとWorkflowを書き、目的の動作を得ることが出来ました!
解説
name: Update licenses files on: schedule: # “At 19:00 on Friday (UTC)” -> At 05am on Saturday (JST) - cron: '00 19 * * FRI' jobs: build: runs-on: macOS-latest steps: - uses: actions/checkout@v1 - name: set up JDK 1.8 uses: actions/setup-java@v1 with: java-version: 1.8 - name: Read .node-version run: echo "::set-output name=NODE_VERSION::$(cat .node-version)" id: node - name: Use Node.js (w/ .node-version) uses: actions/setup-node@v1 with: node-version: "${{ steps.node.outputs.NODE_VERSION }}" - name: Setup yarn run: npm install -g yarn - name: yarn install run: yarn install - name: Run updateLicenses.sh run: ./scripts/updateLicenses.sh - name: Create Pull Request uses: peter-evans/create-pull-request@v1.2.1-multi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
これが我々のチームで使用しているWorkflowの現物です。 順に解説すると:
- .on.schedule[].cron
- UTCで毎週金曜日19時に実行されるようにしました。日本標準時だと土曜日の朝5時。
- .jobs.build.runs-on: macOS-latest
- 弊社アプリはReact Nativeを採用しています。よって、iOSもAndroidも面倒が見れるmacOSコンテナを使用します
- .jobs.build.steps
- Actionを記述しています。
- 前半はmacOSコンテナにないものを用意しています。
- 後半は
yarn install
した後にupdateLicenses.sh
を実行しています。 - .node-versionを読んで実際にインストールするnodeバージョンを指定するくだりはけっこうエグい感じですが、こういう感じっぽいです(記法どうにかならなかったのか?)
updateLicenses.sh
については、おおよそ以下の処理をしています。
- npmパッケージ一覧からライセンス情報を含むJSONを生成する
- iOSはCocoaPodsが
Pods-***-acknowledgements.plist
なファイルを生成しており、中にはライセンス情報が含まれているので、plutil -convert json
でJSONに変換します - Androidは cookpad/license-tools-plugin を使っているので(licenses.ymlを設定するダルさを乗り切れば)
./gradlew checkLicenses generateLicenseJson
で済みます
生成されたJSONはRN側ではファーストクラスのオブジェクトとして扱えるので、あとは煮るなり焼くなり。
peter-evans/create-pull-request
についてですが本記事を書くに当たり調査したところ、どうも REPO_ACCESS_TOKEN
は設定不要のようです。
この設定は意外と説明が面倒くさかったので、省けて良かったです。
実際の動作
さて実際の動作としては、けなげに土曜の早朝にPRをつくってくれています。カワイイ!
これで我々のチームはまたひとつ本業に専念することが出来るようになりました。。。!
Actions実装で気をつけること
Actionsを実装するうえで気をつけることとして、現時点ではいくつか問題があります。
1. HCL記法は使えず、YAML記法で書く
少し前までGitHub ActionsではHCLという記法が採用されていましたが、現在は使うことが出来ず、YAML記法のみサポートしています。 しかし、一部の古いActionのREADMEではHCL記法でのサンプルが書かれているため、読み替える必要があります。
大雑把には以下のように読み替えると良いと思います。
action "Action Name" { needs = "Master" uses = "org/repo@version" args = "branch master" }
- name: Action Name needs = "Master" uses: org/repo@version with: args: branch master
2. Docker container形式のActionはmacOS, Windowsコンテナでは動かない
ここにあるように、Actionは2種類あり、macOS, WindowsコンテナではJavaScriptで実装されたもののみ動作します。 Docker containerスタイルのものはActions実行時にエラーとなり時間の無駄になるので気をつけてください。
どうしても使いたいActionが非対応だった場合はIssueを立ててお願いしてみてもいいかも。
なお、そのActionがJavaScriptスタイルかDocker containerスタイルのどっちで実装されているかは、
リポジトリの action.yml
を確認してnodeが使われているならほぼJavaScriptスタイルだと断言できそうです。
runs: using: 'node12' main: 'index.js'
まとめ
GitHub ActionsはGitHubを使えるならみんな使える機能(のはず)なので、皆さんもGitHub Actionsで業務改善していこうな!
それでは~