LCL Engineers' Blog

夜行バス比較なび(高速バス比較)・格安移動・バスとりっぷを運営する LCLの開発者ブログ

リモートワークへの取り組み

この記事はリモートワーク Advent Calendar 2016 - Adventar 25日目の記事です。

弊社におけるリモートワークの事例や普段の取り組みを見波が紹介したいと思います。

基本的なルール

細かい部分は割愛しますが大まかには以下のようなルールで運用しています。

  • 7:00-22:00の間で8時間働く(11:00-15:00のコアタイムは意識する。オフィスは10:00-19:00)
  • 前日までにリモートワークの予定をカレンダーに登録してチャットで申告する
  • 当日に勤務開始時に予定の勤務時間をチャットで申告する

週一でリモートワークする日を決めている人や午前はリモートで午後は出社してオフィスで働く人もいます。1名(私のことですが)は地方在住でフルリモートで勤務しています。

様々な活用事例

前述のとおりリモートワークといってもやり方や目的が異なります。その具体例を挙げていきます。

集中できる

メンバーから物理的に話しかけられることがなくなるので自分の作業に集中することができます。オフィスの開始時間より早く開始すればチャットによるやり取りも不要になるので重めの設計や実装も捗ります。

時間を有効に使える

まず通勤時間が0になります。これに加えて比較的フレキシブルなルールで運用しているためうまく時間をやりくりすることで自分の時間を有意義に過ごしたり急な家庭の体調不良にも対応ができます。例えば早めの勤務にして家族と夕食を共にしてから勉強会に参加したり、子どもが保育園で熱を出しても中断して迎えに行き、家族が帰ってきたら子守をバトンタッチしてすぐに仕事を再開できます。

地方在住でも働ける

今のところまだ私だけなのですがフルリモートでの勤務も実践しています。弊社は東京にオフィスにあり私は長野県に住んでいます。中途採用でリモートワークを前提として入社しました。最初の数ヶ月はオフィスで勤務をして、その後リモートワークに移行しました。現在は月一くらいの頻度で社内のイベント等に合わせて出社してしています。自分が住みたい場所に住みながらやりたい仕事・魅力的なサービスに携わることができるのは幸せなことです。

どうやって実現しているのか

メリットが多いリモートワークですが、よく挙げられるデメリットとしてオフィスとリモートでの情報の乖離があります。オフィスの口頭でのやりとりがリモートワーカーには共有されない、リモートワーカーの様子や進捗が見えないといった話はよく耳にします。このようなデメリットを下記のように解消しています。

すべてを記録する

弊社ではYouTrack(JetBrains製のIssue Tracking System)を利用しています。これを間接部門も含めて全社的に使用しています。タスクは全てIssueになっておりコミュニケーションは各Issueのスレッド上で行われます。たとえ口頭でのやりとりが発生してもその内容をIssueに記載するので場所に関係なく把握できるようになっています。また、メンバーとのやりとりが無くても状況や進捗にアップデートがあったら細かくIssueを更新します。逆に進捗がないという場合でも行き詰まっている点や確認事項をコメントしてメンバーに助けを求めます。 このようにリモートワークに関係なくすべてを記録することでオフィスでもリモートでもやり方を変えずに仕事をすることができています。

チャットを活用

近頃はSlackが主流のようですが弊社ではChatworkを利用しています。メンバーとの細かな調整やすぐに回答をもらいたいことはチャットで行います。デプロイやテスト環境の起動もチャットのbot経由で行うようにしており誰が何をしているのかがより把握しやすくなっています。また、本番環境等での作業をする場合も何かあったらすぐに他のメンバーがサポートできるように逐次作業内容とその結果をチャットで実況します。

ビデオ会議

リモートからミーティングに参加が必要な場合はZoomを使ってビデオ会議(音声のみ場合もあり)をしています。エンジニアは週一で定例ミーティングを設けているのでリモートワークの私もそれなりの頻度でメンバーの声を聞くことができチームとしての距離を遠くに感じることなくほど良いバランスを保つのに一役買っています。

おわりに

まだまだ課題や改善点は多くありますが、以上のようにオフィスでもリモートでも同じように働けるようなプロセスを確立しています。前回私が出社したときもミーティングが少し円滑になったくらいでリモートワークをしている普段とほぼ変わらぬ仕事の進め方ができました。

おわりのおわりに

個人的にリモートワークによる一番の恩恵は毎日家族と夕食をともにすることができ、子どもと過ごす時間も増えたことです。これまでの社会人生活の中でワークライフバランスが一番良い状態です。 LCLでは家族とごはんを食べたり、自分の時間を有意義に過ごしつつサービスを共に良くしてくれる仲間を募集中です。 ご興味がある方は是非採用ページからご応募お待ちしております。

