読者です 読者をやめる 読者になる 読者になる

OSS Gate in Speee

株式会社Speeeの@selmertsxです。

今回は、2016年6月11日(土)に、弊社にて行った OSS Gate ワークショップについて、 ご紹介させて頂きます!

OSS Gate について

OSS Gate は、「OSSの開発に参加する」を実際に体験できるワークショップです。
株式会社クリアコードの代表取締役をされている、須藤功平さんが講師として活動されています。

OSSの普及を目的として始まり、今回で4回目となっています。

ワークショップの流れ

ワークショップ全体の流れは下記のようになっています。

  • ワークショップの説明
  • コミットしたいOSSを選ぶ
  • 選んだOSSのドキュメントを読み、動かしてみる
  • 改善したい点を見つけたら、issue/PRを作る
  • ワークショップの振り返り

ワークショップの説明

f:id:mogmog2:20160624185212j:plain ※ ワークショップについて説明を受けているエンジニア

ビギナーとメンター

ワークショップは、ビギナー、メンターと立場を分けて行いました。

OSSの開発に参加したことない、もしくは参加したことはあるけど、自信がないといった人がビギナー。 OSSの開発に参加したことがある人がメンターとなって、役割分担してワークショップを進めます。 メンターのお仕事は、ビギナーが困ったときに話を聞き、意見を求められたら答えるといった形でビギナーのサポートを行うことです。

僕は、OSSの開発に参加したことはほとんどないのですが、 人数の関係で2人のビギナーのメンターとしてワークショップに参加させて頂きました。

作業ログ

ビギナーは、個人のgithub issueにログを残しながら作業を進めていきます。 メンターは、ビギナーの作業を直接見たりログを眺めたりしながら、 ビギナーの作業進捗を追います。 ログには、現在の作業内容と、思っていること、そして必要なら備考を残してもらいます。

ログを細かく残すことによって、問題が発生したときに、何が原因だったのか振り返り、 そのときのログなどを、issue報告をする際に活かすことが出来るようになります。

・ 作業内容: gem install
・ 感想: dependencies多すぎ

※ 作業ログのサンプル

コミットしたいOSSを選ぶ

ビギナーは、これから貢献するためのOSSを選びます。

今までお世話になってきたOSSや、 これから使おうとしているOSSを、 貢献する対象のOSSとして選んでいる人が多かった模様です。

僕が見ているビギナーの人は、 それぞれ delayed_jobsimple-rss を選んで作業を進めていました。 両方共、次に仕事で使うから早くキャッチアップしたいという、かなり現実的な理由でした。

なおメンターは、コミットしたいOSSを選ぶことは出来ません。 基本的にずっとビギナーの方を見守ります。 僕も、羨ましいなと思いながら見守っていました。

選んだOSSのドキュメントを読み、動かしてみる

f:id:mogmog2:20160624185215p:plain

READMEを上から眺めながら、実際に gem install し、動作確認を進めていきます。 業務の中では、必要なところだけつまみ読みすることが多いので、頭から全部読むのは 少しばかり懐かしい感覚です。

改善したい点を見つけたら、issue/PRを作る

f:id:mogmog2:20160624185217p:plain

一通りドキュメントを読み込み、実際にgemを動かしてみて、 貢献できるチャンスを見つけたら、issue/PRを作っていきます。

幸い(?)にも、delayed_job, simple-rssともに、 手順書をそのままなぞるとエラーが出てしまう問題があったため、 その修正PRを出すなどしました。

https://github.com/collectiveidea/delayed_job/pull/919
https://github.com/cardmagic/simple-rss/pull/25

また、参考となるReadmeを探している間に fluentd-doc のエラーも見つけたため、 さくっと修正してました。(ota42yさんすごい!)

https://github.com/fluent/fluentd-docs/pull/229

ワークショップ振り返り

最後に、ワークショップの成果や感想などを、 みんなで issue に書いて振り返りました。 みんな、何らかの形で貢献できた模様です!

今まで敷居が高いと考えていた、OSS貢献への第一歩を踏み出せて、 みんな満足していました。

