メドピア開発者ブログ

集合知により医療を再発明しようと邁進しているヘルステックカンパニーのエンジニアブログです。読者に有用な情報発信ができるよう心がけたいので応援のほどよろしくお願いします。

メドベアと一緒にお待ちしています at RubyKaigi 2019

こんにちは! エンジニアの宮原です。
明日から、RubyKaigi 2019が開催されますね。

rubykaigi.org

メドピアとRuby

メドピアは、現役医師が経営するヘルステックカンパニーとして、国内医師の3人に1人が参加する国内有数のドクタープラットフォーム「MedPeer」や、遠隔医療サービスなどを運営・開発しています。2016年頃から、Ruby on Railsへ移行を行っており、新規プロダクトには積極的にRubyを採用しています。
Rubyのコミュニティを盛り上げるべく、今年はプラチナスポンサーとして協賛しています。

ブースへ遊びに来てください

技術研鑽のためのイベントや勉強会への参加は会社が積極的にサポートしており、RubyKaigiは参加希望の全エンジニアに参加費(交通/宿泊費含む)を支給しています。
今年は、ベテラン・若手含め総勢16名、Rubyエンジニアの80%が参加します。   (留守を守ってくれるエンジニアのみんなに大変感謝です...!) f:id:nyagato_00_miya:20190417073021j:plain

メドピアブースでは、開発中プロダクトのGemfileやRails Statsを公開します。

f:id:nyagato_00_miya:20190415175442p:plain
会場ではモザイク無しの実物を公開します

当日は、ヘルスケアカンパニーとして皆さんの健康をサポートできるよう、400名限定でアルコールパッチテストを実施します。 アルコール体質を「ぜんぜん飲めない族」、「ほんとは飲めない族」、「危ない族」の3種類に判定し飲酒のリスクを知るパッチテスト。 ご参加頂いた方全員へメドベアデザインのチロルチョコをプレゼントします。 さらに、限定20名(抽選)でメドベアTシャツも当たりますよ!

f:id:nyagato_00_miya:20190416203504j:plainf:id:nyagato_00_miya:20190416204112p:plain

f:id:nyagato_00_miya:20190415183424p:plain
3Fメインホールホワイエ メドピアブースでお待ちしております♪

「これは!」と感じたセッションについて、ベテランエンジニアと若手エンジニアが対談形式に考察する内容など公開予定です。

それでは、当日会場で皆さんにお会いできることを楽しみにしています。
是非、一緒にRubyKaigiを盛り上げましょう!
ブースでメドベアと一緒にお待ちしています。


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

Rails初学者からみたRailsdm2019の景色

こんにちは、メドピアフットサル部の櫻井です。
Rails歴3ヶ月の自分が贅沢にも「Rails Developers Meetup 2019」に参加してきましたので、そのレポートをお届けしたいと思います。 ちなみに、メドピアでは今回のようなスポンサードイベントへの参加費は会社が全額サポートしてくれちゃいます。

railsdm.github.io

第一線で活躍するRails開発者の技術的知見を広げることに主眼を置く本イベントは、DHH氏の基調講演に代表されるように本当に魅力的なセッションだらけでした。
ただ、それぞれの具体的な内容はRails Developers MeetupのYouTubeチャンネル*1や各登壇者さんのスライドから追うことができるため、本記事ではイベントの様子とそこで駆け出しエンジニアである自分が感じたことをお伝え致します。

f:id:shibadog39:20190326130753p:plainf:id:shibadog39:20190326095106j:plain

ドリンクスポンサーやってました!

メドピアはドリンクスポンサーとして、1日目は特製のPeerWaterを、2日目はメドベアの可愛すぎるカップでコーヒーを提供させていただきました。 特にメドベアコーヒーは好評をいただき、スポンサー枠の350杯が昼過ぎにはなくなってしまうほど大盛況でした。ありがとうございました!

f:id:shibadog39:20190326130923p:plainf:id:shibadog39:20190326131030p:plainf:id:shibadog39:20190326095652j:plain

f:id:shibadog39:20190326095640j:plain
大人気だったメドベアコーヒー

スポンサー企業によるノベルティグッズはどれも個性的でついつい手にとってしまいました。ノベルティはこういったイベントの醍醐味の一つですよね。 また、2日間とも最後には懇親会が開催されました。お寿司からスイーツまで、さらには日本酒からワインまで美味しいものを口にしながらワイワイできる最高の時間でした。

f:id:shibadog39:20190326131510j:plainf:id:shibadog39:20190326100659j:plain

f:id:shibadog39:20190326125419j:plain
大盛り上がりの懇親会

メドピアからの登壇

今回メドピアからは@pipopotamasuさんと@purunkaoruさんがそれぞれセッションとPRセッションで登壇させていただきました!

f:id:shibadog39:20190326100901j:plainf:id:shibadog39:20190326100912j:plain

お二方の登壇の様子

Railsフロントエンドボイラープレート「medpacker」の紹介 by @pipopotamasu

本ブログの記事でも投稿させていただいているmedpackerを紹介させていただきました。
どのような背景からmedpackerを作成する必要が生じたのか、medpackerを使えば何ができるようになるのかわかりやすく説明されています。webpackerからの脱却を考えている場合は、ぜひスライド及び記事の方を参考にmedpackerを使ってみてください!本当に3分かからずにセットアップできます。

