LCL Engineers' Blog

夜行バス比較なび・格安移動・高速バス比較を運営する 株式会社LCL開発者のブログ

Baltoを利用して素早くサービスを改善する

LCLでは、今年の初めから開発フィードバックのツールとしてGoodpatch様のBaltoをメインで活用しています。 先日、Goodpatch様へ事例として取り上げていただきましたが、より具体的な利用方法について紹介します。

goodpatch.com

Baltoとは

Webサイトやモバイルアプリに対して、簡単にスクリーンショット・動画付きのフィードバックを送れるツールです。フィードバックした内容は、スレッド別に管理され、それぞれにコメントやステータス管理ができます。

f:id:lcl-engineer:20170614100938g:plain

以前はIssueトラッカーを利用していましたが、スマートフォンからフィードバックはかなり面倒でした。(スクショを取って、チャット等を経由でPCに渡して、PCでIssueトラッカーへ添付 & コメント )

Baltoの場合は、チャットのように気軽に送れて、Issueトラッカーのようにステータス管理もできるので、それぞれのいいとこ取りのツールだと感じています。

利用フェーズ

開発中の中盤から最後にかけて利用するが多いですが、サイトの動きが大きく変わるような改善の場合は、初期段階から利用するケースもあります。また、プロダクションのサイト・アプリをBaltoに登録しておき、ふとした時に気になったことをフィードバックするという活用もしています。

Baltoにはいくつかプランがありますが、弊社が利用しているスモールプランの場合はプロジェクトが4つまでしか登録できません。そのため、完了したプロジェクトは、必要フィードバックがあればIssueトラッカーに転記し、プロジェクトは削除するという運用にしています。

導入方法

Webサイトの場合は、管理画面からURLを登録するだけで使えます。

iOS/Androidアプリの場合は、SDKを導入してアプリを配信します。

SDKの導入ページがあるため、こちらの通りにやれば特に詰まることなく、実装できるかと思います。

なお、Balto SDKはiOS9以上が対応ですが、弊社のアプリはiOS8から対応しているため、BaltoのSDKが導入できません。そのため、Balto専用のブランチを用意し、iOS9からがターゲットとなるように一時的に書き換えて導入しています。nアプリの配信はAPIが用意されているため、faslaneに組み込んでビルド・配信は自動化しており、一度導入してしまえば手間なく配信できます。

lane :balto do
  ・・ビルド部分省略・・
   system("curl -F project_token=[project_token] -F user_token=[user_toke] -F package=@./../[アプリ名].ipa -F ready_for_review=1 https://balto-api.herokuapp.com/api/v2/builds/upload")
end

テスト配信に関しては、Fabric/Crashlyticsも併用しています。使い分けとして、基本的にはBaltoを利用してフィードバックサイクルを回し、最終チェック段階でFabric/CrashlyticsでBalto SDKを組み込んでいないアプリ配信しチェックしています。

まとめ

Baltoを利用すること、ちょっとした隙間時間でフィードバックできるようになり、フィードバックの数が増えたと感じています。

サービスを良くするには、いかにフィードバックを集めて地道に改善していくかが、重要な要素の一つであると捉えています。気軽にフィードバックができ、漏れなく管理が行えるBaltoは、フィードバックサイクルを回すプラットフォームとして、適していると思ってます。

1ヶ月間の無料トライアルができるようなので、みなさんも是非使ってみて下さい。

www.balto.io

AWS EC2 パラメータストアを利用した秘匿情報管理

DBの接続情報・APIキーなどの秘匿情報は、git管理下に置くべきではないですが、皆さんはどのようなに管理しているでしょうか?

先日のAWS Summit Tokyo 2017のDMM様の事例で、EC2 System Managerパラメータストアの紹介がありましたので、使ってみました。

【資料公開】AWS Summit Tokyo 2017にてDMMのAWS移行について紹介してきました - DMM.comラボエンジニアブログ

EC2 SystemManager パラメータストアとは

簡単に言うと、key/value形式のパラメータをAWSで集中管理できる仕組みだと理解しています。

主に、以下の特徴があります。

  • AWS API、CLIを利用してアクセス可能
  • KMSを利用してパラメータ値の暗号化が可能
  • IAMを利用して、各パラメータへのアクセス権を細かく制御可能