ワークショップとその後

今回のOSS Gate は、弊社の技術力アップを目的として開催されました。

すぐに目に見える効果が出るほど、世の中甘く無いですが、 いくつかのPRがマージされるなどし、 参加者のOSS活動への心理的な障壁は随分取り除かれてきたのかな という印象を受けました。

また、PRがマージされた何人かのエンジニアは、 OSS貢献への自信もついたのかなと思います。

これまで利用している gem などで問題が発生したら、 その問題を回避する形で業務を進めていましたが、 貢献チャンスと受け取って逆にテンション上げるように なったメンバーも少なからずいた模様です!

※ マージされたPR

https://github.com/gimite/google-drive-ruby/pull/206

https://github.com/rurema/doctree/pull/275

最後に

OSS Gateでは定期的にワークショップを実施されてます。 1ヶ月後の7月開催分はすでにキャンセル待ちと大盛況です。 すでに9月分も募集が始まっていますので、OSSに興味のある方はぜひ! https://oss-gate.doorkeeper.jp/events/46275

またSpeeeではOSS活動をしたいエンジニアを募集しています。 Ruby,Scala,Go,iOS,Androidと様々な募集をしていますので、興味のある方はぜひ!

ASEAN6億人にあたらしい転職サービスを届けるエンジニアを募集! https://www.wantedly.com/projects/44504

「嫌われる広告から好かれる広告へ」未来のスタンダードを創るエンジニア募集! https://www.wantedly.com/projects/58311

アプリでライフスタイルを変えていく、iOS/Androidエンジニア募集! https://www.wantedly.com/projects/57015

あんしん大規模リプレースサポート【社内勉強会レポート#2】

FuelPHP Ruby 社内勉強会

社長室エンジニアの id:takanamito です

@hiragramによる前回の technica-blog.jp につづき 今週の僕の発表もレポートさせていただきます。

トークテーマ

あんしん大規模リプレースサポート

キーワード

  • Rails
  • リプレース
  • kage
  • nginx
  • Datadog

発表スライド

質疑応答

nginxでリダイレクトをしなかったのはなんで?

マスタデータに基いて生成されるURLが存在し、マスタ刷新によりDBから新旧マスタの対応を取得してリダイレクトさせる必要があったため

kageに流すリクエスト量をスライドの中の数値に絞ったのはどういう理由?

  • kage導入にあたって検証時間があまり取れなかったため、障害時に影響を小さくするため
  • kageはthinで動かしていたが、どの程度の負荷に耐えられるかわからなかったので 1req/s以下になるように調整

所感

3月ごろに行ったリプレースについて、まとめて発表しました。

質疑応答ではkageに質問が集中したりと、シャドウプロキシを使った検証については社内に事例がなかったためみんなも興味津々だったので発表できてよかったです。

またDatadogを使ったnginxのモニタリングについても、fluentdの設定など社内リポジトリで公開しているので これから他チームへの導入の手助けになればと思っています。※そのうち社外にも公開したい。

YAPC::Asia Hachioji 2016にSpeeeから2名が登壇します #yapc8oji

こんにちは。エンジニアの@hiragramです。

7月2日(土)〜3日(日)に品川にて開催される、YAPC::Asia Hachioji 2016にSpeeeからエンジニア2名が登壇することになりました。

トークする内容を簡単に紹介させていただきます。

[1日目] DMM英会話はいいぞ(LT)

github.com

エンジニアには英語力が必要、とはいえガリガリ勉強するのはだるいし時間ないし…というあなたのために、4ヶ月DMM英会話を続けた体験談をお話します。 DMM英会話の仕組み、どんな先生とどんなレッスンをするのか、教材について、モチベーション維持、感じた効果などについてトークします。 果たして僕は会社の金でWWDCに行けるのだろうか…!

[2日目]しくじり先生 〜 アドネットワーク開発でしくじった話

  • @suthio
  • 7/3(2日目) 10:00~ Bルーム

github.com

