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の種類を適切に選べば意外とこういう苦労をしなくて済んだりしたのでしょうか・・・もしそうならこっそり教えてください。

Chrome ExtensionをFirefoxが採用予定のWebExtensionとして書き換える際に便利なwemfというコマンドラインツールを作りました

Firefox46 が Developer Edition としてリリースされました。 WebExtensionはFirefox46でalpha stateということになっています。

このまま順調に行けば、 2016-08-02にリリースされる予定の*1Firefox48でstable releaseになります。

また上記ブログ記事でも触れられていますが、 addons.mozilla.org (AMO) にアップロードして署名をすることが出来るようになっています。

先日、WebExtension現状確認してみた - Pastalablog in はてなという記事を書いて現状を確認しました。最近まで結構大きめのバグ*2があって、動かせるExtensionがかなりシンプルなものだけだったのですが、先日それも解消されてかなりの数のExtensionが動くようになっています。

動くようには具体的にはこの2つのことを行う必要があります。

と言っても2つとも Chrome incompatibilities - Mozilla | MDNChromeとの差分が書かれているので、ここに書かれている通りにすればOKです。

今回作ったwemfというコマンドラインツール*3は、上記の作業のうちのmanifest.jsonの書き換え作業をシュッとやってくれるツールです。

やってくれることは以下のことです。

  • 必ず含まれているべきキーと対応する値を追加
  • 未対応のキーを削除
    • 現状未対応のキーがあるとインストールに失敗するので、そのようなキーを削除します。
  • 未対応のキーワードの使用を通知
    • web_accessible_resourcesワイルドカードが使えないなどがあるので、そのようなキーワードを含んでいる場合は削除せずに通知します。

% npm install -g wemfでインストールし、% wemf /dir/chrome-ext/package.json -O /dir/firefox-ext/package.json で変換したものを出力してくれます。

また、--validateオプションを利用することでmanifest.jsonの簡単なバリデーションチェックが出来ます。(厳密な値のチェックなどをするのではなく、未対応のキーを含んでいないかなどをチェックするだけです)

詳しい使い方はリポジトリのREADMEや--helpなどを見てください。

ちなみに今のv0.2.1は2015-02-06 (JST) 時点でmanifest.json - Mozilla | MDN に書かれている情報を基に実装しています。

何か更新があれば極力追随するつもりですが、何かあればPRがください。

どうぞご利用ください。

*1:https://wiki.mozilla.org/RapidRelease/Calendar

*2:https://bugzilla.mozilla.org/show_bug.cgi?id=1208257 ChromeExtensionのドキュメントでoptionalになっている引数を解釈出来ないというバグ

*3:名前は WebExtension Manifest Formatterの略です

Heroku上でNodeJS+OpenCV環境を構築するためのDocker Image作った

表題通りのものを作ったので報告します。

経緯としては週末にOpenCVとimagemagickで顔合成するツール作ったので、それをWebアプリケーション化したいと思って作った。

すぎゃーんさんのブログに書かれている情報を参考にしたらそれっぽく動くようになってめでたい感じ。

すぎゃーんさんの作られたDockerfileをベースにheroku/docker-nodejsdocker-pythonを参考にして構築した。

構成としてはdocker-pythonの上でNodeJSとOpenCVをそれぞれインストールするという感じになっている。

OpenCVなどのインストールはすんなりと成功したのだけど、node-opencvが結構鬼門で、それに対応するためにいくつか環境変数を適切に設定したり、OpenCVのバージョンを3.0から2.4系に下げるなどをしている。

HerokuにDockerをDeployする方法に関しては公式ドキュメントに詳しく書かれてるので、それを見てheroku-docker pluginでえいやとやると動くはず。

詳細については顔認識をして◯で囲むアプリケーションを書いた*1ので、それを参考にしてもらえれば良いかと思います。

repository: https://github.com/pastak/docker-heroku-nodejs-opencv-sample

App URL: https://heroku-nodejs-opencv-sample.herokuapp.com/

何かあればissueなどで教えて下さい。よろしくお願いします。

*1:コードは http://qiita.com/n0bisuke/items/f650a876d14807b70f80 のをほぼそのまま利用しました

WebExtension現状確認してみた

このブログ記事は KMCアドベントカレンダー2015 の5日目の記事です。

ちなみに昨日の記事は id:hnagamin好きなSCP-JPの紹介 - hnagamin でした。

