その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

Gitでmerge済みのブランチをローカル・リモート共々消す

merge済みのブランチがいつまでも環境に居座っていると精神衛生上よろしくないのでこまめに消す派なのですが,いちいち手作業でやるのもダルいしコマンド一発ですべてを片付けたいというのが人情と言うものなので,最近ではゴリッとスクリプトを書いてそれを使っています.

ここにも同じものを置いてあります.
シェル力が低いので,正直これが良いやり方なのかどうかはわかっていませんが,とりあえず動いていて便利なので記した次第.

GitHub Webhooksのpushイベントで重複しているcommitを判別したい

TL;DR

commitオブジェクトに生えているdistinctプロパティを見れば良い.
distinctが0の場合,それは重複しているcommitであることが分かる.
Ref; https://developer.github.com/v3/activity/events/types/#payload-18

本編

さて,GitHubのWebhooksのpushイベントを受け取って,それをIRCや他のチャットツール等にフォワードしたくなるようなことがままあると思います.

これをナイーブに実装しようとすると,pushイベントを受け取って,そのpayloadに乗ってくるcommitsをベロっと舐めてフォワードするような感じになるでしょう.
つまり,

2ac1745 commit3
26cecfa commit2
8ee5552 commit1

というcommit郡がpushされると,これらのcommitの情報がフォワードされるという感じですね.


で,例えばこの場合のpush先がfeatureブランチだったとして,そのfeatureブランチをmasterブランチにmergeするとどうなるかというと,webhookのpushイベントが発火して,merge commitと共に*1 上記のcommitsの情報が再びpayloadに乗ってやって来ることとなります.
このpayloadの情報をすべてフォワードすると,既にフォワードされた内容が再びフォワードされてしまうことになるので具合が悪いことがあります.


