Bitriseで本をビルドする #bitrise #ReView #iOSテスト全書


Bitrise Advent Calendar 8日目のかっくん(@fromkk)です。
今年の頭ぐらいから始動したiOSテスト全書でレビューを担当しました。
ようやく発送も始まったので注文済みの人は楽しみに待っていてください!

僕はレビューする際は実際にPDFの形になってる方が有難かったので、読む時は都度都度Macでビルドして本をiPhoneやiPadに転送して読んで、気になる所は印を付けて後でフィードバックする様な方法を取っていました。
ある時気付いたんですよね。

このそうそうたるメンバーが揃っていながらCI/CD出来てないとはどういう事だ!?

ただ、皆には本を書く事に集中して欲しかったのと、僕が個人で契約しているBitriseアカウントがあったので、最初は個人的な遊びとしてBitrise上でビルドする事を試みました。

前提条件

  • macOS Catalina(10.15.1(19B2106))

さすがにiOSテスト全書の環境をそのまま紹介するわけにはいかないのでTechBooster/ReVIEW-Templateをcloneして自分用にカスタマイズして利用します。
fromkk/Bitrise_Docker_Review_Sampleにサンプルを配置しておきましたので興味のある方は見ていただければと思います。

ローカル環境での動作確認

まずはDockerがインストールされている前提で話を進めます。
ReVIEW-Templateを参考にしながら docker pull vvakame/review:4.0 を実行します。
そして ./build-in-docker.sh を実行してみたところ

% ./build-in-docker.sh
+ rm -rf node_modules
+ npm install --unsafe-perm

> [email protected] postinstall /book
> bundle install

Traceback (most recent call last):
    2: from /usr/local/bin/bundle:23:in `<main>'
    1: from /usr/lib/ruby/2.5.0/rubygems.rb:303:in `activate_bin_path'
/usr/lib/ruby/2.5.0/rubygems.rb:284:in `find_spec_for_exe': Could not find 'bundler' (1.17.2) required by your /book/Gemfile.lock. (Gem::GemNotFoundException)
To update to the latest version installed on your system, run `bundle update --bundler`.
To install the missing version, run `gem install bundler:1.17.2`
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] postinstall: `bundle install`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2019-12-07T03_22_42_956Z-debug.log

とエラーが出てしまったので build-in-docker.sh ファイルを

- docker run -t --rm -v $(pwd):/book vvakame/review:4.0 /bin/bash -ci "cd /book && ./setup.sh && REVIEW_CONFIG_FILE=$REVIEW_CONFIG_FILE npm run pdf"
+ docker run -t --rm -v $(pwd):/book vvakame/review:4.0 /bin/bash -ci "cd /book && gem install bundler:1.17.2 && ./setup.sh && REVIEW_CONFIG_FILE=$REVIEW_CONFIG_FILE npm run pdf"

と書き換えて再実行。

% ./build-in-docker.sh 
Fetching: bundler-1.17.2.gem (100%)
Successfully installed bundler-1.17.2

.
.
.

INFO review-pdfmaker: uplatex -interaction=nonstopmode -file-line-error -halt-on-error __REVIEW_BOOK__.tex
INFO review-pdfmaker: dvipdfmx -d 5 -z 9 __REVIEW_BOOK__.dvi

Done.

これで ./articles フォルダの配下にPDFファイルが生成されているはずです。(config.yml に設定してある bookname がファイル名になります)
これで最低限の確認が完了です。続いてBitriseの設定に移ります。

Bitriseでビルド

普段Bitriseを利用する時は大体iOSアプリやMacのCLIアプリをビルドする為、何も考えずにMacのマシンを選んでいました。
ただ、re:viewをビルドする為にDockerを利用したかったのですが、BitriseのMacマシンにはDockerが入っていませんでした。
調べてみた所BitriseのLinuxマシンにはDockerが入っている事が分かり、先に進める事が出来ました。

セットアップ

BitriseはiPhoneやAndroidアプリをビルドする事に特化しており、セットアップも少しだけ手こずりました。

Add New App -> Add New App on web UI をクリック

公開範囲を設定

リポジトリを選択

ブランチを選択

バリデートが実行され

見事に失敗します!

iOS/Android向けのビルドじゃないので当たり前ですね。
Restart scanning without validation を選択して続けます。

無事バリデーションが完了します

OTHER/MANUAL から Android & Docker, on Ubuntu 16.04 を選択して I'm ready をクリックします。

アイコンは今は不要なので Skip してWebhookを設定します。

ようやく初期設定が完了です。 Stack を手動で設定するところが少しややこしかったですね。

とりあえずビルドを実行しますがまだ本は出来ないので Workflowを編集します。

ビルド

Workflow EditorPrimary を選択すると Do anything with Script step というステップが最初から用意されているのでここを次の様に編集します。

コードだけ抜き出すとこんな感じ

#!/usr/bin/env bash
# fail if any commands fails
set -e
# debug log
set -x

docker pull vvakame/review:4.0
./build-in-docker.sh

file_name=$(cat articles/config.yml | grep "bookname: " | sed -e s/'bookname: '/''/g)

now="$(TZ=Asia/Tokyo date +%Y%m%d_%H%M%S)"
pdf_path="$(pwd)/articles/${file_name}.pdf"

envman add --key PDF_PATH --value $pdf_path
envman add --key DROPBOX_DIR --value $now

これで実行してちゃんと動くかを確認します。

PDFの配布

deploy-to-bitrise-io ステップは失敗するので削除します。
今回は著者陣の過去の経験からDropboxでシェアする様にしました。

Dropbox consoleでアプリを作成します。
設定を進めていき OAuth 2 セクションの Generate access tokenGenerate ボタンをクリック。

表示されるトークンをコピーしてBitriseの Secrets に追加します。

Workflow EditorSend file to dropbox ステップを追加

The secret access token に先ほど設定した $DROPBOX_API_KEY を設定、Local File$PDF_PATHDropbox remote target には適当なディレクトリ名で良いのですが今回は /$DROPBOX_DIR/ を設定しました。

これでビルドすると

の様な感じでディレクトリが作成されて本が出来ていきます。
あとはSlackなどに通知を設定したりしていきましょう。

おまけ

PDFがBitriseから書き出せる様になったことで新たな要望が出てきてしまいました。

ページ数

PDFtkを利用すればページ数が取得出来ることが分かったので利用しました。

apt install -y pdftk
pages=$(pdftk $pdf_path dump_data | grep NumberOfPages)

TODOリスト

todo=$(find . -name *.re | xargs grep -n -r "#@# TODO")

TODO と書かれている箇所を探してリスト化しました。
結果は、

こんな感じです。

今日も1日餃子を食べて頑張りましょう。

もはやBitriseから実行する意義を感じなかったのでSlackで /remind "今日も1日餃子を食べて頑張りましょう。" at 8AM every day を実行しておきました。
すると翌日

まさか実行されるとは(笑)

まとめ

という事で、ただのレビュワーにも関わらず少しばかり突っ込んでプロジェクトに貢献する事が出来たかなと思います。
勿論iOSテスト全書にはCI/CDの章があり、正しいBitriseの使い方も紹介されています。
ご購入がまだで気になっている方は今からでも是非ご購入下さい!

P.S.

本を書くための環境が整ってしまった。
何か書くか。