今年の1月から広告配信システムの開発をしています。 開発した際に盛大にしくじってきたので、 僕が「しくじり先生」としてが僕と同じ失敗を他の人が犯かさないように「今回の開発の問題点と教訓」を伝授します

よろしくお願いします!

会場でお話できるのを楽しみにしています!

参加登録はこちらから

yapcasia8oji-2016mid.hachiojipm.org

Swiftでニコ動風実況ツールを作った【社内勉強会レポート#1】

iOSエンジニアの平山@hiragramです。

Speeeでは週に1回すべての事業部のエンジニアが集まる全体MTGで持ち回りで15分~20分程度の発表をしています。今後は発表内容を社内勉強会レポートという形で記事にしていきたいと思います。

今回は僕が発表したので、そのレポートです。

トークテーマ

Swiftでニコ動風実況ツールを作った

キーワード

  • Swift
  • OSXコマンドラインアプリケーション
  • Slack Realtime Messaging API
  • AppKit

発表スライド

f:id:hiragram:20160531140214j:plain

質疑応答

OSXのバージョン依存はどれくらいあるのか

APIの追加/廃止はそこまで激しくないけど、最新のOSで動かしたかったら最新のXcodeでやってねみたいなのはあるので気合でついていく必要がある。

改行を取り除くあたりに闇が少し見えた

(stringByReplacingOccurrencesOfStringメソッドの名前の件)

Appleデベロッパーならこの手のやつは全部覚えてて当然ですね。僕は覚えてません。

所感

OSXのAppKitは普段触ってるiOSのUIKitとはなかなか毛色が違って新鮮な気持ちでした。

今のSpeeeはRubyエンジニアがほとんどなので、iOSエンジニアが喋って面白いことってなかなかひねり出すの大変でした。

デモも結構盛り上がったかなと思っているので、今後社内勉強会等でみんなが使ってくれたら嬉しいです。

Google Apps Scriptの開発をモダンに行う方法

株式会社Speeeの山本です。皆様、こんにちは!

今回ご紹介させていただくのは、Speeeで実践しているGoogle Apps Script(以下 GAS) を用いたモダンな開発手法についてです。この記事を通してGASって「便利だし使えるかも!」と思っていただければ幸いです。

Google Apps Scriptとは

Google Apps Scriptは、言わずと知れたGoogleが提供するサーバサイドのスクリプト環境です。 基本的にはWebブラウザを通して開発を行います。 f:id:bino98ty:20160428185259p:plain

作業効率化に威力を発揮するGAS

Speeeでは特に、管理部門の作業効率化でGASを使用しているケースが多く、例えば

  • Slackの制限付きユーザを各種チャネルに招待するアプリケーション
  • メーリングリストの文面生成を自動化するアプリケーション
  • Speeeラウンジの使用状況を閲覧するアプリケーション

など、様々な用途でGASが使用されております。 また、GASはGoogle ドキュメントやGoogle スプレッドシートなどへの強力なAPIが用意されており、Google Driveを日常的に使用している環境では、特にGASを利用する利便性を見込めるのではないかと思います。

こんなに便利なGASですが、単なる作業効率化ツールとしての枠を超え、1つのアプリケーション開発に、GASを使用するケースも登場します。

開発事例の紹介

経理業務支援のアプリケーション開発にGASを採用

現在私は経理業務支援のアプリケーションを開発しているのですが、メイン機能はGoogle スプレッドシートとGASのみで開発しています。 経理業務支援のアプリケーションでは、 - クライアント様への売上/請求の一覧化 - 入金情報の管理 - 請求書発行と送付 という業務の自動化や効率化を行っています。

秘匿性の高い情報をGoogle スプレッドシートに預けることに対しての不安に思うかもしれませんが、 Google Appsが持つ強力なユーザ管理機能や、端末<->サーバ間の通信のセキュリティ対策を十分に行っているGoogle Appsを利用する方が、 オンプレでサービスを設置したり、他のクラウドサービスへホスティングしたりするより、信頼性が高いと思っております。