株式会社LCL(エルシーエル)

Bitrise + GradleでAndroidアプリのCI環境構築

弊社では、Bitriseを利用してAndroidアプリのCI環境を構築しています。まだまだBitriseを利用している事例は少ないので、簡単にご紹介いたします。

なお、Bitriseを利用したiOSアプリのCI環境構築については、以下の記事で紹介しています。 techblog.lclco.com

前提条件

  • Gradle(gradlew)でビルドができること

初期設定

まずは、新規作成〜ビルド(apkの作成)までの手順を紹介いたします。

アプリの作成

Bitriseでは、まずビルド等の対象アプリを登録する必要があります。 [Add new app] をクリックすると、ウィザード画面が表示されます。

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

以下のマニュアルに沿って、進めればよいので詳細は割愛します。

Creating your first App on Bitrise · Bitrise

Workflowの作成

アプリ作成後のWorkflowはデフォルトでは、このような状態になっています。この時点で、ビルドに必要な基本的な流れは網羅しています。

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

Gradleで実行するタスクは、以下の箇所で設定します。

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

上記のテキストボックスにタスクを直接入力してもよいですが、GRADLE_TASKという環境変数に設定することもできます。

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

環境変数の設定画面で、ビルドタスクを入力します。複数のビルドを実行する場合は、半角スペースで区切りで入力します。

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

ビルドする

以上で設定は完了で、あとは[Start a build] ボタンでビルドが行えます。

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

BitriseでSigned APKを作成する

keystoreファイルをBitrise上に登録することで、リポジトリにkeystoreファイルを保存することなく、Signed APKを作成できます。

keystoreファイルの登録

Workflowの[Code signing & Files]メニューから、ファイルをアップロードします。

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

ファイルをアップロードするとパスワード等の情報の入力画面になります。 必要な情報を入力し、[Save metadata]で保存します。

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

この画面で登録した情報は、各項目に記載されている環境変数( $BITRISED_ANDROID_XXX)でアクセスできます。

File Downloader Stepの追加

Bitrise上に登録したkeystoreファイルは、ビルド時にダウンロードが必要です。その為に、File Downloaderというステップを追加します。

今回は、Git Clone の Stepの後に追加します。(Gradle の実行前ならどの場所でも良いはずです)

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

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

続いて、 File Downloader Stepへ変数を設定します。

  • Download source url には、 $BITRISEIO_ANDROID_KEYSTORE_URL を設定
  • Download destination pathには、任意パスを設定(ここでは、$HOME/keystores/release.jks を設定)

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

build.gradleの編集

Bitrise上で登録したkeystoreを利用するように、signingConfigsを書き換えます。

signingConfigs {
    release {
        keyAlias System.getenv("BITRISEIO_ANDROID_KEYSTORE_ALIAS")
        keyPassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD")
        storeFile file(System.getenv("HOME") + "/keystores/release.jks") // File Downloaderで指定したパス
        storePassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PASSWORD")
    }
}

以上で完了です。Gradleでリリースビルドを行うと、Signed APKが生成できます。

まとめ

Bitriseを使えば、単純なビルド環境だけならすぐに用意できます。無料プランもありますので、CI環境未構築の方は、最初のステップとして是非利用してみてください。

Hubot + Jenkins + Mackerelを利用したデプロイの見える化

弊社では最近、今更ながらHubotを利用したデプロイを行うようにしました。

なぜ今更ながら取り組んだのかも踏まえて、構成などを簡単に紹介いたします。

導入の背景

Hubot導入前は、以下のような流れでデプロイを行っていました。

  1. デプロイ担当者が、Google Analyticsのアクティブユーザを確認
  2. アクティブユーザが規定の数より少なければ、Jenkinsのビルドを手動で実行

この方法でも手間はそれほどかからないのですが、チーム・サービスの拡大によっていくつか問題が見えてきました。

ミスが起こりやすい

運営するサービス数の増加に伴い、Jenkinsのデプロイビルドも増えてきました。そうすると、弊社サービス「夜行バス比較なび」のデプロイをする際に、別サービス「格安移動」のデプロイビルドを実行してしまうなど単純なミスが発生するようになりました。

状況が見えない

最近リモートワークを行うメンバーが増え、Chatworkがコミュニケーションの主体となっています。そのため、前述のようなミスが発生したとき、以下のような状態になってました。