MedPeerの取り組みの「失敗」の話をしよう by @purunkaoru

メドピア社内における様々な取り組みとそれにともなう失敗事例を紹介しました。
具体的には

  • 技術的負債をなくしていく整地部
  • Railsのバージョンアップ
  • 懸垂棒

に関するお話を紹介しています。我々と同じ失敗をしないためにも参考にしてください! また、自慢の取り組み・失敗話がありましたら共有していただけると嬉しいです。

初学者から見たRailsdm

冒頭にも書きましたが自分はRails歴3ヶ月で、もちろん今回のRailsdmが初参加でした。
正直に言うと今の自分が参加してなにか得るものがあるのか戦々恐々としていましたが、今となっては参加してよかったと心から思っています。

具体的には以下の3つがその理由です。

手軽に挫折することができる

セッションで前提とされている事柄・技術自体を知らないということが頻発します。比較することもおこがましい方々が登壇者ということを理解しながらも、Railsdmの2日間の間「このままじゃいけない」と何度考えたかわかりません。

手軽に視座を引き上げることができる、世界を広げることができる

第一線のエンジニア・事業責任者の方の問題解決の軌跡や課題意識を直接聞く機会はなかなかないと思います。また、日々の業務では扱う機会がなかったRailsをとりまく周辺技術であったりコミュニティに関する話題に触れることは、自分の興味関心の領域を広げることになると思います。

手軽に自分が何に「おもしろい」と感じるのか観測できる

セッションの内容は本当に多様で、技術にとことん向き合ったものからプロダクトの設計の話、Rubyコミュニティの話までありました。どういう話を聞きたいと思ったか、聞いてどう感じたか改めて振り返ることで自分の志向を再確認できるのではないかと感じました。

まとめると

魔法のようなRailsの技術自体も人の手によって作られているという当たり前のことを認識できたことが最も大きな収穫であったように思います。挫折感もあったのは確かですが、イベント後にはコードを書きたいという前向きな気持ちになっていました。

駆け出しエンジニアこそ、こういったイベントに積極的に参加するべきなのかもしれません。自分はこのRailsdmをきっかけに、各種勉強会に物怖じせずに参加してみようと思うことができました。 嬉しいことにメドピアでは今回のようなイベント・勉強会への参加を推奨する制度があるのでバリバリ活用していきたいと思います。

最後に

Railsdm参加することができてとても良かったです。運営のみなさま本当にありがとうございました!

突然ですが、人間は忘れる生き物です。 ja.wikipedia.org 今回自分が感じた「勉強しなきゃ」とか「あの技術調べてみよう」という気持ちもあっという間にどこかにいってしまうことでしょう。そんなの嫌だということで、メドピアではランチの時間で集まってRailsDM再放送上映会を実施することにしました。
こういった取り組みが自発的に起こるのが弊社の魅力なのかもしれません!楽しみです。

f:id:shibadog39:20190326105654j:plain
Railsdm2019最高でした!

以上、Rails Developers Meetup 2019のレポートをお届けいたしました!

※画像左下にクレジットが入っているものはラブグラフさん*2の撮影によるもので、それ以外は個人で撮影したものになります。


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

GitHub メンションを Slack DM する機能を Serverless Framework で作った話

メドピアマッスル部見習い kenzo0107 です。

今回は GitHub のコミュニケーションを円滑にすべく導入した GitHub 通知の Slack DM 機能になります。

github.com

導入経緯

GitHub.com でイシューコメントやプルリクエスト等でコメントをした、してもらった、時に気づかず放置されてしまうことが度々ありました。

Slack 上で
「あれ、どうなりました?」と聞くと、
「コメントくれてたんですね、すいません、気づきませんでした」と。

この防止策の一環として導入したのが、 GitHub メンションを Slack DM に通知する機能になります。

Slack には既に GitHub アプリあるけど?

Slack には既に GitHub アプリがありますが、個人宛てに DM 通知するには個々が認証する等、一手間あります。

その為、認証等せずとも、GitHub.com 通知を個人宛のメンションとして Slack DM する仕組みが必要と考えました。

新入社員さんに一手間かけてもらうことなく、スムーズに GitHub + Slack のコミュニケーションを体験してもらえるようにしました。

システム構成

f:id:kenzo0107:20190228125632p:plain

  1. mogezo 君が GitHub イシュー or プルリク コメントで hogeko さんへメンション
  2. GitHub Webhook を AWS API Gateway で受け、
  3. Lambda を実行し、
  4. hogeko さんへ Slack DM 通知する

図の点線で囲んだ AWS 内の処理を Serverless Framework で構築しました。

導入手順

以下導入手順の大まかな流れです。

  1. GitHub Webhook 設定
  2. Slack Incoming Webhook URL 発行
  3. serverless framework で API Gateway + Lambda + CloudWatch Logs 構築

GitHub Webhook 設定

Organization の Webhook を作成します。*1

