githubにpushされたのをhookしてec2で自動的にpullする

今回やりたかったことは、githubの特定のリポジトリにpushしたら、それをhookして、ec2のWebサーバーにPostされ、
自動的にpullして特定ディレクトリを更新。
です。
やったことがなかったので、ひじょうに勉強になりました!

ec2環境を整える

こちらの記事通りやればOK。
なかなか用語などに馴染みがなく理解しずらかったのですがこのあたりは慣れですね。

わずか5分!? AWSのEC2でクラウドなウェブサーバーを構築してみた | 株式会社LIG

rbenvを入れる

ec2にrbenvをインストールする方法 – Hive Color
こちらの記事のとおりやればうまくいきました!
以下、メモ程度でやったことを残しておきます。

install_rbenv.sh

groupadd staff
gpasswd -a ec2-user staff
cd /usr/local
git clone git://github.com/sstephenson/rbenv.git rbenv
chgrp -R staff rbenv
chmod -R g+rwxXs rbenv

yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison iconv-devel

mkdir /usr/local/rbenv/plugins
cd /usr/local/rbenv/plugins
git clone git://github.com/sstephenson/ruby-build.git
chgrp -R staff ruby-build
chmod -R g+rwxs ruby-build

あとは、インストールするだけ。

sudo sh install_rbenv.sh

すべてのユーザーでrbenv使えるようにしておく

/etc/profile.d/rbenv.sh
# vi /etc/profile.d/rbenv.sh
export RBENV_ROOT=/usr/local/rbenv
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"

一度ログアウトして再度ログインするか、

source /etc/profile.d/rbenv.sh

する。

rbenvでrubyをインストールする

rbenv install 2.1.2
rbenv rehash
rbenv global 2.2.1

これで、

ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]

こうなればOK!

hook用のWebサーバーはSinatraを使ってみる

ググるとSinatraでやっている方が多々いて、Sinatra久々に触ってみよーということでやってみました。
以下の記事のコードをかなり参考にさせていただきました!

githubにPushしたらwebhooksとSinatraを利用してサイトを自動的に更新する – blog.katsuma.tv
Webサイトをgithubで管理してpush時に自動的に同期する方法 – Blog by Sadayuki Furuhashi

app.js

require 'sinatra'
require 'json'

here = File.dirname(__FILE__)
SCRIPT = "sh -x #{here}/update-website.sh"

set :port, 8080

post '/' do
   begin
      push = JSON.parse(params[:payload])
      system(SCRIPT)
      "ok."
   rescue
      "error."
   end
end

get '/' do
  system(SCRIPT)
  "ok."
end

サンプルにもう書かれていて、他の記事にもJSON.parse(params[:payload])でpayloadというのが取れるというのが書かれていたのですが、
どうも今試してみると、取れなかった。

その変わり、githubに

Which events would you like to trigger this webhook?
Just the push event.

というラジオボタンがあったので、postの中身は、

post '/' do
  system(SCRIPT)
  "ok."
end

にしてみた。
確かに、イシュー追加しようが、コメント書こうがpostがこなかったので、これでもいいかな。

Rubyで外部コマンドを実行して結果を受け取る方法あれこれ – Qiita

git clone、git pullするshellスクリプト

#!/bin/sh

tmpdir=/var/www/html/hoge
repo=git@github.com:hoge/hoge.git

if [ -d "$tmpdir" ];then
    cd "$tmpdir"
    if git pull; then
        exit 0
    fi
fi

# /var/www/html/
dirname=`dirname "$tmpdir"`
# hoge
basename=`basename "$tmpdir"`

cd "$dirname"

if git clone "$repo" "$basename"; then
  exit 0
fi

Sinatraを起動する

production環境で実行しないと外からのリクエストを受け付けなくなったようなので、以下のように実行。

ruby app.rb -e production

Sinatraがデフォルトでは外部から繋がらなくなってたよ – Qiita

メモ

■yumでインストールしたファイル一覧
rpm -ql nginx
rpm -qa | grep nginx

■サービス一覧
chkconfig –list
3のところが自動起動するかどうか

■自動起動するようにする
chkconfig nginx on

■サービス自体をすぐに起動する
service nginx status
service nginx start

■pemファイルの権限は600にしないとダメ(Mac側)
chmod 600 cliskkey.pem

■ec2にsshログイン
ssh -i key.pem ec2-user@IPアドレス

■postが空いているか確認
telnet IPアドレス 8080

■指定ポートが使われているか確認
netstat -anp | grep 8080

■/var/www/htmlのownerを変える
chown ec2-user:ec2-user /var/www/html

参考リンク

Webhooks | GitHub API

Amazon Web Services クラウドデザインパターン実装ガイド
大澤 文孝
日経BP社
売り上げランキング: 43,041

Macのスクリーンショットを動画にするRubyコード

