何も変えてないのにjenkinsのdailyのテストが通らなくなった。

% rake test
rake aborted!
no such file to load -- omniauth/password

(See full trace by running task with --trace)

手元でも確かに動かない。omniauthに何が起こった?bundleなどビルドプロセスが外部に依存してるとコードは変わってなくてもこういうことがあるのでdailyのテストも大事だな。

% bundle list | grep omniauth
  * omniauth (0.0.1)

OMG!

何故だかバージョン指定無しだと0.0.1が入るようになっている。

# Gemfile:
gem 'omniauth', '~> 0.2.6'

バージョンを指定して凌ぎましたが、他でも起きたら怖いので原因知ってる人がいたら教えてもらえると嬉しいです。

先週の土曜日(6月25日)にtokyo.clj#12に行ってきました。

場所は四谷にある株式会社タイムインターメディア様の会議室。(下がオライリー・ジャパン)

自分のブログによるとclojureをはじめたのが6月15日らしいので初心者ですが、初心者の時こそ得る物が多いと思って行ってみました。

僕はHSQLDBを使ってみたりスクリプトとして使う時の設定を探したりしてました。Hackthonなのでもくもくと作業できてよかったです。その後の懇親会もLisp/Clojure関係のお話を聞いてWeb/Ruby関係とはまた違った感じで新鮮で勉強になりました。

Clojureはまだ初心者ですが、Javaのライブラリがそのまま呼び出せる・呼び出しやすい為もあってか、周辺ツールが充実してる気がします。LispなのでみんなEmacsで書くため、CLI中心で行けるのも嬉しいです。(僕はvimですがVimClojureも期待より全然完成度高かったです)

JavaはIDEとXMLが障害となって避けてたんですが、Clojureにはその二つが苦手な人が沢山いるらしく、IDEをとXMLを使わなくていいツールを勝手に揃えてくれるので安心です。

ただ、カッコがついたファイルを「DSLだから設定ファイルとして使え」と言われても僕には未だにプログラムとしてしか見れないです。(project.cljとか.emacsとか)

下記の通りで何の問題も無し。

DBを使いたい - 逆引きClojure

HSQLDBの使い方でちょっと時間かかったぐらい。CLOB型とか覚えられない・・・。

Lokka Config [Jenkins]

"Trigger builds remotely"を選んで適当なTOKENを設定する。

Githubの"Post-Recieve URLs"にそのURLを設定する。

http://example.com/job/PROJECT_NAME/build?token=TOKEN

追記:

Github Pluginを0.5にアップしたらチェックボックスが出現してもっと簡単になりました!

Lokka Config [Jenkins]

追記2:

と思ったら上手くいってませんでした。何がどう動いてるのが理解出来てない感じ・・・

Configure System [Jenkins]

verifyと出るけどgithubにpushしてもbuildされない状態。以前のやり方に戻そうかな?

DTermからGUIアプリを立ち上げるには$ open -a /Applications/Safari.appとかする必要があって面倒なので~/.macappにそれぞれのアプリをopenするスクリプトを作るスクリプトを書いてみた。

#!/usr/bin/env ruby

require 'fileutils'

def e(path) path.gsub(/[ ()]/) {|s| "\\#{s}"} end

FileUtils.rm_rf("#{ENV['HOME']}/.macapp")
FileUtils.mkdir("#{ENV['HOME']}/.macapp")

Dir.glob('/Applications/{,Utilities/}*.app') do |path|
  script = "#{ENV['HOME']}/.macapp/#{path.split('/').last}"
  open(script, 'w') {|f| f.write(<<-EOS) }
#!/bin/sh
open -a #{e(path)}
  EOS
  FileUtils.chmod(0755, script)
end

Make symlink from Mac GUI Apps. — Gist

~/.macappにPATHを通せば$ Safari.appみたいな感じで立ち上がるようになる。(DTerm等のGUIの場合は/etc/launchd.confに書く必要がある

理想のランチャー道は遠いな・・・。

ちゃんと書く場合はleiningenでproject作った方が楽だけど、手元で手軽にclojureしたい場合の為にsystem-wideにインストールする。

$ brew install clojure-contrib
# ~/.zshrc
export CLASSPATH=$CLASSPATH:/Users/komagata/homebrew/Cellar/clojure-contrib/1.2.0/clojure-contrib.jar

clojureも依存で入る。バージョンは2011/06/25現在だと1.2.0。ついでにちょっとした起動スクリプトもcljって名前で入れてくれる。

% clj
Clojure 1.2.0
user=> (+ 1 2 3)
6

引数無しだとreplが立ち上がる。

;; unk.clj
(println "unk")
% clj unk.clj
unk

スクリプトを渡せば実行される。

clojure.mainが標準入力からスクリプトを受け取れれば

#!clj
(println "unk")

って書けそうだけど、無理。

;; project.clj
(defproject bar "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.2.1"]]
  :main bar.core)