設定項目 内容
Playload URL 仮設定で良いです (ex. https://hoge )。
後ほど設定します。
Content type application/json
Secret 認証の際に必要なパスワード情報です。
適当なランダム値を設定してください。

対象イベントは以下としました。

  • Commit comments
  • Issue comments
  • Pull requests
  • Pull request reviews
  • Pull request review comments

f:id:kenzo0107:20190215182516p:plain

Slack Incoming Webhook 作成

以下リンクから Slack Incoming Webhook URL 作成します。

https://slack.com/services/new/incoming-webhook

Serverless framework で API Gateway + Lambda 構築

事前準備です。

serverless framework プロジェクトを clone します。

git clone https://github.com/medpeer-inc/githubcom2slack
cd githubcom2slack

Nodejs は本プロジェクトでは AWS Lambda 最新の 8.10.0 としています。*2

node -v

v8.10.0

Serverless Framework インストールします。

npm install -g serverless

関連ライブラリをインストールします。

npm install
bundle install -j4 --path vendor/bundle

AWS Access Key ID, AWS Secret Access Key を環境変数設定します。

現状弊社では direnv を利用し設定しています。*3

// direnv インストール
brew install direnv

// 環境変数設定
echo -n 'export AWS_ACCESS_KEY_ID=HOGEFUGA' >> .envrc
echo -n 'export AWS_SECRET_ACCESS_KEY=BUDOUBAR' >> .envrc
direnv allow .

AWS KMS Key 作成

aws kms create-key

{
    "KeyMetadata": {
        "AWSAccountId": "xxxxxxxxxxx",
        "KeyId": "yyyyyyyyyyyyyyyyyyyyyyyy",
        "Arn": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy",
        "CreationDate": 1549615619.872,
        "Enabled": true,
        "Description": "",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER"
    }
}

キーのエイリアス作成

aws kms create-alias \
    --alias-name alias/githubcom2slack \
    --target-key-id yyyyyyyyyyyyyyyyyyyyyyyy

秘密情報の暗号化

今回、秘密情報として扱うのは、以下2 点です。

  • GitHub Webhook Secret
  • Slack Incoming Webhook URL

AWS Lambda コンソール上で暗号化ボタンをポチッと押すのでなく、暗号化した文字列を環境変数として設定します。

GitHub Webhook Secret 暗号化

aws kms encrypt \
  --key-id arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy \
  --plaintext "<GITHUB_WEBHOOK_SECRET>" \
  --query 'CiphertextBlob' \
  --output text

Slack Incoming Webhook URL

aws kms encrypt \
  --key-id arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy \
  --plaintext "<SLACK_INCONMING_WEBHOOK_URL>" \
  --query 'CiphertextBlob' \
  --output text

<SLACK_INCONMING_WEBHOOK_URL>https:// の後の ドメインからの文字列を指定してください。*4

上記 2 つ生成された値を secrets.yml に設定します。

  • secrets.yml は以下の様になります。
GITHUB_WEBHOOK_SECRET_ENCRYPTED: *****************************
SLACK_INCONMING_WEBHOOK_URL_ENCRYPTED: *********************************
AWS_KMS_KEY_ARN: arn:aws:kms:ap-northeast-1:xxxxxxxxxxx:key/yyyyyyyyyyyyyyyyyyyyyyyy

秘密情報の暗号化

yaml_vault で secrets.yml ファイルを暗号化した secrets.yml.enc をリポジトリで管理します。*5

env \
  AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
  AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
bundle exec yaml_vault encrypt \
  --cryptor=aws-kms \
  --aws-region=ap-northeast-1 \
  --aws-kms-key-id=alias/githubcom2slack \
  secrets.yml -o secrets.yml.enc

KMS key を利用した暗号化・復号権限を特定 IAM Group に絞ることで、そのグループに属するユーザのみ暗号化・復号が可能になります。

GitHub.com ユーザと Slack ユーザを紐付け

以下 2 つを紐づける為に git2slackNames という hash 値を設定します。

  • GitHub.com ユーザ名
  • Slack ユーザ名
// github username : slack username
const git2slackNames = {
  'kenzo0107': 'kenzo.tanaka',
}

上記の場合、新たにユーザ追加する度にコード修正が必要となります。

もし GitHub.com ユーザ名 と Slack ユーザ名 に命名規則がある場合、以下メソッドで命名規則に沿った変換を実装すると追加の手間がありません。

弊社では命名規則があるので、変換処理をするようにしています。*6

function extractUsernameFromMessage (message) {
  let usernames = []
  let usernameCandidates = message.match(/@[a-zA-Z0-9-]+/g)
  if (!usernameCandidates) {
    return usernames
  }

  for (let i in usernameCandidates) {
    var u = usernameCandidates[i].replace('@', '')
    if (denySlackDmUsers.indexOf(u) > -1) {
      continue
    }
    if (git2slackNames[u]) {
      usernames.push(`@${git2slackNames[u]}`)
    }

    // github username と slack username に命名規則があれば、
    // ここで変換 git --> slack username へ変更するも良し
  }
  return usernames
}

例)命名規則がある場合

  • GitHub.com のアカウント名: medpeer-<firstname>-<lastname>
  • Slack のアカウント名: <firstname>.<lastname>

以下のような変換が可能です。

