AndroidアプリのQA実施に必要な作業を自動化する

こんにちは、Androidエンジニアの堀江(@Horie1024)です。VASILY DEVELOPERS BLOGは新年2回目の更新になります。ちなみに去年の更新回数は53回だったようです。

また、Androidチームのトピックスとしては、先日ベストイノベーティブアプリ大賞を受賞した際にいただいたトロフィーがオフィスに届きました。今年も賞をいただけるようVASILY全員で頑張ります。

company.vasily.jp

はじめに

Android版iQONのリリースは約1~2週間に1回行っており、リリース前には社内QAを実施しています。QAを実施するために必要な作業は定型な作業ですが、手動で行うと思いの外時間が掛かりますし、作業の抜け漏れが起きる事もあります。

そこで、タイトルにもあるようにQAの実施に必要な作業を自動化しました。一度自動化してしまえば作業に抜け漏れがなくなり、自分たちの時間も節約できます。

今回は具体的にどのように自動化したのかご紹介しようと思います。

自動化の方法

VASILYでは、以前からHeroku上にホストしたHubotSlackと連携させ利用しています。したがって、今回もSlackとHubotを使い自動化を行っていきます。Slackから特定の文字列を入力するとHubotが反応し、QA実施に必要な作業を自動的に実行するようにします。

この記事ではHerokuやHubotの設定は紹介しませんが、Web上に良い記事が多くありますので参考にしてみてください。

f:id:vasilyjp:20170119033836p:plain

QA終了までの流れの整理

まず、今までのQA開始からQA終了までの流れを整理し書き出しました。QAは毎回以下のような流れで開始され終了します。

  1. QAの開始・終了日時をSlackで全員に通知
  2. GoogleスプレッドシートでQAシートを作成
  3. Qiitaチームにリリースノートを作成
  4. APKを作成しBetaで社内に配布
  5. SlackでQA依頼
  6. QA終了日時を過ぎたらSlackにQA終了報告とお礼を投稿

次にこれらをどこまで自動化するのかを考えます。

自動化する範囲

どこまで自動化するかを考え易くするために先程整理したQAの流れをQA予告QA準備QA開始QA終了の4つのフェーズに分類してみました。

f:id:vasilyjp:20170119025651p:plain

分類する中で気づいたのは、QA準備以外のフェーズは全てSlackへの投稿という点です。これらのQA実施に関する連絡は、柔軟に対応できるようにした方が使い勝手が良さそうに思えます。

例えば、QAをお願いする時に一言添えたいかもしれませんし、QAの終了日時が伸びるかもしれません。また、QAでたくさんのフィードバックをもらえてお礼の文言を変えたい場合もあるかもしれません。

したがって、QA準備フェーズの自動化にフォーカスします。

コマンドの設計

SlackからHubotを使い自動化するには、Hubotに反応させるコマンドを決める必要があります。シンプルにandroid qaとしてみました。

Slackでandroid qaと入力するとHubotが反応し以下の作業を実行するようにします。

  1. GoogleスプレッドシートでQAシートを作成
  2. Qiitaチームにリリースノートを作成
  3. APKを作成しBetaで社内に配布

どう自動化するか?

QAシート、リリースノートの作成、APK配布を自動化するにはどうすれば良いでしょうか。各作業について考えていきます。

1. GoogleスプレッドシートでQAシートを作成

QAシートは以下のフォーマットを利用しています。

f:id:vasilyjp:20170119162027p:plain

Sheets APIを使うことでフォーマット通りのスプレッドシートを作れますが、コードが複雑になるため予め用意したスプレッドシートをマスターにし、それをDrive APIでコピーしてQAシートを作ります。

追記

マスタースプレッドシートの共有にサービスアカウントを追加する必要があります。

2. Qiitaチームにリリースノートを作成

Qiitaチームへのリリースノートの作成にはQiita API v2を使用し、POST /api/v2/itemsを使うことで投稿することができます。リリースノートのフォーマットは以下の通りで、記事のタイトルには「Android バージョン番号 リリースノート」、タグには「リリースノート」、「Android」を付けます。

# リリース日

# QA
* 期限
* QAシート

# 更新内容

タイトルのバージョン番号やリリース日、QAの期限はSlackを通じて対話的に入力できるようにします。また、更新内容にはGitHub APIのRepository/Releasesを使用し、GitHubのリリース機能で記載した内容を取得するようにします。そして、QAシートの項目には、作成したQAシートのURLを記載します。

3. APKを作成しBetaで社内に配布

AndroidチームではCIにWerckerを使用しています。以下のQiitaの記事にまとめていますが、Wercker APIでビルドを実行しAPKの作成とBetaでの配布を行います。

qiita.com

記事内でも紹介していますが、Wercker APIをHubotから使用するためのAPI ClientをOSSとして公開しています。

github.com

以下のように簡単にWercker APIを使用することが可能です。

const Wercker = require('wercker-client').default;
const wercker = new Wercker({
  token: 'your_token'
});