サークルの人たち最近ずっとSCPの話してて、scpって色々あるんだなぁと思っていたのが、実はそういう話とは違ったということが発覚して良かったです。

今までのブラウザ拡張について

ブラウザ拡張といえば皆さんも一度くらいは書いたことあるのではないでしょうか。

今まではブラウザでそれぞれ実装方法に違いがあってざっとまとめると大体こんな感じです。

Mozilla Firefoxは最近Addon-SDKをリリースし、XULなどでの開発から旧Jetpackを利用した開発へと移行を開始し、Firefox 38からはビルドツール群もnodeJSで実装されたものが利用可能になりました。*1

そんなこんなで各位思い思いにブラウザ拡張の実装を作っていたわけでした。

WebExtensionって何?

とまぁここまで来て、こうやってみるとFirefoxで提供されているAdd-onと同等のものがChromeなどにも提供されている中で、Add-onSDKを押し進めるのではなくWebExtensionとして共通のAPIを利用できるようにすることでBlink向けに書かれたブラウザ拡張をFirefoxでも簡単に動かせるようにしようという話です。Firefox的にはマルチプロセスの話とかもあるのですが、ここではあんまり触れないので上記のリンク先を読んで下さい。

仕様策定とかをするという話はなくて、とりあえずはFirefox側でChromeのドキュメントや実装を参考に同じような挙動を実装するという話です。

Microsoft Edgeにインストール可能になるExtensionもChrome Extensionとほぼ同じものになるという話があるので、今回のChrome ExtensionベースのWebExtensionがデファクトスタンダードになりそうです。

僕も普段はChrome Extensionをよく書いていて、話題に上がってから定期的に話題巡回をしているので、状況を簡単にまとめてみます。

最新情報を把握したい人向け情報

日本語でシュシュッと雰囲気を掴みたい人は@yoichiroさんのChrome Extensions から見る WebExtensionsがまとまっている感じなので、それを見ましょう。

実装状況やバグトラックの雰囲気を掴みたい人は Are we Web Extensions yet?というページがあって便利なのでおすすめです。参照すべきbugzillaへのリンクや、Chromeドキュメント・MDNへのリンク、Firefoxの実装へのリンクがあるので、状況を俯瞰したりするのには良いと思います。

Mozilla Wikiにもシュッと開発状況や開発チュートリアルがまとまっています。とりあえずこのページに目を通すと良いと思います。

https://wiki.mozilla.org/WebExtensions

MDNドキュメントも整備中ではありますが、着実に増えつつあります。開発チュートリアルなどもあるので、時間がある人は読んでみると良いでしょう。

サポート完了のAPIのリストはここにあります。メソッドごとに記述があるので、自身で実装などをする際はここを参照して実装済みか確認すると吉です。

サンプルコードを読み書きしてみる

既にtabscontextMenusbrowserActionnotificationsなどはある程度サポートされているので、それらの機能を利用した拡張機能を実際に開発することが可能になっています。

サンプルコードがGitHubに公開されているので、それを覗いてみることにします。

0. 環境準備

WebExtensionはhttps://nightly.mozilla.org/https://www.mozilla.org/en-US/firefox/channel/#developerで動かすことが出来ます。

皆さんもどちらかはインストールしていると思いますが、まだの人はインストールしてください。

インストールしたら起動して、about:configに移動して、xpinstall.signatures.requiredの値をfalseにします。

https://gyazo.com/07135817da46e77f946ec3fef8f41e01

1. サンプルをインストールしてみる

https://github.com/mdn/webextensions-examples のコードを動かしてみます。

  • $ git clone git@github.com:mdn/webextensions-examples.git
  • $ cd webextensions-examples

拡張機能のパッケージングはzip圧縮して拡張子をxpiにすればOKです。例えば、notify-link-clicksをインストールしてみるということにします。

  • $ cd notify-link-clicks
  • $ zip -r ../notify-link-clicks.xpi *

これで出来たnotify-link-clicks.xpiFirefoxabout:addonsドラッグアンドドロップしてinstallボタンをクリックするとインストールできます。

https://gyazo.com/e1b3f4d6b1a28062c77bf2dfb81a5816