管理コンソールからの登録

EC2 Managemtn Consoleの左下に、Parameter Storeのメニューが有ります。Parameter Storeへアクセスするには、事前に、IAM Policyの「AmazonSSMFullAccess」を付与しておきます。 ( AmazonSSMFullAccessは、他の権限も含まれているため、厳密に権限管理する場合は、独自にポリシーを作成したほうが良いかと思います)

f:id:lcl-engineer:20170606214647p:plain

登録画面は、至ってシンプルです。この画面で登録するだけで、AWS CLI等で参照できるようになります。

f:id:lcl-engineer:20170606215310p:plain

AWS CLIからの参照

EC2インスタンスから、AWS CLIを使ってアクセスする方法を紹介します。

「AmazonSSMReadOnlyAccess」PolicyをAttachしたIAM Roleを作成し、EC2に割り当てておきます。

以下のコマンドでパラメータの取得可能です。

aws ssm get-parameters --region ap-northeast-1 --name production.db.user
->
{
    "InvalidParameters": [],
    "Parameters": [
        {
            "Type": "String",
            "Name": "production.db.user",
            "Value": "db_user"
        }
    ]
}

valueだけ取得したい場合は、queryを利用して以下のようにとれます。

aws ssm get-parameters --region ap-northeast-1 --name production.db.user  --query "Parameters[0].Value" --output text
-> db_user

パラメータストアのアクセス制御

ポリシーを独自で作成することで、細かいアクセス制御が可能です。 以下のポリシーの場合は、productionで始まるパラメータのみにアクセス可能です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1482841904000",
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameters"
            ],
            "Resource": [
                "arn:aws:ssm:[region]:[AWSアカウント]:parameter/production.*"
            ]
        }
    ]
}

パラメータの命名ルールとして、環境名やサービス名を入れておくと、環境やサービス単位で適切な制御ができると思います。

KMSを利用した暗号化

暗号化については、クラスメソッド様の記事が非常に参考になりますので、紹介だけに留めておきます。

AWS KMS で EC2 Systems Managerパラメータストアを暗号化 | Developers.IO

Railsで利用する

例えば、Railsのデータベース接続情報で利用する場合は、database.ymlで環境変数から読み込むようにします。

production:
  <<: *default
  database: db
  username: <%= ENV['DATABASE_USER'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  host: <%= ENV['DATABASE_HOST'] %>
  port: <%= ENV['DATABASE_PORT'] %>

Railsの起動ユーザの .bash_profileで、パラメータストアから値を取得して環境変数にセットしておけば、Railsアプリから参照できるようになります。

export DATABASE_USER=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.user --query "Parameters[0].Value" --output text)
export DATABASE_PASSWORD=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.password --with-decryption --query "Parameters[0].Value" --output text)
export DATABASE_HOST=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.host --query "Parameters[0].Value" --output text)
export DATABASE_PORT=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.port --query "Parameters[0].Value" --output text)

サーバプロビジョニングを自動化する場合は、Chef等で自動的に上記の内容をセットするようにしとけば良いと思ってますが、他にもっといい方法があるかもしれません。

まとめ

Railsでの秘匿情報を管理する方法としては、「yaml_vault + AWS KMS 」が良いと思ってましたが、EC2 System Managerのパラメータストアも手軽にセキュアな環境が構築でき非常におすすめです。EC2 System Managerは地味ですが、他にも良い機能があるので、今後は是非活用していきたいと思います。

参考

EC2 Systems Manager のパラメータストアを利用したアプリケーション環境設定の管理 | Developers.IO

AWS Key Management Serviceを使ってconfigファイルを暗号化すると便利 - Qiita

Railsのデプロイ時にwebpackのビルドを実行する

弊社が運営しているサービス:夜行バス比較なびのサーバーサイドはRuby on Railsですが、フロントエンドの一部はReact & ES2015で書かれています。今回はデプロイにおけるRailsとwebpackの連携について紹介します。

www.bushikaku.net

React & ES2015導入の詳細もブログで公開しています。ぜひ読んでみてください。

techblog.lclco.com

これまでの問題