wercker.Runs
  .getAllRuns({applicationId: "your_application_id"})
  .then((res) => {
    console.log(res);
  }).catch((err) => {
    console.log(err);
  });

全体の流れ

Slackにandroid qaと入力してからの処理の流れを図にすると以下のようになります。

① Slackにandroid qaと入力
② Hubotが反応
③ Drive APIを使いQAシートを作成
④ Qiitaチームにリリースノートを投稿
⑤ Wercker APIを使いビルドを開始
⑥ WerckerがGitHubからアプリのコードを取得しAPKを作成
⑦ BetaでAPKを配布
⑧ 配布の完了をSlackに通知

f:id:vasilyjp:20170119143606p:plain

実装

上記の流れを実装したサンプルコードです。

github.com

サンプルコードでは以下の流れで処理を行っています。

  1. Google APIクライントの初期化
  2. android qaコマンドを定義
  3. リリースするVersion Nameを入力
  4. マスターとなるシートをコピーしてQAシートを作成
  5. QAシートのタイトルをVersion Nameを含めたタイトルに更新
  6. QAシートのアクセス権限を特定のdomainに属するアカウントのみ編集できるよう変更
  7. GitHubのrepositoryからリリースノートを取得
  8. リリース日を入力
  9. QA期間を入力
  10. リリースノートをQiitaに投稿
  11. Wercker APIを使いビルドを開始

ローカルで実行

実行中の様子はこのようになります。

f:id:vasilyjp:20170120152001g:plain

リリースノートもテンプレート通りに投稿されています。

f:id:vasilyjp:20170120153208p:plain

実装する上で困った点

Google APIクライントの初期化

HubotからDrive APIを操作するにはgoogle/google-api-nodejs-clientを使うのですが、認証・認可についての情報が少なく困りました。

手順としては、最初にAPIマネージャーからGoogle Drive APIを有効にします。

https://console.cloud.google.com/apis/api/drive/overview

f:id:vasilyjp:20170119201643p:plain

次にコンソールにアクセスし、サービスアカウント名サービスアカウントIDを入力してサービスアカウント新規作成します。役割には、スプレッドシートの編集を行う必要があるため編集者を指定します。役割の詳細はこちらから確認できます。

キーのタイプにJSONを選択し、作成をクリックするとJSONファイルがダウンロードされます。

f:id:vasilyjp:20170120192112p:plain

ダウンロードしたJSONを使用し認証・認可を行います。こちらを参考に、以下のようにgoogleapisモジュールのJWT(JSON Web Token)メソッドを使いクライアントを作成します。

JSONファイル中にclient_emailprivate_keyというフィールドがあるので、それを以下のSERVICE_ACCOUNT_EMAILSERVICE_ACCOUNT_KEYに当てはめます。

const jwtClient = new google.auth.JWT(
  SERVICE_ACCOUNT_EMAIL,
  null,
  SERVICE_ACCOUNT_KEY,
  ['https://www.googleapis.com/auth/drive'],
  null);

これでDrive APIを使用できるようになります。

SERVICE_ACCOUNT_KEYをHerokuの環境変数から読み込むとクライアントの初期化に失敗する場合があるので、以下の記事にまとめています。

qiita.com

Hubotとの対話的な入力

リリースするVersion Name、リリース日、QA期間はHubotと対話的に入力するようにしています。今回は、hubot-conversationモジュールを使用しました。

VersionNameを入力させるには以下のようなコードになります。

// Slackに通知
msg.reply("リリースするVersion Nameを入力してください。");

// Version Nameの入力を待機
var dialog = conversation.startDialog(msg);
dialog.addChoice(/([0-9]*\.[0-9]*\.[0-9]*)/, (conversationMsg) => {
  // 入力された文字の取得
  console.log(conversationMsg.match[1]);
});

Drive APIでのファイルのパーミッション変更方法

ファイルのパーミッションを変更するには、Permissionscreateメソッドを使用します。

パーミッションはroletypeの組み合わせで指定します。例えば、編集権限をvasilyドメインのユーザーに付与するなら以下のように指定します。

{
  role: "writer",
  type: "domain",
  domain: "vasily"  
}

google/google-api-nodejs-clientでは、Request Bodyをresourceパラメータで指定するのでファイルのアクセス権限を変更するコードは以下のようになります。

drive.permissions.create({auth: jwtClient, fileId: sheetsId,
  resource: {
    role: "writer",
    type: "domain",
    domain: "vasily"
  }}, (err, res) => {});

まとめ

自動化した結果、QAの準備が自動的に完了するようになりとても楽になりました。また、作業の抜け漏れも無くなりスムーズにQAを行うことができています。GitHubのリリース機能でリリース内容を書くのを忘れる事があるのが課題です。

VASILYでは一緒にサービスを開発してくれるエンジニアを募集しています。今後はiQON以外の新規サービスの開発も行う予定ですので、少しでもご興味のある方のご応募をお待ちしています。