for (let i in usernameCandidates) {
  ...
  ...
  if (u.match(/^medpeer-/)) {
    usernames.push(`@${u.replace(/medpeer-/, '').replace(/-/, '.')}`)
  }

いざデプロイ

sls deploy -v

GitHub Webhook URL 設定

GitHub Webhook URL が仮設定状態だったので、生成されたエンドポイントを設定します。

sls info

Service Information
service: githubwebhook2slack
stage: production
region: ap-northeast-1
api keys:
  None
endpoints:
  POST - https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/production/webhook
functions:
  githubWebhookListener: githubwebhook2slack-production-githubWebhookListener

上記の例では、 https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/production/webhook がエンドポイントになります。

こちらを仮設定だった Github Webhook URL に設定します。

では、早速試してみましょう!

GitHub.com のプルリクエストでメンションします。

f:id:kenzo0107:20190227143042p:plain

するとすぐに Slack DM 通知がきます。

f:id:kenzo0107:20190227123309p:plain

通知がこないな、という時に

Lambda のログが CloudWatch Logs に流れてますので、ログを確認してください。

そもそもログが出ていないのであれば、 Webhook の設定忘れや URL に誤りがある等チェックしてみてください。

まとめ

弊社では、非エンジニアも GitHub でコミュニケーションしています。

今回の実装によって、コミュニケーションが円滑になったことに加えて、 GitHub 上で明示的にメンションすることが増えた様に思います。

また、 GitHub から API Gateway + Lambda の認証が確立できたことで、 GitHub イベントをトリガーとした AWS リソースの変更に応用する様にもなりました。

こちらについては今後執筆できればと思います。

以上です。 参考になれば幸いです。


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

*1:リポジトリを絞りたい場合は、個々のリポジトリの Webhook に設定してください。

*2:nodenv でセットアップしています。

*3:特段これでなくてはいけないということではないので、適宜設定してください。

*4:https:// を含めるとエラーになるかと思います。

*5:serverless-secrets-plugin という暗号化する npm 管理可能な package もあるのですが、暗号化時にパスワードを設定する必要があります。そのパスワードの管理をAWS パラメータストアにすると、結局、KMS が必要となり、秘密情報を取得する手間がさらに増えてしまう為、導入経験がある yaml_vault にしました。その他にもあろうかと思いますが、もし良いのあるよ!という場合は是非教えてください!

*6:命名規則がない場合はこの辺りを DB に持たせても良いかもしれません。

MedPeerをrails 5.2へアップデートしてました!🎊

こんにちは、エンジニアの森田です🌴

rails 5.2.0が発表されたのが2018年4月10日🚃

大分遅くなってしまいましたが、2018年10月18日にメドピアが運営する医師専用コミュニティサイト「MedPeer」を、rails 5.1.6からrails 5.2.0にアップグレードしていました🎊

f:id:madogiwa0124:20190105151411p:plain

今回は、アップグレードを行った手順や躓いた部分を今更感もありますが紹介いたします🙌

アップグレードまでの道のり

まずはバージョンアップまでに行ったことの概要を下記にまとめました。

  1. リリースノートとアップグレードガイドを読んで影響を確認
  2. Gemfileのrailsのversionを5.2.0に変更してbundle update
  3. rails app:updateで設定周りを更新
  4. テストを実行し、失敗したor警告が発生した箇所を修正
  5. 社内の検証環境にデプロイして、動作確認
  6. 本番デプロイ
  7. 振り返り会

それぞれについて、実際にやったことを紹介いたします🙇

リリースノートとアップグレードガイドを読んで影響を確認

まずはRails5.2の変更点を知るためにRailsGuideのアップグレードガイドとリリースノートを読みました👀 (私は英語があまり得意ではないので、日本語版もあって非常に助かりました・・・!)

アップグレードガイド

リリースノート

Gemfileのrailsのversionを5.2.0に変更してbundle update

月に1回bundle updateを行っていて、比較的依存Gemのバージョンが上がっている、またマイナーバージョンのアップデートということで影響も少なそうだったので、bundle updateで依存Gemを含めて、アップグレードを行いました。

※月1回のbundle updateの施策については、こちらから👀

speakerdeck.com

rails app:updateで設定周りを更新

次にrails app:updateをとりあえず全てyesで実施して、危なそうな部分を戻す対応を行いました。影響が大きそうだった差分だけ下記に記載しておきます👀

  • bin/railsbin/rakeでspringをロードしないような変更が入っていたので反映しませんでした。
  • active_storagetest_unit関連の設定ファイル追加及び既存ファイルへの更新は、使用していないので反映しませんでした。
  • config/application.rbconfig.load_defaults5.2に変更しました。
  • bootsnapは開発環境のみで動くようにし、本番での使用は一旦様子見しました。

設定ファイル関係はわからないことも多かったのですが、技術顧問の前島さんにレビューしてもらえるので安心・・・🙏

f:id:madogiwa0124:20190105151558p:plain

テストを実行し、失敗したor警告が発生した箇所を修正

とりあえず全体でテストを走らせて落ちた箇所と警告が発生していた部分を修正しました👷
主な修正は下記のようなところでした。

Arelのexistsを使っていた箇所を修正

existsを使っている箇所でDEPRECATION WARNING: Delegating exists to arel is deprecated and will be removed in Rails 6.0.の警告が発生していたため、下記のようにEXISTSではなくNOT INを使って行うように修正しました。

# before
where(Expert.where('users.id = experts.user_id').exists.not)
# after
where.not(id: Expert.select(:user_id)) }

Dangerous query method対応

rails 5.2から下記のようにsqlをハードコーディングするとDangerous query methodの警告が発生するようになりました。

Post.order('RAND()')

MedPeerでは固定の文字列を渡している箇所でのみ発生していたので、Arel.sqlで対応しました。

Post.order(Arel.sql('RAND()'))

テストの無い管理画面に立ち向かう