@edvakfさんにスクリーンショット撮ると面白いよーと教えていただいたので、以下の記事を参考にRubyでコード書いてみた。
Macのスクリーンショットで1日の作業を記録して動画で振り返り – 西尾泰和のはてなダイアリー

screencaptureというMacに初めから入っているコマンドを使うとスクリーンキャプチャが撮れるらしい。
さらに、ffmpegを断片の画像たちを動画に変換する。

これで一日の最後に自分がどうゆう作業をしていたのがダイジェスト(走馬灯)のように確認できて面白い。
さらにiSightで自分の顔を撮っても面白そう。

スクリーンキャプチャを撮るサンプルコード

class Capture
  attr_accessor :path
  @@INTERVAL = 30

  def initialize(path="~/")
    @path = path
  end

  public
  def capture
    Dir.glob(@path + "**/*") do | f |
      p f
      File.delete(f)
    end

    0.upto(0/(0.0)) do | count |
      filename = @path + now() + "-%08d.png"%[count]
      save(filename)
      sleep(@@INTERVAL)
    end
  end

  private
  def save(filename)
    system("screencapture -x #{filename}")
  end

  def now
    Time.now.strftime("%Y-%m-%d")
  end
end

capture = Capture.new("/Users/hisamatsu/capture/image/")
capture.capture

gist

スクリーンキャプチャ

画像から動画を作るサンプルコード

事前に

brew install ffmpeg

しとくこと。

class Movie
  attr_accessor :image_path
  attr_accessor :movie_path

  def initialize(image_path="~/", movie_path="~/")
    @image_path = image_path
    @movie_path = movie_path
  end

  public
  def capture
      filename = movie_path + now() + ".avi"
      save(filename)
  end

  private
  def save(filename)
    command = "ffmpeg -y -f image2 -r 5 -i #{@image_path}#{now()}-%08d.png -s 720x450 #{filename}"
    system(command)
  end

  def now
    Time.now.strftime("%Y-%m-%d")
  end
end

capture = Movie.new("/Users/hisamatsu/capture/image/", "/Users/hisamatsu/capture/movie/")
capture.capture

gist

画像を動画にする

aviファイルなのでVLCとかで開くとよいかと思います。

たのしいRuby 第3版
たのしいRuby 第3版
posted with amazlet at 13.01.25
高橋 征義 後藤 裕蔵
ソフトバンククリエイティブ
売り上げランキング: 21,205

RailsのAsset Pipelineを試してみる

Aiming study#6pdfこちらのスライドを見て、そうかRailsを使わなくてもAsset Pipelineを使うのはありだなーと思ったので、試してみました。

Rails3.1のAsset Pipelineと仲良くなる – a newcomer!
ASCIIcasts – “Episode 279 – Asset Pipelineを理解する”
アセットパイプライン(Asset Pipeline)in Ruby on Rails|シフルIT
ここを読んでだいたい理解した。

つまり、アセット系のファイルをconcatして、minifyしてくれると。

つい最近書いたCoffeeScript・Sassをgruntでコンパイルするこれと同等のことをRailsのAsset Pipelineを使ってやってみました。
Rails3.1からの機能のようですが、現時点で入れると「Rails 3.2.8」が入るので大丈夫ですね。

gem install rails

application.jsファイルを見ると分かるのですが、jquery・jquery_ujs・その他のすべてのJavaScriptファイルをひとつのapplication.jsにまとめるようです。
そこでためしに、application.jsではなく、その他にもうひとつJavaScriptファイルを作るようにしてみました。

JavaScript – CoffeeScript

ファイルの配置。

assets/javascripts
├── application.js
├── foo.coffee
├── hoge.js.coffee
└── index.js

index.jsがapplication.jsと同じ役割。
中身は以下。
重要なのは、一番下の3行。

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require_self
//= require hoge
//= require foo

require_selfは自分自身を指しています。
あとは、個別に2個のファイルを指定、.jsは省略可能。

CSS – SCSS

同じようにCSSファイルも。

assets/stylesheets/
├── application.css
├── index.css
└── style.css.scss

index.cssがapplication.cssと同じ役割。
中身は以下。

/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
 * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the top of the
 * compiled file, but it's generally better to create a new file per style scope.
 *
 *= require style
 */

production.rbにindex.jsとindex.cssを追加する

config/environments/production.rb」に以下のように個別でコンパイルしたいファイルを追加する。

  # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
  config.assets.precompile += %w( index.js index.css )

コンパイルする

rake assets:precompile

上記のようにrakeすると、「public/assets」配下に出来上がる。

assets/
├── application.css
├── application.css.gz
├── application.js
├── application.js.gz
├── index.css
├── index.css.gz
├── index.js
├── index.js.gz

こんな感じになる、余計なファイルは省略しています。

gruntでコンパイルするのもいいけど、こうゆうのもありですね。

Ruby on Rails 3 ポケットリファレンス
山田 祥寛
技術評論社
売り上げランキング: 73001