これをどう解決するかというと,冒頭に書いたとおりcommitのオブジェクトに生えているdistinctプロパティを見れば良くて,このプロパティが0の時は重複しているcommit (雑な言い方をすると,過去に1度でもpushイベントのpayloadに乗ったことのあるcommit) で,1の時は重複していないcommitであるということが分かります.
従って,既にフォワードした内容を再度フォワードしたくない場合は,distinctが1のcommitだけをフォワードすれば良いという事になります.
(Perlのコード例で恐縮ですが,つまりこんな感じです: https://github.com/moznion/App-GitHubWebhooks2Ikachan/blob/621e7ddef9d0d05a1396a8325a436f74de17e30a/lib/App/GitHubWebhooks2Ikachan/Events/Push.pm#L15)


かつてはHead Commitのcommit logを見て,「“Merge”から始まるcommitだから,これはmerge commit!」みたいな野蛮な方法で重複commitの判別を涙ぐましく行なっていたわけですが (しかもこの方法だとFast-Forwardの場合に対応できない!),distinctを見ればそんな無駄な努力をする必要はありませんでしたよ,という話でした.

*1:Fast-Forwardの時はmerge commitは無いでしょうが

COOKPAD 5-day winter internshipに参加したのでポエムを

参加してまいりました.
途中までは事実を述べて,途中からはポエムになります.どこからポエムが始まるか,みんなで探してみよう!


開催期間中は毎朝6:30に起床してはdoor2doorで2時間かけて,それも満員の中央線と山手線を駆使して出勤しなければならないという,朝と満員電車に弱い僕にとってはまさに試練とも呼ぶべき催しで,僕の心は幾度も布団の誘惑に屈しそうになりましたが,奇跡的に1日たりとも遅刻せずにインターンシップを終えることが出来ました.というか朝6:30って言ったら僕のような人間にとっては午前3時にも匹敵する早起きですよ!*1


さてインターンシップの内容ですが,1週間でスマートフォンアプリをモリモリッと企画してそれをグワワッと実装して,それをジャーンとプレゼンするという大変にエクストリームリィな内容でした.「1週間でスマートフォンアプリを作る」というのは字面だけを見るとさほど難しいことではないように思えるかもわかりませんがトンデモナイ.時間とはここまでここまでここまで足りないものか,という事を実感した次第です.


率直に言えば,僕はスマートフォンアプリの開発にそれほど興味があったわけでも無いし,アプリケーションの企画という活動について言えば輪をかけて興味がなかったので,「必然的に」という言い方もいかがなものかとは思いますが,僕が持っているそれらにまつわるスキルは低いワケで,当然ながら繰り出される成果物のクオリティはそれはもう大変に大変微妙なものが出来上がったという結果は想像に難くないでしょう.

しかしながら時同じくしてインターンに参加した皆さんの成果物等々を見ると,アイデアは面白く,アプリの品質は高く,プレゼンも明朗,質疑応答も的確とそれはもう力の差をまざまざと見せつけられたワケですよ.




これは悔しいなと.




「興味が無いから」とか「俺はこれだけで十分だから」とか,そういう「〜から」というのは単なる「やらない」という事を正当化する為の言い訳に過ぎない事は自分でも重々承知していて.それでもなお,「僕は興味が無いから」などと宣ってこの程度の結果しか出せないというのは完全に怠惰であるし慢心であるし邪悪でしかない.確かに興味が無い事について興味のある素振りを見せるとそこには確実に苦痛が待ち構えているし,実際この1週間は僕にとってひっじょ〜〜〜〜〜につらかったという事は表明する.しかしそのように「興味ねえーし」というスタンスを貫いて視野角を狭めて得をすることがあるのだろうか? これは反語ではない.正直どうなのかはわからない.これについてジェネリックな結論を出すには,僕にはあまりに経験が足りないし知識も足りない.しかし今回に限って言うと,それによって得をしたことは1つとて無い.微視的に見れば,興味が無い分野であっても,気合と愛で能動的に興味を持つべきだと言える.しかし人生は有限だ.無限に興味を持ち,それを吸収することは叶わない.


例えばこの話題は,「どのようにキャリアを積むか」という話題にも通じると思う.
多角な方面の力を付けて,所謂フルスタッキーな力を付けて,所謂フルスタックな,所謂フルスタックエンジニアとして生きていくのか,あるいは何か「これだ!!!」というものを見つけて,それ一本槍に,そこにパラメータを極振りして突き抜けたエンジニアとして生きていくのか,あるいはのらりくらりと過ごして所謂IT芸人として生きていくのか,あるいはエンジニアをやめるか,あるいは,あるいは……
興味をどこにどう持つか,というのはそういう話だと思う.


ところで僕はウィザードリィが好きだ.ウィザードリィではとりあえず「ちから」と「せいめいりょく」をゴリゴリ上げて,脳筋パーティを作って戦うのが好きだ.僕は阿呆なので,できるだけ魔法の使用回数のことは考えたくない.しかしこのパーティでは長くダンジョンに潜ることは出来ない.全員が全員脳筋野郎ではパーティは回って行かないのだ.従って,パーティのそれぞれのメンバが別方向の能力を特化させ,力を合わせて戦う必要がある.
これを現実に当てはめると,自分のどのパラメータに値を振るかというのは重要な問題で,これにはひょっとすると時期が関係するかもしれない.例えば周りにいるエンジニアがみんな脳筋ばかりな時期に,自分も脳筋にパラメータを振って生きていくのは相当なマッチョじゃないとつらい気がする.しかしだからといって,興味の薄い分野にパラメータを極振りするのも違うベクトルのマッチョさだとも思う.本当は剣で戦いたいのにティルトウェイトを唱え続ける人生で良いのだろうか.難しい問題だ.


また,僕はファイナルファンタジーも好きだ.しかし赤魔道士を愛用したことはシリーズを通して一度たりとも無い.やはり何かに特化している方が好きなんだと思う.赤魔道士にメテオは使えないのだ.




僕は何を言っているんだ?




とにかく,クックパッドのインターンは非常に示唆に富んでいましたし,皆さん総出で僕の頭をスカンと殴ってくれたお陰で甘い認識が晴れたと思います.得るものは,確かに多かったと言えるでしょう.
本当にありがとうございました.

*1:おや待てよ,午前3時って言ったら普段の僕なら起きてるな

「UNIXという考え方」を読んだ

UNIXという考え方」をAmazonのwish listに入れていたらid:kenjiskywalkerさんが贈ってくださったので読みました.お陰でUNIXという考え方を学べました.ありがとうございます!


本書では一貫して「プログラムを小さく作る」という事と「1つのプログラムには単一のことだけを上手くやらせる」という事について言及されています.
プログラムを小さく作るということによって,そのプログラムはコンピュータのリソースに対して優しくなり,なおかつ巨大なプログラムと比較して人間が理解するのが簡単になるので保守がしやすくなり,かつ他の部品と組み合わせやすくなるという論旨です.
プログラムを小さく作ると,必然的にそのプログラムは多くの責務を負えなくなる為,自然とプログラムは単一の機能のみを持つようになります.従ってこれら2つの考え方は対になっていると言えるでしょう.
本書で言われている「プログラム」と言うのは,恐らくexecutableな1つの実行ファイル (例えば1つのシェルスクリプトやコマンド) を指しているものと思われますが,この考え方は例えば「1つのメソッドには1つの仕事だけをさせる」というふうにメソッド (あるいは関数) に負わせる責務の範囲を限定する事や,「全知全能の神クラスを作らない」のようにクラスに負わせるべき責務の範囲を狭める,などといったプログラムの設計に対しても応用できると思いました.
このようなことは確か「リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)」にも書いていた気がします.