今回railsのバージョンを上げると同時に管理画面で使っているadministrateというgemのバージョンも大きくあがりました。メドピアでは管理画面ではクリティカルな部分以外でテストコードを書いていません😥
全てを手作業で確認するのは大変なので、今回はRails.application.routesを使ってpathを生成し、各画面遷移時にステータスコード200が返却されることを検証することで、手動テスト前の最低限の品質保証、バージョンアップによるエラーの検知が出来るようにしました🙇

require 'rails_helper'
module AdminRoutingTestHelper
  class << self
    # Admin配下のpath名と、それに合致するcontroller名とaction名を取得
    def admin_routes(actions)
      routes = routes(actions)
      routes.select { |route| route[:name].include?('admin') }
    end

    private

    def routes(actions)
      routes = Rails.application.routes.routes
      routes = routes.map { |route| prepare_route(route) if route.name }.compact
      routes.select { |route| actions.include?(route[:action]) }
    end

    def prepare_route(route)
      { name: route.name, action: route.requirements[:action], controller: route.defaults[:controller] }
    end
  end
end

RSpec.describe '画面に正常に遷移できるか確認' do
  IGNORE_PATH = [
    # 自動テスト対象外のpathを記載 
  ].freeze

  # 前提データが必要な場合は自動テストを行うのが難しいので、一覧と新規に限定
  admin_routes = AdminRoutingTestHelper.admin_routes(['index', 'new'])
  # 対象外のpathを除外
  target_routes = admin_routes.select { |route| IGNORE_PATH.exclude?(route[:name]) }
  url_helper = Rails.application.routes.url_helpers

  # 対象のpathの件数分、遷移しステータスコード200が返ってくることを検証
  target_routes.each do |route|
    describe route[:name] do
      before do
        visit url_helper.url_for(host: Capybara.app_host, controller: route[:controller], action: route[:action])
      end
      it "#{route[:controller]} # #{route[:action]}" do
        expect(page.status_code).to eq 200
      end
    end
  end

社内の検証環境にデプロイして、動作確認

テストのある部分はテストを全て通し、ない部分については先述の仕組みで確認したあと、ディレクターさんにも協力して頂き、業務上クリティカルな箇所について手で検証しました。

今回はマイナーバージョンアップということで、普段使っている本番相当の検証環境にバージョンアップを反映して検証を行いました。

本番デプロイ

通常業務に影響がなさそうという検証が出来たので、2018年10月18日にバージョン対応をmasterブランチにマージし、本番環境にデプロイしました🎊

VersionUp振り返り会

最後にバージョンアップの際に行ったことを整理して、KPTで振り返りを行いました。以下が出てきた内容の抜粋です🙇

Keep

  • 管理画面のテストを最低限ではあるが、自動的に行うことが出来た。

Problem

  • Gemfileで過去に色々な経緯からバージョンが固定されているGemがあり、月1のbundle updateで1年半程更新していないものもあった。railsのバージョンアップによる依存関係の解消時に大きくバージョン上げる必要があったため、検証負荷が高くなってしまった。
  • バージョンアップ用の環境を用意しておらず通常開発と同じ環境でバージョンアップの検証も行っていたため、通常開発業務の検証の際にバージョンアップを切り戻すといった作業が必要でメンテナンス負荷が高く、現状の検証環境のrailsのバージョンを把握しづらかった。

Try

  • Gemfileを読み解く会を開催し、経緯を理解した上で外せるものはバージョン固定を外す。
  • GemfileのVersion固定は、bundle updateのタイミングで見直す等の仕組み化を行う。
  • VersionUpのときは専用の環境を用意する。

Gemfileに記載されているgemがどのように使われているのか、なぜバージョンが固定化されているのかなどを読み解く会をやるといった今後のアクションに繋げることが出てきて、バージョンアップをするだけでなく、その過程で感じた問題等も話せたので振り返りいいのでは?という気持ちになりました🙌

おわりに

大分乗り遅れた感はありますが、今回はMedPeerをrails 5.2にバージョンアップした話でした。 現在6.0に関しても色々と情報が公開されてますが、次回の6.0に関しては乗り遅れずにバージョンアップ出来るように今回の反省を生かしていければと思います!

Railsフロントエンドボイラープレート「medpacker」の紹介

メドピアマッスル部のフロントエンドエンジニア村上(@pipopotamasu)です。

最近筋トレに時間を割かれ、家でコードが書く時間が減ってしまったのが悩みの種です。

今日は最近作ったメドピア用Railsフロントエンドのボイラープレート、「medpacker」を紹介しようと思います。

github.com

medpacker作成の背景

Railsには公式で大きく分けて2つのフロントエンドの環境があります、アセットパイプラインとwebpackerです。 これらはメドピアの既存プロダクトでも使ってきたのですが、プロダクトの規模が大きくなったり、時間が経つにつれて色々な辛みが見えるようになってきました。

アセットパイプライン

  • 最終的にJSやCSSのファイルを1つのファイルに出力するため、プロジェクトが大きくなってくるとファイルサイズが大きくなってしまう(キャッシュが効いてないと読み込みが遅すぎる、開発時のビルドに時間がかかる)
  • ES6+を使いたい場合はwebpack等のBundlerを自前で設定する必要がある(またはbundlerをwrapしているgemを使う必要がある)