技術選定の場に於いて、下記のような理由でGoogle スプレッドシートとGASに利用が決定しました。

  • ユーザインターフェースを作成する工数の大幅カットが見込める。
  • Google スプレッドシートは 経理担当者 が直接システムを変更する余地がある。
    • (経理業務ドメインは難解のため、エンジニアと現場の方と共同で開発していきたかった)
  • 経理の方にとってGoogle スプレッドシートはExcelに似ているため新システムの学習コストが低い。

すべてWebブラウザで完結できることは上記のような利点もありますし、良いことのように思えます。 しかしエンジニアとしては、自分の好きなエディタを使って開発をしたいし、バージョン管理したいし、テストも書きたいし...と思うわけです。

Google Apps Scriptの開発をモダンに行う方法

Google Apps Scriptをローカル環境で...

今年の1月のことです。Googleのデベロッパーブログに下記の記事が公開されました。

コマンドラインから Apps Script プロジェクトをアップデートするためのコマンドラインインターフェース(CLI) が公開したとのこと。早速導入してみました。

使い方

本CLIを利用するためには、下記が必要です。必要に応じてインストールしておいてください。

  • node v0.12.x 以上

早速インストールして使ってみましょう。

$ npm install -g node-google-apps-script

Google の Developers Console から gappsで使うための OAuth2、その他のアプリケーション としてキーを発行します。詳しくはnode-google-apps-scirptのGitHubを見ていただければと思います。 https://github.com/danthareja/node-google-apps-script#11-default-apps-script-developer-console-project

無事に発行ができたら、キー情報が含まれたJSONを落としてください。あとは、インストールしたてのgappsコマンドを用い、認証をします。

$ gapps auth ./client_secret_<client_secret_key>.json

上記コマンドを打つと、

