CircleCIによる電子書籍の継続的デプロイメント
先日、CircleCIを導入して、CIによるEPUBビルド環境が整ったわけですが、人間とは欲望が尽きないもので、こうなってくると、今度は継続的デプロイメント環境が欲しくなってきました。
私が考える電子書籍の継続的デプロイメントがどのようなものか整理してみると、EPUBビルド(テスト)が完了した後に、Kindleへファイルを自動送信するのが自然だろうという回答に至りました。
そこで、CircleCIに設定を追加して、継続的デプロイメント環境を整えてみるとことにしました。
kindlemail を改造して環境変数に対応させる
KindleへのMOBIファイルの転送は、以前記事に書いたとおり、kindlemailを利用しているのですが、今回、CircleCIで動かすにあたり、OAuthトークンなどを設定ファイルからではなく、環境変数から読み込むようにした方が良いと思いましたので、改良をほどこしたkindlemailを作ることにしました。
とりあえず、簡単に実現したかったので、lib/Configuration.rb
ファイルを次のように変更することにしました。
@@ -61,23 +61,33 @@ class Configuration def get_email_credentials - raise ArgumentError, "Cannot find email credentials file #{EMAIL_CONF_FILE}." if !File.exists?(EMAIL_CONF_FILE) - begin - load_yaml(EMAIL_CONF_FILE) - rescue - raise StandardError, "Error parsing #{EMAIL_CONF_FILE}" + if (ENV['SMTP_OAUTH_TOKEN'] && + ENV['SMTP_OAUTH_TOKEN_SECRET'] && + ENV['KINDLE_USER_EMAIL']) + + return { + :smtp_oauth_token => ENV['SMTP_OAUTH_TOKEN'], + :smtp_oauth_token_secret => ENV['SMTP_OAUTH_TOKEN_SECRET'], + :email => ENV['KINDLE_USER_EMAIL']} + else + raise ArgumentError, "Cannot find email credentials file #{EMAIL_CONF_FILE}." if !File.exists?(EMAIL_CONF_FILE) + begin + load_yaml(EMAIL_CONF_FILE) + rescue + raise StandardError, "Error parsing #{EMAIL_CONF_FILE}" + end end end
「SMTP_OAUTH_TOKEN」と「SMTP_OAUTH_TOKEN_SECRET」と「 KINDLE_USER_EMAIL」という3つの環境変数が全て存在すれば、設定ファイルではなく、環境変数を優先して利用するという形です。
フォークしたリポジトリに上記の変更を加えて、新規作成したブランチ(use-env-first)が下記になります。
GithubリポジトリからGemをインストールする
次は、新たに作成したリポジトリから、kindlemailをインストールするようにGemfileを書き換えます。
@@ -2,5 +2,5 @@ source "https://rubygems.org" gem "review" gem "md2review" -gem "kindlemail" +gem 'kindlemail', github: 'akinomurasame/kindlemail', branch: 'use-env-first' gem "dropbox-sdk"
bundle update
を実行すると、指定した自分のリポジトリのkindlemailに更新されました。
CircleCI の設定を変更する
CircleCI で行なうことは、kindlegenを使ってEPUBからMOBIを作成して、kindlemailによってMOBIをKindleへ送ることですので、作業内容は主に次のようになります。
- kindlemailの環境変数を追加する
- kindlegenをインストールする
- デプロイ設定を追加する
順番に作業を追っていきましょう。
kindlemailの環境変数を追加する
これはCicleCIの設定パネルから、先ほどの3つの環境変数を追加するだけですので、とても簡単です。
kindlegen をインストールする
kindleへMOBIファイルを送るためには、CircleCIでkindlegenコマンドが使える必要があるため、これをインストールする設定をcircle.yml
に追加します。
@@ -1,3 +1,9 @@ +dependencies: + pre: + - mkdir tmp && cd ./tmp + - wget http://kindlegen.s3.amazonaws.com/kindlegen_linux_2.6_i386_v2_9.tar.gz + - tar zxvf kindlegen_linux_2.6_i386_v2_9.tar.gz + - cp kindlegen /usr/local/bin test: override: - rake md2review epub send_to_dropbox
kindlegenはMakefileがないので、べたにインストールしました。そして、ブランチをpushして、CircleCIのビルドを実行してみると、無事にインストールされることを確認しました。
さて、毎回kindlegenをダウンロードするのは少し無駄な処理なため、キャッシュを使うように書き換えることにしました。
少し設定が複雑になるため、ついでにインストール処理をスクリプトファイルにしました。
dependencies: cache_directories: - tmp pre: - bash ./install-kindlegen-2.9.sh test: override: - rake md2review epub send_to_dropbox
#!/bin/sh -xe if [ ! -e tmp/kindlegen ]; then mkdir tmp && cd ./tmp wget http://kindlegen.s3.amazonaws.com/kindlegen_linux_2.6_i386_v2_9.tar.gz tar zxvf kindlegen_linux_2.6_i386_v2_9.tar.gz sudo cp kindlegen /usr/local/bin; fi
pushして、ビルドが完了した後に、リビルドしてキャッシュが利用されていることを確認しました。
デプロイ設定を追加する
circle.yml
にデプロイ設定を追加します。masterブランチが変更されたタイミングで、デプロイすることにしたので、次のような設定になりました。
@@ -7,3 +7,8 @@ dependencies: test: override: - rake md2review epub send_to_dropbox +deployment: + staging: + branch: master + commands: + - rake mobi send_to_kindle
これで、masterブランチにマージされると、kindlemailが実行されるようになりました。最後に、送信先のKindleデバイスを柔軟に追加できるようにします。
デバイスリストからKindleへ送る
kindle_addresses.yml
というデバイスリストのファイルを作成して、こちらに追加されているアドレス全てにMOBIを送るようにRakefileを修正します。
- kindle1@example.com - kindle2@example.com
desc 'send to kindle' task :send_to_kindle do if File.exist?("kindle_addresses.yml") YAML.load_file('kindle_addresses.yml').each do |kindle_address| sh "bundle exec kindlemail -f #{bookname}.mobi -k #{kindle_address}" end else sh "bundle exec kindlemail -f #{bookname}.mobi" end end
この変更により、kindle_addresses.yml
に書かれている、全てのsend-to-kindleアドレスに対して、MOBIファイルが自動的に送られるようになりました。
masterへマージ、デプロイ実行
様々な変更をしましたが、masterブランチにマージすると、無事にCircleCIによる自動デプロイが実行され、継続的デプロイメント環境が完成しました。
bundle exec kindlemail -f example.mobi -k kindle1@example.com kindlemail 0.2.8. Written by djhworld. https://github.com/djhworld/kindlemail Preparing example.mobi to be sent to kindle1@example.com Adding attachment: /home/ubuntu/.kindlemail/.staging/c78f78d87f0de292b516a7af051f0d40_209895.mobi (290.9131 kb) Sending message....sent! example.mobi was successfully sent to kindle1@example.com bundle exec kindlemail -f example.mobi -k kindle2@example.com kindlemail 0.2.8. Written by djhworld. https://github.com/djhworld/kindlemail Preparing example.mobi to be sent to kindle2@example.com Adding attachment: /home/ubuntu/.kindlemail/.staging/c78f78d87f0de292b516a7af051f0d40_970393.mobi (290.9131 kb) Sending message....sent! example.mobi was successfully sent to kindle2@example.com
まとめ
まだまだ電子書籍の執筆環境は改善できる点があるかと思いますが、ひとまずCircleCIによる継続的デプロイメントを試すことができたのは、私にとって大きな進歩でした。
あと簡単に思いつく改善としては、PDFの自動作成もCircleCI上で行なえれば便利かなと考えているのですが、CircleCI上でTeX環境を整えるのは、なかなか骨な気がするため、やるかどうか悩んでいます。
やるとすれば、TeX環境構築済みdockerコンテナを用意して利用するという方法が良いのかなと思うのですが、dockerを利用したことのない一介のライターの私にとっては、なかなか大変そうな作業です。
しかしながら、こういった改善を続けつつ環境を整えて、その情報を共有していくことで、他の電子書籍執筆者の助けになれば幸いですので、これからも少しづつ改善を続けていきたいと思う次第です。