データは全てASCIIで保存するべきで,デバイス依存のバイナリファイルで保存するな,という話も参考になりました.これは,データは持ち運べなくなった時点で価値が無くなり死ぬので,データの価値を殺さない為にも可搬性を維持するのは重要であるという意味で,恐らく現在だとASCIIではなくUTF-8で保存するのがベターなのでしょうが重要な知見だと思いました.確かにコンピュータ間でデータコンバートが必要になるのは地獄でしかありません.


UNIXという考え方において重要なポジションを占める「ソフトウェアの梃子を使う」という考え方は,どことなくオブジェクト指向の考え方に似ているように感じました.ソフトウェアの梃子とは,複数の小さなプログラムを組み合わせて1つの機能を実現するという手法の比喩表現で,これは小さなオブジェクトと小さなオブジェクトがメッセージを送り合う事で協調して動作し,1つの機能を提供するというオブジェクト指向の概念に通じるところがあるように思いました.双方とも小さいパーツを再利用して開発効率を高めるというアプローチで,なるほどという感じです.


また,「できるだけ早く試作する」という事に関しても書かれていて,これは最近話題になった「Team Geek ―Googleのギークたちはいかにしてチームを作るのか」にも書かれていたという記憶があります.最初から完全に正しいソフトウェアを書くことは不可能で,更に状況に応じて仕様は変更されるとした上で,誤った前提のままプロジェクトを推し進めるのではなく,早い段階で試作品を出してそれをテストし,批判を受けることによって方向を修正し,成果物を洗練していくという一連の流れが書かれていました.

わけてもその文脈で

1. 短い機能仕様書を書く
2. ソフトウェアを書く
3. テストをして書き直し,これを繰り返す
4. 必要なら詳細なドキュメントを書く

という開発フローが紹介されており,「それってつまりシンプルなアジャイルじゃん!」と思わず膝を打ちました.


あと参考になったのは「100%の完成度よりも90%の解を探す」という思考です.
僕はいわゆる「異常な努力」というやつをよくやってしまうんですが,なぜその「異常な努力」が必要となってしまうか*1 と言うと「あまり頻度は高くないけれどこういうユースケースに対応したい」だとか「ここをpluggableにすればもっと汎用的に使えるのではないか」だとか,そういった100%の完成度を執拗に狙ってしまうからなのです.
しかしそういう異常な努力によって生み出された機能はやはり実際にはあまり使われなくて,実装のコストと吊り合わない結果になることが大半です.本来は90%の完成度で充分満足しているのに残りの10%に多大な労力を割くのは無駄だと言えるでしょう.
100%の完成度よりも90%の解を探すというのは,「異常な努力」をしそうになった時に一旦待ったをかける良い考え方だと思いました.