webpacker

  • アセットパイプラインの欠点を解消(複数ファイル出力、webpackが設定済み)したのはよいが、webpackの設定がrailsにラップされすぎていてわかりづらい
  • 初期設定だとプロダクションビルドにsource mapがついていたりなど?な設定がある
  • webpack本体のバージョンアップについていけてない(webpackがv4なのに対して、webpackerはwebpack v3依存)

これらの辛みのため新規でRailsプロジェクトを作成する時、今まで通りアセットパイプラインやwebpackerで構築してしまっていいのかという疑問が生じてきました。 またフロントエンド開発をメインで行うのがサーバーサイドエンジニアや外部のフロントエンドエンジニアさんということもあり、プロジェクト間で採用技術や質を標準化するために、またフロントエンドの環境構築の時間短縮のためRailsフロントエンド用のボイラープレートを用意しそれを横展開するのがよいのではないか?

ということで、これらの辛みを克服するためにメドピア用Railsフロントエンド用のボイラープレート「medpacker」を作成しました。

medpackerのコンセプト

medpackerのコンセプトは大きく2つです。

素早く、簡単に導入できる

webpackerのような導入の簡単さを目指し、Railsのアプリケーションテンプレートを使用して設定できるようにしています。これによりrails newをしてから2~3分でフロントエンド環境を構築することができます。

だいたい開発や本番環境で必要なものが初期から設定されている

アプリケーションテンプレートで導入した直後から、webpack・babel・lint・postcss・minify等がすでにセットアップされているため、すぐに開発に着手できるようになっています。

Get started! 実際にmedpackerを導入してみる

それでは実際にmedpackerを導入してみましょう。

STEP1: medpackerをローカルにcloneする

$ git clone https://github.com/medpeer-inc/medpacker.git

STEP2: rails newした直後のrailsプロジェクトを用意する

$ rails new test-project

STEP3: アプリケーションテンプレートを用いて、先ほど作成したプロジェクトにmedpackerを適用する

$ cd test-project
$ bin/rails app:template LOCATION=path/to/medpacker/template.rb

この際いくつかCLIに質問されるので、用途に応じて答えてください。

remove 'app/assets'? y
remove 'test/'? y
need example page? y
Overwrite /Users/yamatomurakami/work/test-project/config/routes.rb? (enter "h" for help) [Ynaqdhm] a

STEP:4 railsを起動する

$ bin/rails s

サーバーを起動し、以下の画面が出たら導入完了です

( ※need example page?にyesで答えないとこのページは表示されません)。

f:id:ec0156hx39:20190122002939p:plain
medpacker_home

medpackerの中身について

作成に至った背景、コンセプトなどはすでに説明した通りです。ここではmedpackerの中身についてみていきます。

webpack

medpackerの核ともいうべきbundlerです。 もちろんフロントエンドのアセットをビルドするために入れてます。 Rails側でビルドしたアセットをHTMLに読み込むためのヘルパーを用意してあり、それを使うことで読み込むことができます。 productionモードでビルドするとCSS, JSがminifyされるようになっています。

webpack-dev-server

webpackでの開発をサポートするツールです。ざっくり以下のような機能があります。

  • JSを変更した時差分のビルドをしてくれる(webpackのwatchと同じ)

  • リロードせずに更新したファイルがブラウザに適用される(Hot module replacement, HMR)

  • 上記のHMRができない場合は自動的にブラウザをリロードし、更新分のアセットを取得する

CSS(SCSS), PostCSS

導入時点で、SCSSとPostCSSの設定がされています。

(※メドピアでは全てのRailsプロジェクトでSCSSを使用しているので、決め打ちで入れてあります)

またPostCSSで初期導入されているプラグインは以下2つです。

  • autoprefixer・・・自動的にベンダープレフィックスをつけてくれるライブラリ
  • postcss-flexbugs-fixes・・・ブラウザが潜在的に持っているflexboxのバグを踏まないように、自動整形してくれるライブラリ

babel

JSを色々なブラウザで読み込めるように(例えば最新の記法が古いブラウザでも読み込めるように)変形/代替してくれるライブラリになります。 導入時点で設定済みなので、IE11とか気にせずにJSを書いても問題ありません。

基本的にメドピアの推奨環境に合わせてありますが、この辺をいじれば対応ブラウザを変えることができます。

lint系

SCSSのlint(stylelint)とJSのlint(eslint)の2つが設定済みです。導入側のプロジェクトのCIに組み込んでおいてください。

Vue.js

medpackerに入れるか迷ったのですが、導入時にVue.jsが初期設定してあります。 個人的にJSライブラリを入れるのは本当に必要になった時に初めて入れればいいと思っているのですが、プロジェクト間での採用技術を統一するために入れてあります(以前とあるプロダクトで外部のエンジニアさんにお手伝いしていただいてた時、社内のほとんどのプロジェクトでVue.jsを使っているにも関わらず、しれっとReactが入っていたことがあったので...)。

工夫したところ

ライブラリアップデート

月1回のペースで、自動的にgemとnpmのアップデートPRがCIで作られるようになっています。 作成後は私がPR内容の確認・マージをしています(この辺は手動です)。 「medpackerを適用しようとしたがバージョンが古い...」というメンテされずに放置されるという事態は避けるようにしています。

アプリケーションテンプレートの使用