notify-link-clicksでbackground script、content scriptやnotificationが動くことが確認できます。user-agent-rewriter((インストール後に http://useragentstring.com/ にアクセスするとwebRequestを利用してユーザーエージェントが書き換わってることが確認できます。このページでしか呼ばれないので注意))などを試すとbrowser actionが動くことも確認できます。

実際に移植してみる

最後にChrome Extensionを実際に移植してみます。

Gyazo Extensionを移植しようとチャレンジしたのですが、chrome.tabs.captureVisibleTabのサポートが無くて挫折した*2ので、自分で過去に作ったgyoogleというのを移植してみることにします。

これは googleの検索結果を表示するとpostMessageでbackground scriptに通信して、そこでXHRでGyazoの検索結果を取得して、メッセージをcontent scirptに返して結果を挿入するというやつです。

この拡張機能で使っているAPIFirefoxのWebExtensionで実装されているので、manifest.jsonにアプリケーション情報を記述するだけでOKです。

WebExtensionのmanifest.jsonはBlinkのものと違って、applicationsが必須です。

最低限のものはこのような感じです。

"applications": {
    "gecko": {
      "id": "gyoogle@pastak.net"
    }
  }
  • idのみ必須です。記法は https://developer.mozilla.org/en-US/Add-ons/Install_Manifests#id を参照して下さい。大抵は上記のようにextensionname@example.orgの形式になっていればOKです。
  • 他、必要に応じてstrict_min_versionstrict_max_versionなどを指定することが出来ます。

将来的にはここでblinkキーが使えてバージョン指定出来るようにするということなのだと思いますが、Blinkはこのキーに現状対応していないので、このままのmanifest.jsonChromeにインストールしようとすると、このようなエラーが出ます。

https://gyazo.com/bcc7825586834b39a3abde5a227dc463

これでビルド(zipに固めて拡張子.xpiにする)してインストールすると確かに動きます。めでたい!

https://gyazo.com/cc7ad5629287a73592db63aa6a7ddd96

今後について

  • ロードマップはここにあります。2016年の中旬くらいまでにはWebExtension1.0としてリリースすることが目標とされています。
  • AMOでのサポートもこれから。
  • 現状 chrome.*のnamespaceで提供しているAPIbrowser.*に移行して、拡張子zip を使いたい。
    • これは標準化のためです。
  • Chromeなどに実装されていないが、Firefoxのこれまでの寛容なAPIで動いていた便利なアドオンのためのAPIの拡張も提案はされています。

まとめ

今実際にFirefoxChrome拡張機能をリリースする場合はAdd-onSDKを利用しても資産はあまり使いまわせないので、WebExtensionの実装は早く進んで欲しいという感じですが、最後のところに書かれているような感じのが実装されるとそれらはBlink系では動かなくなってしまうので、それはそれでどうなんだろうと思いますが、Chromeなどにもサイドバーは欲しいので各位頑張って欲しいです。

APIさえ準備されれば、ほとんど手を入れること無くChrome拡張をFirefoxで動くように出来るのでみなさんも試してみてください。

諸々気になる人は https://wiki.mozilla.org/WebExtensions から辿れる各種バグトラックを追いかけてみてください。

このブログ記事は KMCアドベントカレンダー2015 の5日目の記事でした。

明日6日目は @ くんの「UnambiSweeperというandroidアプリ作ったのでその辺の何か」です。

彼は マインスイーパー雑感 - KMC活動ブログ とかでもマインスイーパーの話をしていたのですが、どうやら最近Androidアプリに移植したらしいのでそういう感じの話が出てくるっぽいです。乞うご期待!

KMCM

京大マイコンクラブではブラウザ拡張に興味がある新入部員を募集しています。年齢や所属、国籍や宗教その他諸々に関する制約はありません。いつでも例会に遊びに来てみてください。詳しくは入部案内を見て下さい。

*1:この辺のjpmの話はKMCの部誌に書いたので、コミケなどで買って下さい! https://www.kmc.gr.jp/events/c88/

*2:https://github.com/pastak/gyazo-chrome-extension/tree/firefox-webextension

iTunesStoreとAmazon Musicを同時に検索できるウェブアプリ書いた

最近バイト先の社長がNodeJSでウェブアプリを書いているらしくて、NodeJSのそういう話をしていたら久しぶりに趣味でウェブアプリでも書くかという気持ちになったので作った。

これは何?

ちょうどAmazon Prime Musicがリリースされた日に始めたのでタイトルのような雰囲気のウェブアプリになった。

使い方は簡単で適当にキーワードを入力するとそのキーワードでの検索結果を出してくれる。

AppleMusicは再生可能な場合はチェックが入ってる。あとiTunesでダイレクトに開くとかそういうのが出来る。

Amazonはよく分からなかったので、AmazonPrimeMusicはページに行って確認して頂くという感じになってる。気合い出せば出来るのかもだけどAPIのレスポンス睨んでも無さそうだったからこういうことになってる。

今のところherokuのFreeプランを利用しているのもあってレスポンスが遅い。多分hobbyとかにしたらもう少しマシになるのだろうと思ってる。

Recent Keywordに直近検索された10ワードを表示しているので、発想支援的に使えるのではと思ってる。Apple Music良いのだけど、「for you」と「new」と検索でしか曲が探せなくて、newもそんなに表示件数が多くないのでdigったり気付きを得るにはfor youのプレイリストからアーティストを辿って行くとかそういうのが必要なので、他の人が聞いてるのとかそういうの知れたら良いなと思ってつけた。

プレビュー、スマートフォンのブラウザでも聞けると思うので、出先とかで友だちに曲を教えたりするのとかにも使って欲しい。

こういう感じでTwitterで共有とかもおすすめです。

何かあれば教えて下さい。よろしくお願いします。

開発関係の話

最近バイトでもずっとES6とReact触ってるし、Electronアプリケーションも色々書いたりしてて、フロントエンドJSをよく書いてるけど、NodeJS自体はCLIツール書いたりとかしかしてなかった。最近のJS開発関係現状把握も込めて今回はサーバサイドもJSで書いた。

  • Babel6初めて触ったら、presetとか設定しないといけないの分かってなくて最初スッって通したらシュッとそのまま出てきて愉快な気持ちになった。
  • サーバサイドのWAFにはkoaを使った。generatorを使ってるのが特徴っぽい。
  • Reactはv0.14を使った。

観賞用です。何か有ったら教えて下さい。

GyazoをSpotlight風のUIで検索できるElectronアプリを公開しました。ブラウザ拡張もあるよ。

過去にSpotlightプラグインを組み込むFlashlight向けにIvySearchを検索する のを書いたことがあった*1のだけど、Yosemiteになってから動かなくなってどうやら今後もFlashlightは開発をしなさそうな雰囲気なので、先日行われたバイト先のハッカソンを利用してElectronを使ってSpotlight風に扱えるアプリケーションとして書き直したので紹介します。

Gyazo

NinjaユーザーじゃないとIvySearch有効にならないので利用できないのですが、偶然今日からIvySearchが全ユーザーに解禁されているので皆さん利用できると思います。

これは何

MacOSXSpotlightのようなUIでIvySearchを検索して結果をクリップボードに保存できるアプリケーションです。

Gyazo

クリップボードにはURLとHTMLと画像Blobが同時に入ります。

使い方

  • https://github.com/pastak/gyazotlight/releases から 自身のプラットフォームに対応するzipをダウンロードして解凍。
  • Gyazotlight.app / .exe などを起動
  • MacOSXの場合はネットワーク受信接続〜が表示されるので「許可」 Gyazo
  • Gyazoの画面が表示されたらログインしてください。(ログイン後自動で閉じます)
  • 右上に忍者が表示されるので、そこから起動したり呼び出し用のショートカットキーを設定することができます。
    • 初期状態だと Control+Shift+G で呼び出すことが出来ます。

ChromeFirefoxから利用する方法

Gyazo

Chrome Extensionと連携することでブラウザ上でテキストを編集しているところにGyazotlightを介してGyazoのURLを挿入することが出来ます。

Install for Chrome

Install for Firefox

使い方

  • テキスト入力中に Control + Shift + U を押すと Gyazotlight が起動するので適当な画像を選ぶ。
  • カーソル位置にGyazoのURLが挿入されます。

おまけ: ブラウザ拡張から呼び出す仕組み

1passwordのブラウザ拡張がネイティブアプリを呼び出す仕組みになっているので、どうなってるのか追いかけたらWebSocketを利用していたので少し真似してみた。

  • Electronアプリケーション内にwebsocketサーバを立てる
  • ChromeExtensionからwebsocketで接続
  • Electronにメッセージが飛んできたらGyazotlightの画面を表示
  • 結果をwebsocketで返す
  • ChromeExtensionで結果を受け取ってカーソル位置に挿入

websocketなので他のブラウザ拡張とかアプリケーションから利用したい場合も比較的簡単だと思います。

その他

細かい使い方はGitHubに書いてあると思います。

MacOSXでは動くのを確認してますが他のプラットフォームでは確認してないので何かあればissueで教えて下さい。PRも歓迎です。