さて驚くべきはこれが1990年代前半に書かれた書籍ということで *2,こうした考え方や哲学はこの時点で既に存在した訳です.
近頃巷で話題になっている「アジャイル」や「リーン・スタートアップ」,或いは「リーダブルコード」などといった考え方の源流は当時から既に形成されていた訳で,これらは過激に (あくまで過激に) 言うなれば元々あった考え方にone more thingを加えた上で,耳障りの良い言葉にパッケージングし直したに過ぎないという印象を受けました.

根源的な思考を学ぶ事に対する重要性を再認識した次第です.

UNIXという考え方―その設計思想と哲学

UNIXという考え方―その設計思想と哲学

*1:本来は大抵必要無いのだけれど

*2:勘違いされている方がいるので書きますけど,初出は1994年です.ref: http://www.amazon.com/The-UNIX-Philosophy-Mike-Gancarz/dp/1555581234

Released Perl::PrereqScanner::Lite

(日本語は英語の後にあります)


I released Perl::PrereqScanner::Lite.

https://github.com/moznion/Perl-PrereqScanner-Lite
https://metacpan.org/release/Perl-PrereqScanner-Lite


This module is the fast edition of Perl::PrereqScanner.
Perl::PrereqScanner has been using PPI as tokenizer, however Perl::PrereqScanner::Lite uses Compiler::Lexer as tokenizer. Moreover it excludes dependency to Moose. Consequently, Perl::PrereqScanner::Lite realized the acceleration. It is faster about 30 times than Perl::PrereqScanner *1.


Now this module can extract modules as prereqs that are declared in use statement and require statement. Besides it can extract modules that are declared in extends notation (member of Moose family) by using Moose extra scanner. And it is able to extract version number that is specified as Foo::Bar->VERSION(1.0.0) by using Version extra scanner.

If you want other extra scanners, make module that has such as the name; Perl::PrereqScanner::Lite::SCANNER_NAME which has the method of scan(), and register extra scanner by add_extra_scanner('SCANNER_NAME') method.


I put this module in App::scan_prereqs_cpanfile.
Now, you can try scan-prereqs-cpanfile with fast mode.

$ scan-prereqs-cpanfile --fast

--fast option enables fast mode. Fast mode means, scan-prereqs-cpanfile uses Perl::PrereqScanner::Lite as the backend module. Perhaps it will run at a high speed.

For example, the result of executing this command on HEAD of mojo;

$ time scan-prereqs-cpanfile
real   0m20.386s
user   0m20.132s
sys    0m0.126s
$ time scan-prereqs-cpanfile —fast
real   0m1.174s
user   0m1.074s
sys    0m0.096s


Enjoy!


==


Perl::PrereqScanner::Liteをリリースしました.
https://github.com/moznion/Perl-PrereqScanner-Lite
https://metacpan.org/release/Perl-PrereqScanner-Lite


このモジュールはPerl::PrereqScannerの高速化版です.
Perl::PrereqScannerではtokenizerにPPIを使用していましたが,Perl::PrereqScanner::LiteはtokenizerとしてCompiler::Lexerを使うことに加え,Moose依存を排除する事により,30倍程度の高速化を実現しています *2


現在はuserequireによって宣言されたモジュールに加えて,extra scannerとしてMooseを利用するとMooseファミリーの持つextends記法によって宣言されたモジュールを抜き出すことが出来ます.Versionというextra scannerを用いる事によってFoo::Bar->VERSION(1.0.0)のようにして指定されたバージョンを抜き出すことも可能です.

その他のextra scannerが必要な場合は,scan()というメソッドを持ったPerl::PrereqScanner::Lite::SCANNER_NAMEという名前のモジュールを書いて,add_extra_scanner('SCANNER_NAME')という具合にextra scannerを登録してやると良いです.


試しに,という言い方もアレですが,Perl::PrereqScanner::LiteをApp::scan_prereqs_cpanfileに組み込んでみました.最新版だと,

$ scan-prereqs-cpanfile --fast