デプロイ担当: 夜行バス比較なびのデプロイします。
私: お願いします。
・・・
私: 格安移動のデプロイビルドが実行されているみたいですけど、間違ってないですか?
・・・
・・・
私: 大丈夫でしょうか?
・・・
デプロイ担当: 間違って実行してしまったので確認してましたが、特に悪影響ありませんでした。

この場合、リモートのメンバーは特に状況が見えづらく、不安になることが定期的に有りました。 このような問題から、ミスが発生しづらく・状況が見えるデプロイの仕組みへ変える必要があるとの考えに至りました。

デプロイ構成

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

  1. Chatworkでデプロイを命令を行う。
  2. Hubotがmackerelから現在のサイトのリクエスト数を取得する。
  3. HubotがJenkinsのデプロイビルドを実行する。
  4. Jenkinsが各サーバに対してデプロイを実行する。

各サイトのNginxのログは、エラー数の監視のためmackerelに随時送信しており、mackerel APIを利用してデプロイ時点でのリクエスト数を取得しています。リクエスト数が規定より多い場合は、デプロイを控えるようにしています

Chatworkでのやりとりは、以下のようになってます。

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

構築手順

Hubotのインストールや、基本的な利用法は割愛します。

ChatworkとHubotの連携

Chatwork APIを利用するためには申請が必要です。かれこれ2年以上プレビュー版ですが、問題なく使えます。以下のサイトから申請して、APIトークンを取得します。

チャットワークAPIドキュメント

ChatworkとHubotの連携は、adapterが用意されているのでそれを利用します。

npm install hubot-chatwork --save

環境変数にChatwork APIの情報を設定します。

# 取得したAPI TOKEN
export HUBOT_CHATWORK_TOKEN="XXXXXXXXXXXXXXXXX" 
# 監視するルームID。カンマ区切りで複数指定、botユーザをルームに所属させる必要あり。
export HUBOT_CHATWORK_ROOMS="111111,22222" 
# 1時間当たりのリクエスト数。APIは、5分間100回までの制限あり。
export HUBOT_CHATWORK_API_RATE="500"

以下のコマンドで実行。引数 -n でbot名称を設定

bin/hubot -a chatwork -n hubot

正しく設定が行われていれば、ping に応答があります。

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

mackerelとHubotの連携

事前に、Nginxのアクセスログをmackerelに投稿しておきます。

fluentdでサービスメトリックを投稿する - Mackerel ヘルプ

投稿したメトリクスは、APIで取得できます。

curl -X GET -H "X-Api-Key: <API_KEY>" "https://mackerel.io/api/v0/services/xxxxx/metrics?name=nginx_access_num.2xx_count&from=1476325055&to=1476325055"

サービスメトリック - Mackerel API ドキュメント (v0)

Hubotから直近の時刻を指定して上記APIを実行すれば、デプロイ時点でのアクセス数が取得できます。

JenkinsとHubotの連携

Jenkinsの認証を有効にしている場合は、以下の記事などを参考に外部からAPIを実行できるようにしておきます。弊社では、Hubot専用のユーザを作成し、限定されたビルドのみ実行を許可しています。

Jenkins のジョブを外部からビルドするには API Token を利用する - @kyanny's blog

HubotからJenkinsビルド実行は、以下のコードが利用できます。JOBのURLなど必要に応じて適宜修正します。

hubot-scripts/jenkins.coffee at master · github/hubot-scripts · GitHub

Jenkinsの情報は、Chatwork同様に環境変数に設定しておきます。

export HUBOT_JENKINS_URL="[JENKINS_URL]"
export HUBOT_JENKINS_AUTH="[ユーザID]:[パスワード or API TOKEN]"

以上でHubotと各サービスの連携は完了です。Hubotへの命令コマンドに応じて、適切な処理を組み合わせれば、デプロイまでの一連の流れが行えます。

導入の効果

見える化は、各自の行動にたよらず「強制的に見えるようにする」という仕組みづくりが重要ですが、以前までは、デプロイ担当者がチャットに状況を流していたので、結局は個々人による行動に依存していました。 今回、デプロイの全ての状況が"強制的に"チャット上に流れるようになったため、確実に見える仕組みが実現できました。

全ての流れが見えるようになったおかげで、まずデプロイが圧倒的にスムーズになりました。さらに、新しいメンバーでもどのようにデプロイが行われているかが、容易に把握できるようになりました。実際にやってみると、他にも応用したい案が多くでてきたので、今後もHubotを育てていきたいと考えています。

弊社では、エンジニアがより働きやすく・成長できる環境を日々検討していますので、ご興味がある方は是非採用ページからご応募お待ちしております。

株式会社LCL(エルシーエル)