より楽にプロジェクトにmedpackerを適用するためにRailsのアプリケーションテンプレートを使用しました。 最初はこの便利機能の存在を知らずに、こちらの方法をメインの適用方法にと考えていました。今考えるととてつもなく使いづらいですね。。。

終わりに

現在メドピアでは3つのプロダクトでmedpackerを使用しています。 使っているうちに出てくる改善点や追加機能などは日々更新していく予定です。

もしこのブログを見た人で「うちではこんなの使ってるよー」とか知見がある人はこっそり教えていただけたらありがたいです。medpackerに取り入れるかもしれません。

またこのmedpackerを作る上でpixivさん、スタディストさんのブログを参考にさせていただきました。本当にありがとうございました。

今日から簡単!Webpacker 完全脱出ガイド - pixiv inside

フロントエンド原理主義者が目論んだ脱webpacker – スタディスト開発ブログ – Medium


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

エンジニアのスキル底上げを目的として『テックサポート制度』を始めました!

こんにちは!メドピアエンジニアの難波です。

今回はメドピアで先月(2018年12月)から始まったテックサポート制度について紹介させて頂こうと思います。

『テックサポート制度』とは?

『テックサポート制度』とはエンジニアの開発力を底上げしてメドピアの事業開発を加速させることが目的の、1人あたり年間12万円まで開発効率・スキルの向上に関わるサポートを行う制度です。

最近色々な企業で同様の「AWSやGCPを積極的に触ってもらうために年間(月間)○○円まで個人で自由に使える制度を作りました!」という声を聞くようになりましたが、弊社ではAWSやGCPのようないわゆるIaaS以外にもElastic CloudやHerokuなどもOKです。他にもRubyMineやDashのような開発効率促進系ツール、珍しいものだとGo RailsやUdemyのようなオンライン学習サービスについてもサポート対象です。

サポート対象は基本的に社内ドキュメントに記載されているリストにあるものということになっておりますが、現場のエンジニアからCTOやエンジニアマネージャーに要望を挙げて、これは良さそうだねと判断されたものはすぐにリストに追加されるようになっています(まだ始まったばかりの制度なのでどんどんアップデートしています)。

ちなみに一部を抜粋すると現状このようなものが載っています。

実際に使ってみた感想

私の場合は早速以下の2つのツールにテックサポート制度を使いました。

  • Tower
    • 評判の良いGUIのgitクライアント。普段はCUIでgitコマンドを実行するのですが、デザイナの人に勧めることもあるので使い勝手を試してみたかったため
  • Microsoft Azure
    • AWSやGCPはよく使うのですが、Azureはあまり触っていなかったのでこの機会に使ってみることにしました

テックサポート制度が始まってからの印象ですが、普段良さそうなツールを見つけても有料だと「必要になったら改めて……」となりがちなのが「とりあえず試してみるか、サポートされるし。」に変わるのは心理的な障壁をなくす効果という点でとても良いなと感じています。

また自分自身での活用についてだけでなく、同僚(特にまだ経験の浅い人)に対して有料ツールを勧めやすいという効果もありました。経験の浅い人にこそ有料でも便利なツールを積極的に使ってもらうことで成長のきっかけとしていって欲しいのですが、今までは「オススメなんだけどちょっと高いんだよなあ」というように躊躇することがありました。それが「とりあえずテックサポートで試してみてよ」と言えるようになったのは良いですね。

メドピアのエンジニア支援制度

今回のテックサポート制度導入によってメドピアで行っているエンジニア支援の制度やイベントは以下のようになりました。

  • 書籍支援制度
  • イベント(カンファレンス等)参加支援制度
  • 開発合宿
  • ランチLT
  • 輪読会
  • 週次KPT
  • プルリク振り返り会
  • テックサポート制度 <- NEW!!

今後もメドピアではエンジニアがよりパフォーマンスを発揮できる環境づくりに注力していきますので、興味が有る方のご連絡をお待ちしております!


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

新人エンジニアが開発合宿に参加してみて@湯河原

こんにちは!メドピア10月入社の新米エンジニアの宮原です。 今回のブログでは、メドピアで恒例となっている開発合宿に参加してきましたので、こちらの様子をお届けしたいと思います。

メドピアでは、これまでにも年2〜3回ぐらいのペースで開発合宿を開催しています。湯河原で開発合宿を行うのは、昨年3月以来になります。

tech.medpeer.co.jp tech.medpeer.co.jp

合宿テーマ

開発合宿のテーマは毎回異なり、技術研鑽や技術的負債の解消、他にも新規サービス立ち上げ等を行ったこともあります。過去の開発合宿では新規サービス立ち上げをテーマに実施され、弊社のサービスとして事業化されているものもあります。

合宿に行く前に各自、取り組む内容について宣言してから開発します。今回はこんな感じです。

  • 業務改善ツールの開発
  • メドピア既存サービスへの新機能開発
  • 新技術を使ったサービス開発

取り組み方は自由でチームを組んでも良し。個人でモクモクと取り組むも良し。特に制約は無いので、自身が取り組みたかった開発がしやすいです。 後日、オフィスにて合宿に参加できなかったエンジニアやデザイナーさんたちへ、成果報告LTをすることになりました。

開発合宿向きの旅館「湯河原 おんやど 恵」さん

今回の合宿は湯河原の「おんやど 恵(めぐみ)」さんにお邪魔しました。メドピアでは過去の合宿でも利用させていただいております。こちらの旅館は、SE出身の社長さんが経営されている旅館で、エンジニアに嬉しい「開発合宿プラン」などが用意されています。お隣にコンビニができたこともあり、お酒やお菓子などの補給線が確保されより開発向きになりました。

