2ヶ月くらい前にiOSDC 2017のプロポーザルを出したんですが、2つ出したうちの1つが採択されたので登壇してきました。
サンプルリポジトリはこちらです。資料だけだとわかりにくい部分もあると思うので、少し補足しておこうと思います。
Import Sketch Icons to Asset Catalog on CI
- Sketchからアイコンを切り出して、Asset Catalogを生成して、差分があったらiOSのリポジトリにPull Requestを出すというのをCIで自動化している話です。
- 私の所属するQuipper Limited.で実際に運用している知見です。
@konifar
- konifarという名前で、TwitterやGitHubをやっています。
- プライベートで、専業主婦の嫁さんとエンジニアリングやエンジニアの仕事に関する雑談をするyome.fmというPodcastをやっています。
- 普段はQuipper Limited.で、スタディサプリというアプリを作っています。Androidエンジニアです。
iPhone7
My first Swift!
How do you manage the icons?
- 皆さんどうやってアイコンや画像を管理してますか?たぶん大体の方はこんな感じのフローなのではないかと思います。
- まず、デザイナーさんがアイコンを作ってくれて、それをzipファイルやSketchファイル、あるいはSketchからExportしたZeplinなんかでエンジニアに渡されますよね。
- で、アイコンを受け取ったエンジニアはそれをXCode上でドラッグ&ドロップしてAsset Catalogに入れます。もしかしたら、簡単なスクリプトで組み込むようにしてるかもしれません。
- そのあと確認できたらPull Requestを出して、マージされたら晴れてiOSプロジェクトに入ります。
- だいたいこんな感じですよね。
Problems
- 別にこのやり方でもいいんですけど、いくつか問題もあります。
- まず、デザイナーさんとアイコンのやり取りするの地味にめんどくさいですよね。「アイコンください」と言ってSlackでもらっても、ちょっと後でやろうとしたらSlackでは流れてしまうし、何か間違っていた時もやりとりしなきゃいけない。
- Asset Catalogにドラッグ&ドロップするのもめんどくさいです。特に新しい機能を作ってたくさんアイコンが必要な時とか超めんどくさい。
- デザイナーさんから見ても、AndroidとiOSの両方のアイコンを管理したり、各エンジニアとやりとりするのは骨が折れるんじゃないかと思います。
Make it automatic on CI!
- 弊社Quipperでは、この流れをCIで自動化しています。
- ここからが本題です。
Overview
- ざっくり全体像を説明します。
- まず、DesignリポジトリにデザイナーさんがSketchファイルをpushします。このSketchファイルには、アプリ内で使うアイコンや画像が全て入っています。このファイルについては後で詳しく説明します。
- masterにマージされるとCIが走り、Sketch toolというのを使ってSketchファイルから画像を切り出します。その切り出した画像からAsset Catalogを生成して、差分があればPullRequestを出します。ここまでがCIで自動化されている部分です。
- あとは、そのPull Requestをエンジニアが確認してマージするだけです。
- EngineerとDesignerとのやりとりが疎になっています。距離が遠くなるというわけではなく、人間同士がやり取りしなくていいところに、間にCIに入ってもらったというわけです。
How it works?
- では、どうやって動いているのかをサンプルリポジトリを例にして少し詳しく見ていきます。
1. Push Sketch file to GitHub
- まず、デザイナーさんがDesign RepositoryにSketchファイルをpushする部分です。
images.sketch
- このSketchファイルは、実際にQuipperで運用されているものです。アプリ内で使われる画像とアイコンが全て入っています。
- それぞれのアイコンはExportの設定をしてあります。
images.sketch
- 2つだけルールを決めています。1つはネーミングルールです。
- 自動でアイコンを切り出してiOS/Androidのプロジェクトに組み込むので、このSketchファイルの段階でネーミングルールを決めておかないと後でリネームが必要になってしまいます。
- 大きく画像とアイコンの2種類があって、画像の場合は
img_
から始まる名前に統一しています。アイコンはic_
から始まるようにして、コード上でわかりやすいようにsuffixにサイズも入れるようにしています。 - また、基本的にアイコンは白色で統一しています。色をつける時はコードでTintをかけています。これは、アプリサイズを減らすためです。
git-sketch-plugin
- ここで、もしかしたら「デザイナーがGitを使えるのか?」と思う方もいるかもしれません。実際に運用してみた経験から言うと、たぶん大丈夫です。
- git-sketch-pluginというSketchプラグインがありまして、これを使うとSketchからGUIでcommitやpushといったGitの操作を行えます。
- さらにこのプラグインのよいところは、commit時にプレビューのpng画像を生成してくれるところです。Sketchファイルはバイナリファイルなので、GitHubで管理するとPullRequest時に何のアイコンが追加/編集されたのか全くわかりません。このプラグインはArtboardというSketchの中のグループのような単位でプレビュー画像を生成するので、その画像の差分を見て何が変わったのか確認できるようになります。
2. Export icons by Sketch tool
- このSketchファイルがmasterにマージされるとCIが走り、sketchtoolでアイコンがExportされます。
Sketch tool
- sketchtoolは、Sketchの各種操作をコマンドラインで実行できる最高のツールです。
- Sketch本体のツールに組み込まれていて、サンプルではinstall_sketch.shで都度インストールして使っています。
sketchtool export slices images.sketch
を実行するとoutput
オプションで指定したディレクトリにアイコン画像が切り出されます。
3. Create Asset Catalog
- 次に、切り出されたアイコンからAsset Catalogを生成する部分です。
Asset Catalog Structure is simple
- Asset CatalogはXcode上でアイコンをドラッグ&ドロップして作られますが、実際にはとてもシンプルな構成です。
Assets.xcassets
の中にアイコン名.imageset
というディレクトリが作られ、そこに解像度ごとの画像が入っています。Contents.json
というファイルもシンプルで、中には各拡張子ごとの画像の情報が記述されているだけです。
import_to_ios.sh
- import_to_ios.shの中の
export_images()
という関数で、Asset Catalogを生成しています。 - まず切り出されたアイコンを一つずつ見ていき、
アイコン名.imageset
ディレクトリを作るためにアイコン名を抽出します。 - アイコン名のsuffixが
_android
だったら処理をスキップしている部分がポイントです。アイコンの中には、Androidのみで使われるものもあります。例えば、Floating Action ButtonのアイコンはAndroidだけで用いられることがあります。これらを別ファイルで管理するのは面倒なので、「suffixが_android
だったらAndroidのみのアイコン」というルールで運用しています。 - そのチェックをくぐりぬけたら、
imageset
ディレクトリを作って中にアイコンをコピーし、Contents.jsonを生成します。
Contents.json
Vector support
- 最近では、Vector画像をそのままAsset Catalogで使えるようになりました。
- PDF形式の画像を使うのですが、sketchtoolはPDF形式のExportにも対応しているので同じような仕組みで自動化することができます。
formats
オプションにpdf
を指定し、Contents.json の生成部分も各解像度ごとではなくPDFファイル1種類のものに変えればOKです。- 実はまだサンプルリポジトリでは対応できていないので、今後やっていきます。もし興味があればPull Requestを送ってもらえるとありがたいです!
4. Send PR to iOS repository
- Asset Catalogができたら、最後はPull Requestを作る部分です。
Send Pull Request
send_pull_request()
という関数の中で、git checkout
、git add
します。何も難しいことはしていません。- ポイントは1つだけで、差分があったときのみPull Requestを送りたいので
git status --porcelain | grep $ASSETS_DIR
で変更があったかどうかをチェックしています。
5. Check and merge PR
- 変更があったらPull Requestが作られるので、あとはエンジニアがそれを確認してマージするだけです。
Pull Request
- これは実際にサンプルリポジトリで作られたPull Requestです。
Contents.json
とアイコンが追加されていることがわかります。- iOSリポジトリでCIを回してDeployGateで配信するようにしていれば、デザイナーさんだけでアイコンの変更結果を確認することも可能です。便利ですよね。
Feedbacks
- 全体の流れの説明は以上です。
- 最後に、よかったところと改善したほうがいいところをお伝えします。
Good points
- よかったところは、AndroidとiOSの画像/アイコンを一元管理できるようになったところですね。
- また、アイコン受け渡し時のデザイナーさんとのやり取りが減って、エンジニアは自動的に作られるPull Requestを見るだけでよいというのもいい感じです。
- Asset Catalogを手動でドラッグ&ドロップして作ることもないので、ヒューマンエラーも防げます(と思っていたんですが、実は登壇後に「それZeplin使っても防げるよ」とTwitterで@hirothingsさんに教えていただけました!ありがとうございます!Zeplin最高ですね)
Improvements
- 逆に改善点としては、アイコンの名前のつけ方のルールをもう少し厳密に決めておくべきだったというのがあります。例えば、検索のアイコンを追加した時に、
ic_search
とつける人もいればic_magnifying_glass
とつける人もいるんですよね。まぁどちらでもいいのですが、エンジニアからするとルールは統一しておきたいところです。アイコンの名前は形を表すものにするか、それとも役割や機能を表すものにするかを明確にしておいた方がよりコミュニケーションを減らせると思います。 - あと、たまにExportの設定を忘れたままSketchファイルをpushしてしまうことがあって、その時は当然ですが差分が出ないのでPull Requestが生成されません。「PushしたのにまだPull Requestが出ません」という無駄なやりとりが発生してしまうので、差分がなかった時はSlackなどに通知するようにした方がいいかもしれません。
- 最後に、これはできたらいいなという話なんですが、この一連のスクリプトをgemなどのライブラリにした方がCoolでしたね。他のiOSプロジェクトがどんな構成で作られているかわからなかったので今回のサンプルリポジトリでは実現できなかったのですが、今後やっていくかもしれません。sketchtoolのようなSketchプラグインでもよさそうですね。
Thanks!
- 発表は以上です。ありがとうございました。
Questions
- ここから先は当日は話しませんでしたが、質問として考えられるものを2つ書いてあります。
Which CI service is the best?
- CIサービスを選定する上では、1つだけ制約があります。
- sketchtool は macOS に依存しているので、CIもmacOSに対応しているものでないと動きません。
- 無料で対応してくいるのは、TravisCIとBitriseです。サンプルリポジトリでは、TravisCIを使っています。
- ただ、TravisCIは無料だとpublic queueが詰まって実行までに1時間くらい待たされることもあります。
- CircleCIは有料プランであればmacOS環境を使えます。
How to introduce this automation?
- この自動化を既存のプロジェクトに導入する場合、どう進めていったらいいのかという話です。
- まず、Sketchファイルを管理するデザイン用のリポジトリを作る必要があります。
- もしAndroidとiOSのリポジトリでアイコン名が統一されていなければ、リネームして揃えましょう。
- 名前が揃ったら、アイコンを1つだけ
images.sketch
に追加します。 - サンプルリポジトリを参考にして、スクリプトを作り、ローカルで実行してみましょう。
- ローカルで実行できるようになったら、CIで動くようにします。
- CIで動いたら、少しずつアイコンを
images.sketch
に追加していきます。あとは最後までやりきるだけです。
iOSDCはアウェーで緊張していたのですが、聞きに来ていただいた皆さんは非常に温かくて安心しました。iOSDC全体の感想はまた別途書こうと思いますが、まずは運営の皆さん、お疲れ様でした!聞きに来ていただいた皆さん、ありがとうございました!