:mainでnamespaceを指定しておくと$ lein run -m bar.coreみたいにイチイチ指定しなくていい。

;; src/bar/core.clj 
(ns bar.core
  (:gen-class))

(defn -main []
  (println "unk"))

スタンドアローンで実行できるjarを作るには:gen-classの指定と-main関数が必要。

まずそのまま実行してみる。

% lein run
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
unk

(このJAVAのOPTIONがイチイチ表示されるの何とかならないかな・・・)

% lein uberjar

Twitter / @mreinsch: @komagata yes, German "übe ...

ドイツ人の@mreinschさんによるとuberとはbeyondとかaboveの意味だそうです。(それでもよく分からないけど)

bar-1.0.0-SNAPSHOT-standalone.jarとbar-1.0.0-SNAPSHOT.jarが出来ていました。jar tvfで中身を見てみると、無印の方はこのプロジェクトのモノだけ。-standaloneの方は依存jar(clojure自身を含む)が全部入ったやつみたいです。

% java -jar bar-1.0.0-SNAPSHOT-standalone.jar 
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
unk

OMG!

Windows XPに持って行って実行してみると・・・

windows_xp_ie6 [Running]

(^q^)

HerokuのCedar StackはClojureに対応してる。要はLeiningenに対応してる。(RubyのBundlerに対応してるのと同じようなもん)

project.cljを見て必要なもんをpush時にインストールしてくれる。

;; lib/unk/core.clj
(ns unk.core
  (:use compojure.core
        ring.adapter.jetty))

(defroutes app
  (GET "/" _ "unk"))

(defn -main []
  (let [port (Integer/parseInt (get (System/getenv) "PORT" "8080"))]
    (run-jetty app {:port port})))
;; project.clj
(defproject unk "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.2.1"]
                 [compojure "0.6.3"]            
                 [ring/ring-jetty-adapter "0.3.8"]])
# Procfile:
web: lein run -m unk.core
$ heroku apps:create --stack cedar
$ git push heroku master
$ heroku apps:open

http://sharp-wind-970.herokuapp.com/

OMG!

環境変数$PORTを使う必要がある部分でちょっと躓きました。

Herokuの新しいCedar Stackを使う。

今までと大きく違うのはforemanを使ったprocess modelが導入されたこと。要はwebアプリもcronジョブもバックグラウンドタスクもみんな宇宙船UNIX号の仲間たち、foremanで平等に扱おうよということ。具体的にはProcfileにprocessの設定を書いてforeman経由で動かす。

# Gemfile:
source :rubygems
gem 'rack'
# config.ru:
require 'rubygems'
require 'rack'

class App
  def call(env)
    [200, {'Content-Type' => 'text/plain'}, ['hello']]
  end
end

run App.new
# Procfile:
web: bundle exec rackup -p $PORT

こんな感じ。

$ gem install foreman
$ foreman start

ローカルでもforemanで試せる。

$ heroku apps:create --stack cedar
$ git push heroku master
$ heroku apps:open

http://floating-dawn-850.herokuapp.com/

いいね!

process typeを自分で定義する

unixのprocessなら何でもありなので適当に定義できる。

# Procfile:
web: bundle exec rackup -p $PORT
unk: echo unk; sleep 1000
% foreman start
02:23:42 web.1     | started with pid 77070
02:23:42 unk.1     | started with pid 77071
02:23:42 unk.1     | unk
02:23:43 web.1     | [2011-06-23 02:23:43] INFO  WEBrick 1.3.1
02:23:43 web.1     | [2011-06-23 02:23:43] INFO  ruby 1.8.7 (2011-02-18) [i686-darwin10.7.0]
02:23:43 web.1     | [2011-06-23 02:23:43] INFO  WEBrick::HTTPServer#start: pid=77072 port=5000

こいつは自由だぜ。

clojureのweb framework。

(ns foo.core
  (:use compojure.core))

(defroutes app
  (GET "/" _ "foo"))
(defproject foo "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.2.1"]
                 [compojure "0.6.3"]]           
  :dev-dependencies [[lein-ring "0.4.3"]]
  :ring {:handler foo.core/app})
$ lein ring server

http://localhost:3000/

lein-ringで前回書いてた問題は解決。