船木俊介「ハッカーズランド」

スーパーソフトウエア東京オフィス代表&キッズラインCTO

最近のWebサービス開発フロー,WerckerでGithubのプライベートリポジトリからAWSへデプロイしてHipChatへの通知まで

カラーズではWebサービスの開発を行っていて、スーパーソフトウエアでは業務系や公共系のシステムから、Webサービス、スマートフォンアプリといったアジャイルなものまで幅広く行っています。
 

同じシステム業界といっても、業務系とWeb系では別の業界といっていいくらい重視するポイントや開発フローが違っていて、エンジニア個人の裁量も異なるので、業務系で長く経験を積んできたという人でもWebサービスの開発現場に慣れるまで戸惑うことも多くあります。これからは転向する人も多いと思うので、Webサービスの開発フローを簡単に紹介しておきたいと思います。

 flow

僕がみているWebサービスの開発現場では、チームメンバーがコードを書き、GitHubでのプルリクエストベースで最終的にmasterブランチにマージされたコードはCIサーバでテストして、テストにパスしたものが自動でステージングやサービスサーバにデプロイされる仕組みにしています。
 

チームコミュニケーションでは、もう社内コミュニケーションにメールを使うことはほとんどなくなってチャットがメイン(いつの間にかメールは時代遅れ)、ファイル共有なんかもチャットで行い、コードレビューはGitHubのpull requestで、サーバはAWS、遠隔でのやりとりが必要な場合はSkypeで、といった感じ。
 

あとはエンジニア個人のマインドをどう作るかというところも大切なポイント。仕事の話や雑談も含めてコミュニケーションをより多く取れば行き違いが当然少なくなるし、結束力も高くなるのはどんな仕事でも同じだけど、基本的にエンジニアというのは高倉健なみにしゃべらないもの。10人の開発チームは10人の高倉健だと思って、コミュニケーションしやすいツールを整備。
 

Webサービスやスマートフォンアプリの開発では、ユーザへ提供する価値も移り変わりが速く、エンジニア個人の活躍の幅も格段に大きい。優秀な人は言語を問わず開発を行ったり、心血を注ぐ個人的なプロダクトがあったり。一方で、出来上がった仕組みの中で決められた業務を担うことが仕事だと思っている人は、ニーズの変化にスキルが追いつかずに埋もれて終わってしまうので、なにより、日頃から技術がどう人に役立つかの興味と成長意欲を持つことが大切。技術スキルは自分で試行錯誤しながらやってみないと伸びないので。
 

具体的な開発環境として、GitHub, Wercker, AWS, HipChatの連携構築をチュートリアル的に紹介していきます。CIサーバは、プライベートリポジトリでも無料のWerckerを試してみることもかねて、Werckerでgitのmasterをテストして、AWSにデプロイまでを自動で行い、結果がHipChatに通知されるイメージ。こういうサイクルが回る環境を作っておいて、日々の機能追加やバグフィックスなどの開発を行っていく流れを体感してもらえればと思います。

1.サンプルrailsアプリケーション

サンプルアプリケーション「rweckersample」を新規に作っていきます。参考までに環境は、ruby 2.1.5, Rails 4.1.4。

$ rails new rweckersample -T -d mysql --skip-bundle

Gemfileに、rspecを追加してbunlde install。rspecの初期化も。

group :development, :test do
    gem 'rspec-rails'
end
$ bundle install --path vendor/bundle
$ rails g rspec:install

      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb

サンプルなので内容は何でもいいですが、ここでは簡単にscaffoldで書籍データ管理をするアプリケーションを作成。

$ rails g scaffold book title:string author:string outline:text

     invoke  active_record
      create    db/migrate/20141228202726_create_books.rb
      create    app/models/book.rb
      invoke    rspec
      create      spec/models/book_spec.rb
      invoke  resource_route
       route    resources :books
      invoke  scaffold_controller
      create    app/controllers/books_controller.rb
      invoke    erb
      create      app/views/books
      create      app/views/books/index.html.erb
      create      app/views/books/edit.html.erb
      create      app/views/books/show.html.erb
      create      app/views/books/new.html.erb
      create      app/views/books/_form.html.erb
      invoke    rspec
      create      spec/controllers/books_controller_spec.rb
      create      spec/views/books/edit.html.erb_spec.rb
      create      spec/views/books/index.html.erb_spec.rb
      create      spec/views/books/new.html.erb_spec.rb
      create      spec/views/books/show.html.erb_spec.rb
      create      spec/routing/books_routing_spec.rb
      invoke      rspec
      create        spec/requests/books_spec.rb
      invoke    helper
      create      app/helpers/books_helper.rb
      invoke      rspec
      create        spec/helpers/books_helper_spec.rb
      invoke    jbuilder
      create      app/views/books/index.json.jbuilder
      create      app/views/books/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/books.js.coffee
      invoke    scss
      create      app/assets/stylesheets/books.css.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.css.scss

ルーティングの設定でrootを追加。

config/routes.rb

Rails.application.routes.draw do
  resources :books
  root 'books#index'
end

DBのマイグレーション。もちろんconfig/database.ymlでmysqlとの接続設定をしておく。productionは、この後サーバで動かす際の値を設定しています。

config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: (mysqlのユーザ名)
  password: (mysqlのパスワード)
  
production:
  <<: *default
  database: rweckersample_production
  username: (mysqlのユーザ名)
  password: (mysqlのパスワード)
  socket: /var/lib/mysql/mysql.sock
$ rake db:create
$ rake db:migrate

== 20141228202726 CreateBooks: migrating ======================================
-- create_table(:books)
   -> 0.2387s
== 20141228202726 CreateBooks: migrated (0.2388s) =============================

これで、WEBrickを起動してhttp://localhost:3000/にアクセスすれば簡単なアプリケーションが動きます。

$ rails s

=> Booting WEBrick
=> Rails 4.1.4 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Notice: server is listening on all interfaces (0.0.0.0). Consider using 127.0.0.1 (--binding option)
=> Ctrl-C to shutdown server
[2014-12-29 05:31:11] INFO  WEBrick 1.3.1
[2014-12-29 05:31:11] INFO  ruby 2.1.5 (2014-11-13) [x86_64-darwin13]
[2014-12-29 05:31:11] INFO  WEBrick::HTTPServer#start: pid=59561 port=3000


rw3
rw2

まだ何もコードを書いていないのでrspecテストは全てペンディング・成功になるはずですが、念のため失敗がないことを確認しておく。

$ rake spec
Finished in 0.24102 seconds (files took 1.44 seconds to load)
30 examples, 0 failures, 17 pending

などの結果が出るはずです。

ここまでをgitにコミットしておきましょう。その前に.gitignoreの設定をしておきます。.gitignoreの作成は、gitignore.ioというサービスを使うとコマンドラインから一発で作成できるので便利。アプリケーションのルートディレクトリで

$ gi osx,rails >> .gitignore

で.gitignoreを作成。実際はセキュリティなど色々と配慮しますが、サンプルなのでconfig/secrets.ymlもコミットする設定に変更します。

.gitignore

# TODO Comment out these rules if you are OK with secrets being uploaded to the repo
# config/initializers/secret_token.rb
# config/secrets.yml

ローカルにコミット実行

$ git init
$ git add .
$ git commit -m 'first commit'