OTOBANK Engineering Blog

オトバンクはコンテンツが大好きなエンジニアを募集しています!

GitHub Actionsで業務を効率化する ~OSSライセンス情報の自動反映 編~

どうも、けいまです。 最近は日中の暑さも和らぎ、夜は窓を開けていると涼しくていい気候になってきましたね。

さて、今回はスマホアプリの開発チームの業務改善をした話をします。

重要だけど毎回気にするほどでもないので忘れがちなタスク

例えばOSSライセンス情報のような、重要だけど毎回気にするほどでもないので忘れがちなタスクってありますよね。 「アプリ内のOSSライセンス情報の更新」などがまさしくそういったタスクだと思います。 気の利くメンバーが「ライセンス情報更新した?」と聞いてくれて初めて「アッやべぇ」と思い出したり。。。 そういったタスクはCIにやらせましょう、というのは、モバイルアプリ開発においては定番の発想であったりします。

しかし、PRのたびにライセンス情報を精査してdiffがあればDangerで警告するような対応も、 まぁ出来なくはないですが、そこまでやるほど頻繁に起こることでもないので、ずっと対応が後手に回っていました。

せっかくなので、毎週末にCIにライセンス情報更新のPRを作るところまでやって貰えたら凄くハッピーだな、と思いました。

PRをつくるのって意外と難しい!

弊社ではBitriseを3並列で運用しています(並列数のアピールは、いちおうこういうところにおカネかけてますよアピールですっ)。 Bitriseには定期実行トリガーの機能があるので、この機能を使えば定期的な実行は実現できそうです。

ところが、BitriseのstepsにはGitHubにPRを作成するstepが存在しないようです。これは困った。 別の解決方法としてはfastlaneを使う方法があるのですが、Androidプロジェクトとの兼ね合いもありRubyに依存したくなかったので断念。。。

docs.fastlane.tools

fastlaneなどの実装からBitrise stepsを作成することも考えたのですが、そこまでやる余力はありませんでした。

GitHub Actions リリース!

そんな最中に弊社リポジトリでもGitHub Actionsが解禁されました。 バックエンドはAzure Pipelinesベースなのだとか

まぁBitriseを辞めることは今は考えていないものの、軽量なワークフローはActionsでやらせたいね~と情報収集していたところ、 まさにずっと探し求めていたPullRequestを作成するActionがありました!

github.com

(発見当初は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 は設定不要のようです。 この設定は意外と説明が面倒くさかったので、省けて良かったです。

github.com

実際の動作

さて実際の動作としては、けなげに土曜の早朝にPRをつくってくれています。カワイイ!

f:id:p-side:20191009010328p:plain

これで我々のチームはまたひとつ本業に専念することが出来るようになりました。。。!

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コンテナでは動かない

help.github.com

ここにあるように、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で業務改善していこうな!

それでは~

はじめてのミューテーション解析 / Mutation testing

こんにちは! 今月から 2 名のエンジニアの仲間が増え、歓迎のために東京に来ている @riaf です。暑くて死にそう!

本日もまた社内勉強会のレポートでございます。

いま PHP 界隈では、mutation testing が熱い! というタイトルで id:sasezaki 先生がお話してくれました。

というのも、近年カンファレンスでも mutation testing がテーマになっている話も増えているということや、数年前にWEB+DB PRESS で PIT が紹介されるなど、界隈で話題になっているという流れがあるそうですが...

さて、ミューテーション解析って何なんでしょう。ミューテーション解析 (mutation testing) とは、テストスイートの完全性を判定する手法の一つで、簡単にいうと「わざとバグがある状態のプログラムに変更して、そのコードに対するテストがちゃんと失敗するかどうか」を確認することで、テストが足りているかを測定しようということですね。

この辺り、ミューテーション解析というかミューテーションテストというか、Mutation analysis というか Mutation testing というかでやや異なる意味を持つみたいですが、今回のお話では「ミューテーション解析 / Mutation testing」が広く認識されているということで、まあ、詳しい話がきになる方はぜひ調べてみていただくということで何卒…。

では早速、PHP におけるミューテーション解析を試していきましょう。 今回使用するのは Infection - Mutation Testing framework というツールです。

続きを読む

【社内勉強会】イケてるコードを書きたいんじゃぁ~~~ _(:3」∠)_

こんにちは、エンジニアのs4kr4です。

今回の勉強会は、keima氏による

「イケてるコードを書きたいんじゃぁ~~~ (:3」∠)

です。 資料はこちら
※ 内容はあくまでも登壇者の一意見です

イケてるコード

みなさんは「楽しくプログラミング」していますか?

エンジニアの本職はコードを書くことなわけですが、せっかくなら「楽しく」「イケてる」コードを書きたいですよね。

どんなコードが「イケてる」のか、というとまたいろいろ意見が分かれると思いますが、今回挙げられたポイントは以下の4点。

  • 優れた設計
  • 少ないコードで多くの解決
  • テクニック
  • 困難な課題を解決する

優れた設計

「どんな設計が優れているか」というのは、時代によっても案件の規模によっても違ってきます。
案件の規模によって最適なアーキテクチャを選択できるように、普段から(雰囲気だけでも)様々なアーキテクチャに触れておくことが大事です 💪

少ないコードで多くの解決

同等の動作を短いコードで実現できるなら、積極的にそうするべきではあります。
しかしワンライナーに近いような短すぎるコードになると、今度は可読性などの観点で良くないコードになってしまいます。

一連の処理に名前をつけて関数に切り出すなどして、コードの情報量(エントロピー)を適切にコントロールできるようになりましょう👨‍🏫

テクニック

いわゆるハック的な話ではなく、どんな知識でも思わぬ場面で役に立つことがあるよ、というお話でした。

keima氏の実体験として、カメラアプリ開発時の端末の発熱問題への対策に、それ以前に読んだモバイルゲーム開発時の熱対策に関する記事が参考になったということがあったそうです。

様々なものに関心を持ち、情報を収集していれば、いつかどこかで使える日が来るかもしれません。

困難な課題を解決する

まだ自分も他人もやったことがないこと、業界内でも先進的なこと、経験したこともない大規模な案件などなど……
仕事をする中で、こうした困難にぶち当たることは度々あるでしょう。
ではどういった心持ちでこのような問題に望めば良いのでしょうか?

まず多くの人は、こうした問題にはできるだけ立ち向かわない方が良いとのことでした。
もし問題が解決できたとしても、その過程でいたずらに肉体や精神を消費してしまうのはあまりよくありません。

それでも問題に立ち向かっていきたい・立ち向かう必要がある場合は、それ一辺倒の生活を過ごすことはせず、必ず逃げ道を作っておきましょう🏃🏃🏃
また、その課題を達成した暁には、必ずそれに見合った評価を得られるように外堀を固めていきましょう。

チームにそういった雰囲気が醸成されていけば、もっともっと仕事が楽しくなり、気軽にコードレビューもできるようになり、プロダクションにイケてるコードがガンガン乗るようになるのかもしれません(最後無理やり繋げた感)


以上です。次回の記事もお楽しみに〜👋