Pastalablog in はてな

時代はブログ! 日記もあるよ→http://pastak-diary.hatenadiary.com

ChromeExtensionの自動ビルドと自動リリースの話

Chrome Extension を作っている人は多いと思うのですが、プロダクトの1つとして作っていたりすると、他のアプリケーションなどと同様に自動ビルドや自動リリースを整えたいと思うのが人情だと思います。

先日、その辺りの仕組みをgyazo/gyazo-chrome-extensionリポジトリで利用したいと思ったので、シュッと整えたり、それに際して幾つか便利なツールを実装したりしたので紹介します。

自動ビルド

Chrome Extensionもユーザーからバグ報告があります。コードの上のバグだと検出出来たりするのですが、Extensionの場合はUI上の不具合の割合が多く、たまにWindowsとか特定の環境やバージョンでしか再現性のないバグがあったりすると手元の環境で再現するのが大変なので、再現できる人にチェックをお願いしたりすることになると思います。

この時、相手がエンジニアだったらリポジトリをcloneして頂いて動作確認していただくとか、そうでなければGitHubなどからzipを手元で解凍してもらうとかして、ディベロッパーモードをオンにしてもらって試してもらうことになります。

これ結構面倒で手軽にbugfixの確認をしてもらうには手順が多くて申し訳ない感じになります。

ChromeExtensionにもパッケージファイル(crx)があるので、これを手軽に配布できると嬉しそうということでまずはその部分の整備から始めました。

Chrome Extensionのパッケージングについては公式ドキュメントに書かれていますが、Chrome自体が必要だったり、掲示されているスクリプトもOpenSSLなどで生成した鍵が必要だったりしてちょっと面倒です。

crxをBuildするためのnpm module crx というのが公開されているのでこれを使うのが簡単で良さそうだったので、このモジュールをビルドに関しては全面的に信用することにしました。

このcrxを利用すると、crxパッケージだけでなく--zip-outputオプションを用いることでzipも生成してくれるので、WebStoreにリリースするためのzipもこのコマンドで生成できます。

ちなみにこのcrxコマンド、masterにはmergeされていないのですが、.gitignoreなどと同じ記法で使える.crxignore対応を実装したPRがあります。 https://github.com/oncletom/crx/pull/51 *1

作戦としてはCI上でcrxコマンドでpushされるたびにtestの後にbuildしてDL可能に出来ると更に便利で良さそうなので、ついでにそのためのGitHubAPIも叩くことにしました。

あとはcrxファイルの配置を適当なサーバにしてリンクを取得すれば良さそうです。gyazo-chrome-extensionで利用しているCircleCIにはデフォルトでgsutilコマンドが入っていたり、Gyazo本体でもGCPを利用しているという理由でGCSに配置しています。

gyazo-chrome-extensionではこの流れを実装したスクリプトをテストの後に叩いて実行しています。

そうするとこういう具合でcommitの度にcrxをビルドしてリンクを貼ってくれるので、レビュアーなどは簡単に動作確認を行うことが出来るようになりました。

( via change webfont to svg images by pastak · Pull Request #152 · gyazo/gyazo-browser-extension · GitHub )

自動リリース

Chrome Extensionのリリースも手動でやると結構面倒です。

https://chrome.google.com/webstore/developer/dashboard に行って、アプリケーションを選んで、リポジトリのmasterなりproductionなりをpullしてzipにしたものをアップロードするというのが必要になります。

Chrome WebStoreにもAPIがあるので、これを使おうという作戦を紹介します。

curlなどを使ってチマチマやっても良かったのですが、せっかくなのでnpmモジュールとしてコマンドラインツールを作りました。

最初はこれをCIで叩くという作戦でした。GoogleのOAuthの認証の期限が結構短くて頻繁にrefresh_tokenを用いてaccess_tokenを更新する必要があるというのに気付きました。その度に環境を更新しないといけないのですが、CircleCIの環境変数APIなどからアップデート出来ないので、期限が切れる度に手で取得して環境変数設定をアップデートするという心温まる世界観になっていました。*2

このままではヤバいということで適当な外部の記憶領域を利用してtoken関係を記憶させようという作戦を立てました。

そして作ったのが、chrome-extension-release-herokuです。

先ほどのchrome-webstore-managerで基本認証や公開などの機能の実装は出来ていたので、それをJSのコードからrequire出来るように改善し利用しています。

deployもリポジトリのREADMEに置いてあるherokuボタンから一発で出来るようになっています。

適当にdeployして設定項目を埋めるとアプリケーションがheroku上で立ち上がります。その後に/initializeをブラウザで踏むとGoogle OAuthの認証に飛ぶので、Chrome WebStoreのアイテムオーナーのアカウントで認証すれば準備完了です。

あとはリリースのタイミングでCIからzipを/releaseにPOSTで投げつければウェブストアへのリリースと公開をやってくれます。この時にCIから秘密のトークンを一緒に渡す必要があるので、このトークンさえ漏れなければ、URLが公開されていても外部から悪意のあるzipが投げられて勝手に公開される危険は防がれるはずです。

自分で書いてから、GyazoChrome Extensionのリリースに何度も利用しているのですが、今のところ問題なく動いています。

まとめ

GyazoExtensionでのChrome Extensionの自動ビルドと自動リリースについて実践していることを紹介しました。

手探りで良くしているという感じなのと、herokuのアプリなどもとりあえず動く感じに作ったという世界観なので、もしよく出来るアイデアなどがあればissueやPRで教えてください。

最後に良ければGyazo Extension割と気合入れて作ってるので、試してみてください。よろしくお願いします。

こっそりWebExtension対応なども始めてるので、興味ある人は是非情報交換しましょう。よろしくお願いします。

*1:自分が機能を提案したのだけど、実装を書いている途中で忙しくなって手を付けられないでいたら、他の人が完成させてくれていたという出来事

*2:これを書いてて気付いたのですが、もしかしてAuthorizeの種類を適切に選べば意外とこういう苦労をしなくて済んだりしたのでしょうか・・・もしそうならこっそり教えてください。