こんにちは、tahara です。
いいかげん Jenkins くら導入しようよ、ということで導入しました(ステージングへの cap が Asset Pipeline の precompile で時間がかかるようになって、手で cap するのがめんどうになったのが本当の理由です)。
Jenkins のセットアップは色々なとこに情報があったのですんなりいきました。 でも、Jenkins から Skype への通知でてこずりました。 Skype Plugin があるので、これを使えば問題ないよね、と思っていたのですが、一日格闘しても動かせず。
Skype Plugin をあきらめ Common Lisp 経由で Skype を使うことにしたら、すんなりできました。 Jenkins → ビルドシェル → Common Lisp → D-Bus → Skype という流れになります。
まず Linux上で動くSkype用のbotを作る方法 - muddy brown thang を参照して Skype を Xvfb で動くようにします。
sudo vi /etc/init.d/skype
#!/bin/bash # # Init file for daemonized Skype service # ### BEGIN INIT INFO # Provides: skype # Required-Start: $local_fs $remote_fs $network $syslog # Required-Stop: $local_fs $remote_fs $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # X-Interactive: false # Short-Description: starts the skype on Xvfb # Description: starts skype using start-stop-daemon ### END INIT INFO # sudo update-rc.d skype defaults DAEMON=/usr/bin/skype DAEMON_USER=jenkins PIDFILE=/var/run/skype.pid XSERVERNUM=20 XAUTHFILE=/var/run/skype/Xauthority LOGFILE=/var/log/skype/error.log DBPATH=/var/lib/jenkins/.Skype XAUTHPROTO=. USERNAME=your-skype-account PASSWORD=your-skype-password NAME=skype test -x $DAEMON || exit 0 set -e . /lib/lsb/init-functions RETVAL=0 dircheck() { if [ ! -d `dirname "$1"` ]; then echo "`dirname \"$1\"` does not exist" return 1 else return 0 fi } start() { echo -n "Starting $DESC: " if ! dircheck "$LOGFILE" || ! dircheck "$XAUTHFILE"; then echo -n "ng. $LOGFILE or $XAUTHFILE" echo RETVAL=1 return fi MCOOKIE=`mcookie` && \ sudo -u "$DAEMON_USER" env XAUTHORITY=$XAUTHFILE sh -c "xauth add \":$XSERVERNUM\" \"$XAUTHPROTO\" \"$MCOOKIE\" >> \"$LOGFILE\" 2>&1" && \ sudo -u "$DAEMON_USER" env XAUTHORITY=$XAUTHFILE sh -c "Xvfb :$XSERVERNUM -screen 0 800x600x8 -nolisten tcp >> \"$LOGFILE\" 2>&1 & echo \$!" >"$PIDFILE" && sleep 3 && \ (sudo -u "$DAEMON_USER" env DISPLAY=:$XSERVERNUM XAUTHORITY=$XAUTHFILE SKYPE="$DAEMON" sh -c "echo \"$USERNAME $PASSWORD\" | nohup \"$DAEMON\" --dbpath=\"$DBPATH\" --pipelogin &") >> "$LOGFILE" 2>&1 && \ (echo -n "ok" && [ -d /var/lock/subsys ] && touch /var/lock/subsys/skype || true) \ || (RETVAL=$?; kill -TERM `cat $PIDFILE`; echo -n "ng") } stop() { echo -n "Stopping" "skype" if [ -e "$PIDFILE" ]; then kill -TERM `cat $PIDFILE` && \ rm -f $PIDFILE && \ if [ -d /var/lock/subsys ]; then rm -f /var/lock/subsys/skype; fi && \ echo -n "ok" || echo -n "ng" else echo "ng. maybe not running." RETVAL=1 fi } usage() { echo "Usage: $NAME {start|stop|restart}" } case $1 in start) start ;; stop) stop ;; restart) stop start ;; *) usage RETVAL=255 ;; esac exit $RETVAL
$ sudo chmod +x /etc/init.d/skype $ sudo mkdir /var/log/skype $ sudo chown jenkins:jenkins /var/log/skype $ sudo mkdir /var/run/skype $ sudo chown jenkins:jenkins /var/run/skype $ sudo update-rc.d skype defaults $ sudo service skype start
Common Lisp と Quicklisp のセットアップ。
$ sudo apt-get install sbcl $ curl -O http://beta.quicklisp.org/quicklisp.lisp $ sbcl --load quicklisp.lisp * (quicklisp-quickstart:install) * (ql:add-to-init-file)
Common Lisp から Skype を使うコードです。
vi /var/lib/jenkins/skype/skype.lisp
(load "~/quicklisp/setup.lisp") (let* ((*standard-output* (make-broadcast-stream)) (*error-output* *standard-output*)) (ql:quickload :dbus)) (defpackage :skype (:use :cl :dbus)) (in-package :skype) (defparameter *chat-id* "#xxxxxx/$xxxxxx;3xxxx9999xxxxx" "Skype チャットの ID") (defun message (chat-id message) (with-open-bus (bus (session-server-addresses)) (with-introspected-object (skype bus "/com/Skype" "com.Skype.API") (flet ((skype (command) (print (skype "com.Skype.API" "Invoke" command)))) (skype "NAME FromCommonLisp") (skype "PROTOCOL 8") (skype (format nil "CHATMESSAGE ~a ~a" chat-id message)))))) (let ((message (second sb-ext:*posix-argv*))) (message *chat-id* message))
Common Lisp からは D-Bus 経由のため、 環境変数 DBUS_SESSION_BUS_ADDRESS の設定が必要になります(cron と gconftool-2 について - AOTRの日記)。
/etc/init.d/skype の XSERVERNUM に 20 を指定しているので、次のようにすればよさそうです。
$ source `ls ~/.dbus/session-bus/*-20` $ export DBUS_SESSION_BUS_ADDRESS
これで sbcl すれば skype でメッセージが送れるはずです。
$ sbcl --script /var/lib/jenkins/skype/skype.lisp 'テストメッセージ'
あ、Skype を Xvfb で動かす前に一度普通に動かして Common Lisp からパブリップ API を使えるよう許可しておく必要があります。 次のような感じです。
$ ssh -X jenkins@example.com $ skype & $ echo $DISPLAY # DISPLAY 番号を確認 localhost:10.0 $ source `ls ~/.dbus/session-bus/*-10` $ export DBUS_SESSION_BUS_ADDRESS $ sbcl --noinform --disable-debugger --load /var/lib/jenkins/skype/skype.lisp 'テストメッセージ'
最後に Jenkins のビルドスクリプトです。 cap をして Skype で通知します。 git のコミットメッセージなども付けるようにします。
ビルドスクリプトはリポジトリに入れておくのがベストプラクテスとのことですので vi $YOURE_RAILS_WORKSPACE/config/jenkins/build.sh
#!/bin/bash # cap rvm_path=/home/deployer/.rvm /home/deployer/.rvm/bin/rvm-shell 'ruby-1.9.3@iko-yo-rails3' -c 'cap staging deploy:migrations' # 20 は /etc/init.d/skype の XSERVERNUM=20 source `ls ~/.dbus/session-bus/*-20` export DBUS_SESSION_BUS_ADDRESS sbcl --script /var/lib/jenkins/skype/skype.lisp "(ninja) Capistrano: いこーよを 確認(ステージング) 環境 http://outing.actindi.net/ にデプロイしました (h)`git log --pretty='%n%s%n%b%n%an' HEAD...HEAD~`"
Jenkins の "ビルド" > "シェルの実行" > "シェルスクリプト" に config/jenkins/build.sh を指定で、できあがり。
最後に、弊社ではエンジニア募集しています。お気軽にお問い合わせください。