webpackの環境は、各自の開発PC(Mac)につくります。 もともとRailsのsprocketsを使っていたため、React化(ES2015化)完了までは今まで通りsprockets を使うことにしました。 つまり、webpackで書き出したファイルを、sprocketsで管理しているディレクトリ以下へコミットしてしまいます。 (良い方法ではないと思いますが、サーバーにnode.jsの環境を作るまでのつなぎです。)

このように上記の記事でも言及していますが、今までwebpackのビルドは開発者がローカルで実行して、生成されたjsファイルもGitで管理していました。ソースコードの二重管理は手間ですし、手順が多いということはミスの誘発につながるため避けたいところです。

解決策

タイトルのとおり、デプロイ時にサーバーでwebpackを実行するようにしました。具体的にはAsset PipelineのPrecompileにフックしてビルドを実行しています。ビルド後はsprocketsに任せてダイジェストの付与を行っています。

この方法は下記の記事を参考にさせていただきました。

WebPackを使ってRailsからJavaScriptを楽に良い感じに分離する - Qiita

設定の詳細は以下のとおりです。

各種バージョン

Ruby 2.1.2
Rails 4.1.5
node.js 6.9.1
babel 6.11.4
webpack 1.13.1

ディレクトリ構成

webpackの入出力のディレクトリを簡単に説明します。実際より簡略化しています。詳細はこちらをご覧ください。

React & ES2015のソースコードはfrontend/src/scripts/に配置しています。

frontend
├── src
    └── scripts
        ├── xxxx
        │   └── xxxx
        │       ├── xxxx.jsx
        │       └── xxxx.jsx
        ├── xxxx     
        │   ├── xxxx
        │   │   └── xxxx.js
        │   │   └── ...
...

ビルドしたファイルはapp/assets/javascripts/es/にbundleされて出力されます。

app
├── assets
    ├── javascripts
        ├── es
        │   └─ xxxx.js
        │
        ├── xxxx // 通常のjsファイルがあるディレクトリ
        │   └─ xxxx.js
...

gitignoreの設定

ビルドで生成されるjsファイルのバージョン管理は不要になるのでgitignoreに追加します。この場合はapp/assets/javascripts/es/配下を無視します。

Precompileへwebpackビルドのフックを追加

lib/tasksにRakeタスクを作成します。これでデプロイ時にwebpackのビルドが実行され、その後sprocketsで処理され配信されます。

task :build_frontend do
  cd 'frontend' do
    sh 'npm install --production'
    sh 'npm run build'
  end
end

Rake::Task['assets:precompile'].enhance(%i(build_frontend))

おわりに

この方法で煩わしい手動ビルドからも解放され、デプロイもスムーズに行うことができています。

ここから更にフロントエンドの環境を整えてより良いサービスを提供していきたいです。

ES5からWebpack管理下の関数を呼び出す方法

フロントエンドエンジニアの岡田です。 先日ご報告したとおり、LCLが運営する「夜行バス比較なび」では、jQueryで作られたサイトをReactへ置き換えています。 techblog.lclco.com

記事を書いた後も細々と置き換えを進めていますが、ページ単位での置き換えは、それなりにまとまった時間が取れないと進められません。 しかしSPAのように複数のjsがあるページでは、その時間が取れず、なかなか置き換えが進められませんでした。

そこで、LCLではもっと小さい単位で置き換える方法を試してみました。
手順は以下のとおりです。

  1. 既存の関数(ES5)を、ES2015へ変換してWebpack管理下のディレクトリへ移動
  2. 移動した関数をグローバル関数へ変更
  3. 既存のjsからグローバル関数を呼び出し

この方法を使うと、関数単位で置き換えが可能です。

ES2015への変換ツール

変換にはlebabを使いました。 lebab.io

具体的な方法

既存の関数(ES5)をlebabでES2015へ変換

// 変換後の関数
const hogehoge = () => {
};

移動した関数をグローバル関数へ変更

window.grobalHogehoge = hogehoge;

既存のjsからグローバル関数を呼び出し

// グローバルに露出している関数を呼び出し
window.grobalHogehoge();

グローバルに露出させるのであまりよくないかもしれませんが、あくまでも移行中の一つの手段としては使えます。この方法で関数をES2015化して、最後にきれいにReactへ置き換えたいと思います。