つい先日Goslingsというものを作った。 Gitのリポジトリの中身をビジュアライズするWebアプリケーションだ。 なんとなく見て楽しいという効用がある他は、Gitの勉強にちょっと使えるかもしれないという程度のものだが、もともとGit Advent Calendar 2016のネタを作るために作ろうと思ったものなので、とりあえずはこんなものでいいのだ。

将来気が向いたら、リポジトリの変更をリアルタイムに反映したり、リポジトリの操作もできるように拡張してもいいかもしれないけど、実用性が感じられないので多分やらない。

因みに、goslingsというのはgeese(雁)の子供を指す、ちょっとマイナーな英語。

geese


Gitオブジェクトを見るアプリだから、GOで始まる名前にしようかと思っていて、そういえば今住んでいるFort Collinsに大量にいるgeeseの子供がgoslingsというし、並んで歩いている姿がちょうどコミットグラフのようだと思い、Goslilngsと名付けた。 単数形だとカナダのイケメン俳優かと思われてしまうので、複数形にした。goslingが一人でいることってないし。

GoslingsはSpring BootJGitなどの習作でもある。 学んだことはアプリケーションとしてアウトプットするとよく身に付くものだ。 また文章としてもアウトプットしておくとさらによく身に付き、備忘録にもなるので、Goslingsの開発メモをいくつかのエントリに分けて書いていくことにする。

まずはSpring Boot編を書こうかと思うが、その前にGoslingsの設計等について書いておく。


Goslingsのアーキテクチャ

GoslingsはWebサーバとして動き、始めにクライアントにHTML文書を返した後は、REST APIサーバとして働く。

サーバ側はJavaでできていて、Spring BootとJGitを使っている。 JGitを使いたかったのでJavaにしたが、そうでなければNodeで書きたかった。

因みに、今回はコーディングの詳細にあまりこだわらないつもりだったので、Lombokで楽をしようかと思ったけど、うっとうしいバグを踏み、どうやっても回避できなかったので使うのやめた。 二度と使うまい。

クライアント側はJavaScript(ES2015 + async/await)のSPAで、禁jQuery縛り。 React + Reduxというのをやってみたかったが、なんか大げさだしそこまで時間がとれなそうだったので、フレームワークなしで作った。ので、 「You Don’t Need jQuery」とにらめっこしながら書いた。

Gitのコミットグラフの描画には、vis.jsを使った。 Stack Overflowの回答から雰囲気で選んだけど、やりたかったことが全部できて、見た目もよかったのでよかった。

サーバはDockerで動かすためにステートレスに作ったつもりで、後述の作業ディレクトリをコンテナ間で共有し、サーバの負荷に応じてコンテナを増やしたり減らしたり、簡単にスケールするようになっているはず。

Goslingsの機能設計

Goslingsサーバにブラウザでアクセスすると、まず参照したいGitリポジトリのURIを入力するフォームが表示される。 ここにはローカルにあるリポジトリへのファイルシステム上のパス(e.g. C:\repos\project-hoge\.git)か、リモートにあるリポジトリのURL(e.g. https://repos.foo.com/project-hoge.git)を入力できる。

goslings-form


URIを入力してBrowseボタンを押下すると、Goslingsの作業ディレクトリ(デフォルトではtmpディレクトリの下のgoslings)に、ローカルリポジトリの場合はそこへのsymlinkを、リモートリポジトリの場合はベアなクローンを作成する。 いずれの場合にも、正規化したURIから生成したUID(SHA-1ハッシュ)をsymlinkファイル名とクローンディレクトリ名に使う。 サーバはリポジトリの準備ができたら、そのUIDをトークン(i.e. リポジトリ引換券)としてクライアントに渡す。 クライアントはそのトークンを使って、リポジトリの情報をサーバに要求する。

こうすることで、以下の様に後でリポジトリを取り扱いやすくなる。

  • クライアントやサーバは、可変長の長ったらしい特殊文字の含まれたURIの代わりに、40文字の数字とアルファベットだけで構成されたトークンでリポジトリを特定でき、処理がしやすい。
  • 後でサーバがリポジトリにアクセスする際、ローカルとリモートを区別する必要がないので、処理がしやすい。
  • サーバ内部でリポジトリというエンティティを扱う際、リポジトリに直接触るデータレイヤと、クライアントからのリクエストをさばくインターフェースレイヤとの間で、単なる文字列であるトークンをやりとりすればよく、データレイヤの実装の詳細をインターフェースレイヤに曝さなくてよくなり、レイヤをきれいに分離できる。これはJavaのインターフェースを作ってやってもできるが、インターフェースのAPIを考える手間を考えるとトークンの方が楽。

クライアントはトークンを受け取ったらコミットグラフビューに遷移する。

graph


このビューでの表示は以前Gitリポジトリの中身を解説した記事に合わせた。

初期状態ではコミットと参照とタグだけが表示されていて、コミットをダブルクリックするとツリーが表示され、さらにツリーをダブルクリックするとドリルダウンしていける。 ノードをシングルクリックするとそのコンテンツを参照できる。

Goslingsの使い方

Spring Bootを使ったおかげで、ビルド成果物は単一のjarで、これを以下の様に実行するだけでサーバが立ち上がる。Webアプリケーションコンテナいらず。

$ java -jar goslings-server-0.0.1.jar --server.port=80

com.github.kaitoy.goslings.server.reposDirというシステムプロパティを使って作業ディレクトリのパスを指定できる。

また、com.github.kaitoy.goslings.server.uriPrefixというシステムプロパティに値を設定すると、その値で始まるURI以外をフォームで入力するとエラーになるようになる。 リモートリポジトリを何でもかんでもクローンされるとディスク容量がいくらあっても足りないので、URLに制限をかけるために作った設定。 汎用性は考えておらず、複数指定したり正規表現を指定したりといったことはできない。

Dockerコンテナイメージもあって、以下のようなコマンドでダウンロードして起動できる。

$ docker pull kaitoy/goslings
$ docker run -p 80:80 -itd kaitoy/goslings 80 /goslings-repos https://github.com/kaitoy/

docker runの後ろの方の80 /goslings-repos https://github.com/kaitoy/が、それぞれ--server.portcom.github.kaitoy.goslings.server.reposDircom.github.kaitoy.goslings.server.uriPrefixに渡される。 --server.portのもの以外は省略してもいい。

Goslings as a Service

Goslings as a Service、略してGaaSを http://www.goslings.tk で公開している。 https://github.com/kaitoy/で始まるURLしか受け付けないようにしてある。

AWSの無料枠を活用してEC2 Container Service (ECS)でホストしていて、Freenomで無料で取得したgoslings.tkドメインとこれまた無料のFreenomのネームサーバを利用して上記のアドレスにしている。

AWSもFreenomも無料なのは12か月だけなので、それが過ぎたらGaaSは終了する予定。