という風に--fastオプションを付けてやる事でバックエンドがPerl::PrereqScanner::Liteとなり,高速に動作することが見込めます.おそらく体感出来るレベルで速さを知覚出来ると思います.

[追記]
mojoのHEADでコマンドを実行するとこんな感じになりました.

$ time scan-prereqs-cpanfile
real   0m20.386s
user   0m20.132s
sys    0m0.126s
$ time scan-prereqs-cpanfile —fast
real   0m1.174s
user   0m1.074s
sys    0m0.096s


ぜひお試しくださいませ.不具合等ありましたら教えて頂けると嬉しいです.

「Webアプリエンジニア養成読本」を読みました

Perlの話がほぼ出てこないこの本はクソ!!!!! (嘘です.著者の1人にそう書けって言われたものだから……)

Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)

Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)

Webアプリの着想・設計・制作・運用までバランスよくまとまっていて良い本だと思いました.この手の書籍で運用にまつわる話が載っているのは中々珍しい気がします.

1章

基本的なWebの技術 (HTTPとかServer-ClientアーキテクチャとかHTMLとか) の説明が優しく,わかりやすくて良いです.僕もWebアプリ触り始めの頃にこれを読めれば!!!! という気持ちになりました.
また,「どんな言語を使うべきか」というところで「その言語を使っている身近な人がいるか,もしくは,コミュニティが活発か」という指標を示していて,大事だと思うとともにフェアだなーと思いました.重要な話だ.
あとGitHubの話題とかあってだいぶナウいですね.

2章 (PHP編)

PHP凄い!!
「とりあえずechoでエラー出してみよーぜー」とか,「$_GETぶっこもーぜー」とか,そういう悪いPHP的世界ではなく,もっと正常で,かつ清浄な,格好いい世界のPHPの話が展開されています.

「簡単な掲示板を作る」というイカニモな話題を通して内容が展開される訳ですが,ビルトインサーバやらパッケージマネージャやらテンプレートエンジンやらORMやら,とにかくPHPの近代的なイケてるツールをふんだんに取り入れていて格好良いです.PHPの入門書籍で名前空間を最初からちゃんと説明しているの良いですね.

また「イケてないPHP情報の見極め方」というコラムは非常に参考になります.他の言語にも通用すると思います.

あとGentoo向けにemergeでPHPをインストールする方法が書いてあってマニアック過ぎる! Gentoo LinuxでのPHPインストール方法が載っている書籍はこれが世界で初ではないでしょうか.*1

2章 (Ruby編)

RailsではなくSinatraを使っていて,Railsがうまい具合に隠してしまって目にできない (しかしそこが重要だったりする) ところをあえて触る,という感じで好印象です.

Rubyの基本的な書式や,最近のRubyを取り巻くエコシステム等が網羅的に説明されており,Rubyを触った事が無い人や「さいきんご無沙汰だワ」という人でも安心して読めて良いなあと思いました.

ブックマークアプリケーションの制作という流れで説明が進みますが,これ読めば大体分かってめっちゃ便利.過不足がなくて凄い.

それにしてもActiveRecord便利過ぎる.そしてRSpecは強力だ……

3章

サーバ (IaaS) の契約 ,サーバの構築,そしてデプロイまでがスピード感ある感じで説明されています.冒頭で書かれている,「自分のサービスを知る」「どこがボトルネックになるかを認識する」「どれくらいの時間サービスがダウンしても許容できるかを把握する」といったことは非常に大切だと感じました.

手作業でのサーバ構築指南だけではなく,ChefやAnsible,またserverspecなどの自動化を支援するツールについても言及されておりバリューがある感じがします.

そして「SCP (FTP) でのデプロイは絶対やってはいけません」と書かれていて非常に力強く感じると共におや涙が……

4章

すごい,監視と測定まで話が広がっている!

サーバの監視手法と共に,監視項目の閾値例も乗っていて大変参考になる感じでした.うっかり蔑ろにしてしまいがちなロギングの話やバックアップの話も丁寧に説明されていてグッドです.
また,ベンチマークとチューニングといった実践的な話についても紙面が割かれており非常に勉強になりました.アプリケーションのどこから測定してどうチューニングするか,という事例が乗っていて大変参考になります.