Please visit the following url in your browser (you'll only have to do this once): https://accounts.google...

などと表示されるはずなので、URLを踏んで認証してください。

Successfully Authenticated with Google Drive!

と、表示されるはずです。 gapps authで行った認証の情報については、ホームディレクトリ以下の.gappsに保存されます。

認証を無事に終えたら、gappsコマンドで管理するGASのファイルを指定します。 Google Drive上でGASのファイルを生成し、 ブラウザ上のエディタでスクリプトを保存してください。 f:id:bino98ty:20160428185257p:plain

そのURLにある Project ID をコピーして、下記のコマンドに貼り付けてから、実行してください。 f:id:bino98ty:20160428185258p:plain

$ gapps init <Project ID>
# Example
# gapps init jiofe3g4jHfr5dekD5deNIO9e...

いかがでしょう。ローカルに下記のGASのファイル達が落とされたと思います。おめでとうございます!

.
├── gapps.config.json
└── src
    └── コード.js

あとは、よしなにファイルを編集して、下記のコマンドを実行すると、ブラウザ上のGASも更新されているかと思います。

$ gapps upload

また、gappsコマンドを使うとき、下記のことを知っておくと良いかもしれません...!

  • GASにアップロードされるファイルは、jsファイル、htmlファイルのみです。
  • jsファイルは、アップロードのタイミングで、gsファイルに自動で変換されます。
  • リモートからローカルにファイルをダウンロードできるのは、この時だけです。例えば、gapps init した後に、ブラウザのエディタでコードを編集しても、ローカルには落としてこれません。

ローカルに落とせたということは...

GASのファイル郡をローカルに落とせるようになったということは、下記のことが可能になりました。

  • GitHubによるバージョン管理が可能になりました。
  • テストも書くことが出来るようになりました。
  • タスクランナーを用いることで、ECMAScript2015(以下 ES2015)記法やTypeScriptをローカルで書いて -> ES5に変換 -> アップロードというフローでの作業が可能になり、Googleへのアップロードを自動で行うこともできるようになります。

ここからは、応用編として上記3つの方法の実施についてもご紹介します。

応用編1: GitHubによるバージョン管理

早速やっていきましょう。 まずは、GitHubにRepositoryを作成し、リモートを追加します。

$ git remote add origin git@github.com:ユーザー名/プロジェクト名.git

次に、Gitの初期化を行い、管理対象のファイルをコミットします。

# GASを落としてきたディレクトリ上で...
$ git init

あとは、ファイルをよしなに編集し、add/commit/push!

$ git add .
$ git commit -m 'initail commit'
$ git push origin master

いかがでしょう。GitHubのリポジトリページを覗いてみてください。GASのファイル達がお待ちです。

応用編2: テストを実施

先述のGoogleのブログにもあるように、スクリプトをローカルに落とせれば、機能テストを書くことも可能です。

今回は、テストフレームワークにmocha、アサーションライブラリにchaiを導入してテストを書いてみます。

$ npm install -g mocha
$ npm install -g chai

次に、テスト用のjsを置くディレクトリを作ります。

$ mkdir test

あとは、テストを書いてあげてください。

プレーンなJavaScriptでnodeのrequire()を利用するため、今回は Browserify + Gasify を使ってみます。Gasifyはjs2gsのBrowserifyプラグインとなります。

$ npm install -g browserify
$ npm install -g gasify

GASにアップロードされるのはデフォルトの設定ではsrcに入っているjs、htmlファイルだけなので、

.
├── gapps.config.json
├── dev
│   └── hello.js # テスト実行先のJS
│   └── main.js  # browserify元JS
├── src
│   └── main.js  # browserify先JS
└── test
    └── hello_spec.js  # テスト元のJS

というディレクトリ構成を作り、コードの実態をdevディレクトリ以下に書き、テストをtestディレクトリ以下に記述していきます。

まずは、下記のようにhelloメソッドに対するテストを書きます。

var chai = require('chai');
var should = chai.should();
var hello = require('../dev/hello');

describe('code.js', function() {
    context('echo', function() {
        it('should return Hello yamamoto when the value is yamamoto', function() {
            hello('yamamoto').should.equal('Hello yamamoto');
        });
    });
});

そして、実態を用意します。

module.exports = function(name) {
  return 'Hello ' + name;
}
var hello = require('./hello');
global.callHello = function () {
  Logger.log(hello('yamamoto'));
}

さて、ここでテストを実行してみます。

$ mocha
  code.js
    echo
      ✓ should return Hello yamamoto when the value is yamamoto


  1 passing (7ms)

無事にテストが通りました!

そして、browserifyにsrc/main.jsを出力させアップロードし、GASとして使えることも確認します。

$ browserify dev/main.js -p gasify -o src/main.js
$ gapps upload

GASのエディタ上からcallHelloを選択、実行すると、

f:id:bino98ty:20160428185300p:plain

ツールバーから 表示 > ログ で出てきた画面上に、Hello yamamotoと表示されていますね。

f:id:bino98ty:20160428185301p:plain

これで、helloメソッドの機能テストがかけるようになりました!良かった。

応用編3: Gulp連携

さて、ES2015で盛り上がる昨今、GASもES2015で書きたいと思うエンジニアの方も多いはずです。 プロトタイプベースのオブジェクト指向であったES5と比べ、Rubyや他の言語で見られる クラスベースのオブジェクト指向を取りいれたES2015ですが、 普段からRubyやJavaを書いているサーバサイドエンジニアにとっても、Javascriptを書く障壁が低くなること、間違いないです。

さて今回は、Babel + GulpでES2015 -> ES5変換する手法を取り入れます。

まずは、Gulpのインストールからです。 1つ1つ$ npm install...するのがめんどくさいので、今回はこちらでインストール時に発行されたpackage.jsonを使います。 gapps initしたディレクトリに下記のJSONを保存します。

{
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-core": "^6.7.4",
    "babel-preset-es2015": "^6.6.0",
    "babel-register": "^6.7.2",
    "gulp": "^3.9.1",
    "gulp-babel": "^6.1.2",
    "gulp-exec": "^2.1.2",
    "gulp-load-plugins": "^1.2.0",
    "gulp-plumber": "^1.1.0",
    "gulp-mocha": "^2.2.0",
    "browserify": "^13.0.0",
    "babelify": "^5.0.5",
    "gasify": "^0.0.1",
    "vinyl-source-stream": "^1.1.0",
    "mocha": "^2.4.5",
    "chai": "^3.5.0"
  },
  "babel": {
    "presets": ["es2015"]
  }
}