f:id:nyagato_00_miya:20181212153651p:plain

おんやど恵み 開発合宿プラン

当日は、湯河原駅に直接集合!湯河原駅近くの「トルティーノ」さんでランチをとってから一同、おんやど恵へ向かいます。

f:id:nyagato_00_miya:20181212153942j:plain
総勢15名の参加となりました!

開発の様子

到着後すぐに会議室へ向かいます。各々合宿で取り組むテーマを発表し、いざ開発スタートです。

会議室には、電源タップ、USB充電器、おやつ、ホワイトボード、腰サポートグッズ等、設備も充実。開発スタートから、もくもく作業をする人もいれば、リフレッシュも兼ねて一足先に温泉に浸かりに行く人も。 ※ディスプレイのレンタルプランもあるそうです。

f:id:nyagato_00_miya:20181212154443j:plain
今回のテーマをそれぞれ発表し、いざ開発開始です
f:id:nyagato_00_miya:20181212154251j:plain

基本的に、食事・お風呂・就寝以外の時間は開発タイムです。初日から夜遅くまで開発に没頭するメンバーもいました。

f:id:nyagato_00_miya:20181212154705j:plain
斯く言う私も、モクモクしていました

湯河原ご飯レポート

※美味しそうなご飯の写真が続きます。空腹時の閲覧はご注意ください

f:id:nyagato_00_miya:20181212155007p:plain f:id:nyagato_00_miya:20181212155013p:plain f:id:nyagato_00_miya:20181212155017p:plain

f:id:nyagato_00_miya:20181212155021p:plain
十二庵さんの豆腐プリンは絶品でした

最終日にランチに行った「うおたつ」さんには足湯もありました。 湯河原では、"足湯駆動開発"が大変捗ります。

最終日

2泊3日の楽しい合宿を終え、成果発表を行います。
技術研鑽に務める人もいれば、がっつりと作り込みデモまでする人まで各々の成果が発表されました。今回の合宿では、最も優れた発表には商品が進呈される!とのことで、みんな気合の入った発表が多かった印象です。

f:id:nyagato_00_miya:20181212154900p:plain
合宿の成果が発表されました

画像認識に取り組んでみました

私は、“食品判別AI”を作ってみました。メドピアにはグループ会社からDiet Plusというアプリがリリースされています。ユーザーから送られてきた食べ物の写真を、管理栄養士さんが確認して健康サポートをしてくれます。
そこで、食品の判別は自動化できそうだなと考えていたこともあり、合宿でやってみることにしました。

学習データの加工や、ニューラルネットワークの構築に時間を要しましたがなんとか形にすることができました。 今回は、GCPにVMのインスタンスを立てて、この中でSystemd + Nginx + uWSGI + Flaskのアプリケーションを動かしています。

f:id:nyagato_00_miya:20181212173511p:plain
お寿司が正しく判別された様子。

TensorFlowのサンプルの中に、再学習するサンプルが用意されています。簡単に画像認識を試す場合は、こちらを活用してみてください。
便利なことにTensorFlowでは、dockerイメージが公開されています。こちらを活用することで、めんどうな環境構築を一瞬で終わらせることができます。
(公式から公開されていると安心感がありますね) https://www.tensorflow.org/install/docker

例えば、猫の分類など行ってみましょう。ロシアンブルー、ペルシャ、メインクーン、ベンガルなどの画像を10枚程度集め、それぞれディレクトリに入れます。 こちらのディレクトリを指定して再学習を実行します。

$ cd cats
$ python3 retrain.py --image_dir ~/cats

学習結果を確認するには、label_image.pyを使います。以下のファイルをGithubからダウンロードし、retrain.pyと同じディレクトリに置きます。 https://github.com/tensorflow/tensorflow/raw/master/tensorflow/examples/label_image/label_image.py

以下の様に、再学習で生成された学習データを活用して判定させます。

$ python3 label_image.py \
--graph=~/tmp/output_graph.pb \
--labels=~/tmp/output_labels.txt \
--input_layer=Placeholder \
--output_layer=final_result \
--image=/cats/test/test_cat.jpg

するとどうでしょう、入力した猫の画像から、猫の種類を判別してくれます。学習データが10数枚であれば、ローカル環境で十分学習させることが可能です。
例で述べさせていただいた内容は、公式にチュートリアルとして掲載されています。ぜひ、トライしてみてください。
https://www.tensorflow.org/hub/tutorials/image_retraining

まとめ

開発合宿では、普段の業務でなかなか取り組めないタスクや負債を潰したり、新しい技術に集中して取り組める絶好の機会だと思います。 また、2泊3日という短い時間で成果を出す必要があるので、自身がこの短期間にどこまで出来るかを確認できる良い機会でもあると思います。 以上!2泊3日のメドピア開発合宿@湯河原 おんやど 恵のレポートでした。

追伸

合宿後の発表会で、僭越ながら私が、kenzoさんと同着で表彰されました。 まさかの同着1位ということもあり、2人で商品同等額を山分けさせていただきました。
頂いた賞金は、HHKB 無刻印を買う軍資金にさせていただこうと思っています。


(☝︎ ՞ਊ ՞)☝︎是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html