総評

ムック本という特性上そこまで厚い本ではありませんが,それを感じさせないボリューム感があります.ひと通り体系的な知識が付くと思うので,Webアプリ触りたての人とかが読まれると良いのでは無いでしょうか.

ただ,この本にはSQLの話が載っていなくて,しかしながらSQLはカジュアルに「よう!」といった感じで,まるで友人の如く登場してくるので面食らうかもわかりません.なので,SQLについて勉強したい人はウェブサイトや別の書籍など,他の媒体を当たる必要があると思います.
また,この書籍ではソフトウェアのテストについて触れられていますが,どちらかと言うとテストライブラリをどう使うか,といった方法論的な話が主なので,理屈的な事を詳しく知りたい人も他の書籍等を参照する必要があると思いました.

この本読んでわからないことあったらすぐにググったほうが絶対に良いと思います.そのコンピュータは艦これのためだけにあるのではない.

そうそう

今週木曜日 (3/20) にこの書籍の発売を記念して、池袋のジュンク堂書店にてイベントを行われるそうです.

http://www.junkudo.co.jp/mj/store/event_detail.php?fair_id=4314

どうやらまだ会場に空きがあるとの事でしたので,興味の有る方は参加されると良いのではないかと思います.


以上現場でした.

*1:これ誰に刺さるんだろう?

Ukigumoの新機能一覧

https://metacpan.org/pod/Ukigumo::Server
https://metacpan.org/pod/Ukigumo::Client
https://metacpan.org/pod/Ukigumo::Agent

ゆるふわCIエコシステムのUkigumoですが,最近ひと通りアップグレードしたのでそれに伴って搭載された新機能について紹介します.

注意

Ukigumo::Server 2.0.0以降はDBのスキーマが変更されているので,テーブルのALTERが必要です.

ALTER TABLE report ADD compare_url VARCHAR(255) DEFAULT NULL;

などとしてやる必要があります.

Ukigumo::AgentがGitHubのWebhooksに対応した

/api/github_hookGitHubのWebhookを飛ばしてやるとjobが登録されるようになりました.
つまり,GitHubのWebhooksの設定でhttp://your-ukigumo-agent-server.com/みたいな感じで宛先を追加してやるとWebhooksが飛んだタイミングでjobが登録されるようになります.便利!

GitHubのStatuses APIに対応した

こういうことが出来るようになりました.
f:id:moznion:20140318122010p:plain

ありていに言えばTravisのような事ができます.

.ukigumo.yml

notifications:
  guthub_statuses:
    - api_endpoint: https://api.github.com
      access_token: YOUR_ACCESS_TOKEN

などと書いてやると実現できるでしょう.
なおこのAccessTokenにはrepo:statusを操作する権限を与えられている必要があります.

Compare URLに対応した

commitの差分URLが出るようになりました.*1
こういったURLがテスト結果のページに出ます: https://github.com/ukigumo/Ukigumo-Agent/compare/caa6fb3bed2ce584ec05c98a15a8f0ec85f2af18...5a378c84459f2b8a94e05635e4a125f5f34d9658

保存するテスト結果の最大数を設定出来るようになった

今までは無制限にテスト結果を保存していましたが,この変更で最大保存件数を設定出来るようになりました.

設定ファイルに以下のように書くと,最大件数を設定することが出来ます.

{
    max_num_of_reports_by_branch => 10,
    max_num_of_reports => 200,
};

max_num_of_reports_by_branchはブランチごとに保存する最大の件数で,max_num_of_reportsは全体の最大保存件数です.

最大保存件数を超えた場合,古いものから削除されていきます.

テスト結果の内容を圧縮できるようになった

テスト結果を圧縮して保存できるようになりました.

設定ファイルに

{
    enable_compression => 1
}

などと記述して,enable_compressionを有効にしてやると,テスト結果を圧縮するようになります.


……という感じでGitHubとの連携に寄せた変更が多く入りました.
ご利用ください.

*1:GitHubしか対応していない気がする