今回、ES2015で書かれたコードは、browserify -> babelify(+ gasifyプラグインを適用)という流れで、GASへのアップロードを行うファイルを生成します。 babel6系を使用する最新のbabelifyを使い、トランスパイルするとGASのアップロードする際に、失敗してしまうことがあります。 ですので、今回はbabel5系を使用するbabelify5.0.5を採用しています。

そして、同一階層上でインストールを実行します。

$ npm install

さて、あとでES2015を記述するディレクトリと、ES5をしまうディレクトリを作成します。また、ついでにgapps uploadも同じタイミングで実行してもらいます。

先述の通り、gapps uploadは、srcディレクトリのみをアップロードしようとするため、GASへ出力するJSの吐き出し先はsrcとします。

今回は下記のようなディレクトリ構成で実行していきます。

.
├── gapps.config.json
├── gulpfile.babel.js # gulpのタスクを実装するJS
├── dev_es2015   
│   └── hello.js # テスト対象のJS
│   └── main.js  # browserify元JS
├── src
│   └── main.js  # browserify先JS
└── test
   └── code.js   # テスト元のJS

下記のファイルをリポジトリルートに置いてください。

import gulp from 'gulp'
import gulpLoadPlugins from 'gulp-load-plugins'
import browserify from 'browserify'
import source from 'vinyl-source-stream'
import runSequence from 'run-sequence'

const $ = gulpLoadPlugins()
const src_es2015_file = 'dev_es2015/**/*.js'

gulp.task('gas-upload', ['browserify'], () =>
  gulp.src('.')
    .pipe($.exec('gapps upload'))
)

gulp.task('test', () =>
  gulp.src(['test/**/*.js'], { read: false })
    .pipe($.mocha({ reporter: 'spec' }))
)

gulp.task('browserify', ['test'], () =>
  browserify({
    entries: ['dev_es2015/main.js']
  }).transform('babelify')
    .plugin('gasify')
    .bundle()
    .pipe(source('main.js'))
    .pipe(gulp.dest('src'))
)

gulp.task('watch', () =>
  gulp.watch(src_es2015_file, ['test', 'browserify', 'gas-upload'])
)

また、hello.jsも、下記の通りES2015ライクな書き方にし、それに合わせてtestも修正します。

export default (name) => 'Hello ' + name
import chai from 'chai'
import hello from '../dev_es2015/hello'
var should = chai.should()

describe('hello.js', () => {
    context('echo', () => {
        it('should return Hello yamamoto when the value is yamamoto', () => {
            hello('yamamoto').should.equal('Hello yamamoto')
        })
    })
})

それでは最後に、gulpを走らせてみましょう。

$ gulp watch

gulpを走らせているときに、dev_es2015の中身に変更があれば自動でテスト/browserify/babelifyを実施。さらに自動でGoogleにコードを送るようになりました。

f:id:bino98ty:20160428185256p:plain

このgulpfileでは、下記を走らせています。

  • watchタスクで、dev_es2015ディレクトリに変更があるかを常にチェック
    • 変更があったら下記のタスクを実行
  • testタスクでは、mochaによるテストを実行
  • browserifyタスクでは、browserify -> babelify(+ gasifyプラグインを適用)を実施
  • gas-uploadタスクでは、gapps uploadを実行

これにて、めでたく、GASをES2015で記述できるようになりました。

まとめ

いかがでしたでしょうか。 Google Apps ScriptはGoogle Driveの連携が非常に簡単に行えることに加え、GASをより便利にするようなライブラリもGoogleが幾つか提供してくれています。(例えば、OAuth2認証を行うこちらなど)

また、Slack連携も簡単に行えるので、普段からDriveを利用しているかたなど、ちょっとした効率化を行う際の何かの参考になれば良いと願っております。

それでは、良きGASライフを!