今年のGitHubの草状況

去年はこんな感じでした。

takezoe.hatenablog.com

仕事で使っているprivateリポジトリも含めた状況はこんな感じ。去年と比べるとだいぶ減ってますね…。

f:id:takezoe:20161229193831p:plain

publicリポジトリだけだとこんな感じ。こちらは結構増えてます。年末にかけてコミットが増えているのはRestyを作り始めたからだと思います。

f:id:takezoe:20161229193904p:plain

仕事以外のもので外に出せないものはBitBucketのprivateリポジトリVPSに立てているGitBucketを使っていたものもあるので個人的な活動という意味ではもう少し多くなるかなという感じです。

ここから分かることは

今年は去年と比べるとあまり仕事をしていない!!

ということでは決してなくw

今年の振り返りエントリはまた別で書こうと思いますが、去年までは新サービスの立ち上げのための作業にかなり時間を使っていたのですが、今年はある程度システムも安定してきて外部での活動にも時間を割けるようになってきたということが現れているのではないかなと思います。

ちなみに昨年も引き合いに出させていただきましたが、日本のScala界隈で最も活発に活動されていると思われる吉田さんは(おそらくpublicリポジトリだけで)こんな感じ。去年よりちょっと減っている!

f:id:takezoe:20161229195216p:plain

しかし相変わらず圧倒的です。しかも、ご自身がコミッタになってるプロジェクト以外へのコントリビュートも多く頭の下がる思いです。

引き続き精進したいと思います。

GitBucketでのGitLFSサポートについて考える

GitBucketに以前から要望として上がっていたGitLFSサポートですが、どうやったら実装できるんだろうと思い軽くリサーチしてみたところ、どうやらGitblitではすでにGitLFSがサポートされているようです。

github.com

LFSサーバのソースコードの該当部分はこのへんでしょうか。単純にHTTPでアクセス可能なエンドポイントを提供すればいいようです。Gitblitのコードは参考になりそうです。

GitLFSのGitHubリポジトリには詳細なドキュメントがあります。

github.com

サーバ側の実装の参考になりそうなのは以下のようなところでしょうか。

うーん、結構大変そう。実際GitLFSを使いたいというニーズはどのくらいあるんでしょうかねぇ…。

追記:どうやらJGitにもLFSサーバの実装が入っているようです。これがそのまま使えればだいぶ楽できそう。

github.com

Scala用のDIライブラリAirframeを試してみた

ScalaではJavaと違ってDIコンテナの必要性を感じることがあまりないのですが、フレームワークを作っているとユーザコードにフレームワークが提供するコンポーネントを供給したり、フレームワーク自体を拡張するための拡張ポイントを提供するためにDIコンテナ的なものを使いたいというケースがあったりします。

PlayではGoogle Guiceが導入されていますが、もう少し簡潔でScalaらしいDIコンテナはないものかと思っていたところ@taroleoさんがAirframeというライブラリを開発されていたのを思い出したので試してみました。

github.com

基本的にはフィールドインジェクションぽい感じで、DIするフィールドを以下のように宣言しておきます。

import wvlet.airframe._

class AccountController {
  val accountService = bind[AccountService]
}

そしてDesignというバインディングを定義するオブジェクトを用意します。GuiceModule相当のもののようです。

val design = newDesign
  .bind[AccountController].toInstance(new AccountControllerImpl())

以下のようにしてDI済みのインスタンスを取得することができます。

val session = design.newSession
val controller = session.build[AccountController]

上記の例ではバインドするインスタンスtoInstanceで指定しましたが、他にもtoSingletonでシングルトンにしたり、to[T]でコンクリートクラスの型を指定してバインドしたりといろいろできます。

同じ型のコンポーネントを複数使い分ける場合、Guiceなどでは名前を指定してDIしますが、Airframeではタグを使って区別することができます。READMEの例に少し手を加えたものですが、以下のような感じです。

import wvlet.obj.tag.@@

case class Fruit(name: String)

trait Apple
trait Banana

trait TaggedBinding {
  val apple  = bind[Fruit @@ Apple]
  val banana = bind[Fruit @@ Banana]
}

val design = newDesign
  .bind[Fruit @@ Apple].toInstance(Fruit("Apple"))
  .bind[Fruit @@ Banana].toInstance(Fruit("Banana"))

Scala用のDIライブラリにはAirframeの他にもSubCutScaladiMacWireなどがあります。各ライブラリを詳細に比較したわけではないのですが、Airframeはこれらの中でも直感的ながら柔軟性も高く扱いやすいように感じます。なかなか良いフィーリングなのでもう少しいろいろ触ってみたいと思います。

Scala用のREST APIフレームワークResty 0.0.5をリリースしました

Scala用の超シンプルなREST APIフレームワークとしてRestyというものを作っています。

takezoe.hatenablog.com

github.com

前回ブログで書いてからちょこちょこいじりつつバージョンアップを重ねているので、前回のブログで紹介できなかった機能や、これまでに新たに追加した機能について簡単にまとめてみたいと思います。

全自動Zipkin

Restyはもともと全自動でSwagger、Hystrixと連携する機能を備えていましたが、これに加えてZipkinも全自動で利用できるようになりました。

以下のようにコントローラーにHttpClientSupportというトレイトをミックスインし、このトレイトが提供するメソッドを使用して別サービスの呼び出しを行うことでZipkinでトレースを行うことができます。

class HelloController extends HttpClientSupport {
  @Action(method = "GET", path = "/hello/{id}")
  def hello(id: Int): Message = {
    // Call other API using methods provided by HttpClientSupport
    val user = httpGet[User](s"http://localhost:8080/user/${id}")
    Message(s"Hello ${user.name}!")
  }
}

なお、全自動と言いつつweb.xmlで少しだけ設定が必要です。Zipkinインテグレーションを使用するかどうか、サンプリングレート、ZipkinサーバのURLを指定します。

<context-param>
  <param-name>resty.zipkin</param-name>
  <param-value>enable</param-value>
</context-param>
<context-param>
  <param-name>resty.zipkin.sample.rate</param-name>
  <param-value>1.0</param-value>
</context-param>
<context-param>
  <param-name>resty.zipkin.server.url</param-name>
  <param-value>http://127.0.0.1:9411/api/v1/spans</param-value>
</context-param>

web.xmlでの設定

全自動SwaggerやHystrixが使えるのは便利なのですが、セキュリティ上運用時はエンドポイントを無効にしたいというケースもあるはずなのでweb.xmlで設定できるようにしました。

どちらもデフォルトでは無効になっており、web.xmlに以下の設定を追加することで有効になります。

<context-param>
  <param-name>resty.swagger</param-name>
  <param-value>enable</param-value>
</context-param>

<context-param>
  <param-name>resty.hystrix</param-name>
  <param-value>enable</param-value>
</context-param>

今後はもう少し設定可能なパラメータを増やしていこうと思っています。

ケースクラスのバリデーション

JSONマッピングするケースクラスのコンストラクタでassertすることで入力値のバリデーションができるようになりました。

case class Message(message: String){
  assert(message.length < 10, "message must be less than 10 charactors.")
}

以下のようなレスポンスが400 BadRequestステータスで返却されます。

{
  "errors": [
    "message must be less than 10 charactors."
  ]
}

もう少し本格的なバリデーションフレームワークを入れようかなとも思ったのですが、Restyはシンプル第一なので標準機能としてはこのくらいにしておこうと思います。

ServletAPIへのアクセス

Restyのコントローラーは基本的にServlet API非依存ですが、Restyが提供する機能だけでは不可能な細かい処理を行う必要がある場合や、HttpSessionを使用したい場合など、Servlet APIを使う必要がある場合はコントローラーにServletAPIトレイトをミックスインするとrequestresponseHttpServletRequestHttpServletResponseにアクセスできるようになります。

class HelloController extends ServletAPI {
  @Action(method = "GET", path = "/hello")
  def hello(): Message = {
    val name = request.getParameter("name")
    Message(s"Hello ${name}!")
  }
}

まとめ

Restyは関数型プログラミングや非同期処理の知識がなくてもScalaで簡単にJSONベースのREST APIを実装することができます。サンプルプロジェクトから始めるのが手っ取り早いと思いますので興味のある方は是非試してみていただければと思います。

github.com

GitBucket 4.8をリリースしました

Scalaで実装されたオープンソースのGitサーバ、GitBucket 4.8をリリースしました。

https://github.com/takezoe/gitbucket/releases/tag/4.8

リポジトリ名での検索

GitBucketで管理しているリポジトリが増えてくると、目的のリポジトリを探すのが難しいという要望があったため、新たにリポジトリを検索するための機能を追加しました。

まず、グローバルヘッダの検索ボックスからリポジトリの検索が可能になりました。

f:id:takezoe:20161223192630p:plain

また、ダッシュボードのサイドバーに表示されるリポジトリの一覧を絞り込み検索できるようになりました。

f:id:takezoe:20161223192639p:plain

IssuesとWikiの検索

IssuesとWikiにテキスト検索のための検索ボックスを設置しました。

f:id:takezoe:20161223192749p:plain

f:id:takezoe:20161223192801p:plain

プルリクエストのコメントの改善

これまでプルリクエストのソースコードにつけたコメントは新しいコミットがプッシュされると表示されなくなってしまっていましたが、今回のリリースから新しいコミットがコメント行を変更していない場合は引き続き表示されるようになりました。

f:id:takezoe:20161223192948p:plain

この改善によってプルリクエストへのコメント機能がコードレビュー用途に使いやすくなるのではないかと思います。

このリリースは他にも以下の修正を含んでいます。

この他にも様々な改善やバグフィックスを行っています。詳細についてはIssueの一覧をご覧ください。

ポートとソケットがわかればインターネットがわかる――TCP/IP・ネットワーク技術を学びたいあなたのために (Software Design plus)

技術評論社さんから送っていただきました。ありがとうございます。

f:id:takezoe:20161210165934j:plain

内容的にそれほど踏み込んでいないということもあるのですが、わかりやすい説明とイラストのおかげで非常に読みやすいです。とはいえ、中盤では軽くですがCによるソケットプログラミングやネットワークコマンドの使い方の解説など手を動かして体験してみるパートもあります。ただ、「ポートとソケットがわかれば〜」というタイトルは若干釣りっぽい気がしないでもないですw

最近はWebアプリを作っているだけだとなかなかネットワーク周りに触れることもないのではと思うのですが、HTTP以下の知識がないエンジニアがネットワークについて最初に読むにはちょうどよさそうです。また、少し難しい部分もあるかと思いますが、非エンジニアの方が読むのにもよいかもしれません。

ちなみにこの書籍のイラストは「小悪魔女子大生のサーバエンジニア日記」の方が描かれているそうです。

小悪魔女子大生のサーバエンジニア日記 ――インターネットやサーバのしくみが楽しくわかる

小悪魔女子大生のサーバエンジニア日記 ――インターネットやサーバのしくみが楽しくわかる

JJUG CCC 2016 FallでGitBucketの話をしてきました

以前ScalaMatsuriでGitBucketについてお話しさせていただいたことはあるのですが、用途を考えると受託開発の現場で使われているケースが多いはずで、JavaコミュニティのほうがGitBucketのユーザ層に近い方が多いのでは…と思ったこともありJJUG CCCのCfPに応募してみたところ無事採択いただきました。

発表に使用したスライドは以下になります(公開用に少し編集してあります)。

www.slideshare.net

今回はGitBucketの紹介に加えて、OSSには継続性が大切だけど、個人レベルの活動だと限界があるのでコミュニティやエコシステムを作ることが必要で、そのためにはどうすべきなのか?ということをお話ししたかったのですが、いろいろと思うところがありすぎてまとまりのない話になってしまったかもしれません。

自分自身、今の会社の業務ではGitHubを使えているのでなかなかGitBucketの開発を継続するモチベーションが難しい部分もあるのですが、そこは今日お話しさせていただいたように個人で頑張るだけではなく、持続可能なコミュニティとエコシステムを作る方向に持っていくことができればと思います。

セッション後にGitBucketステッカー配布させていただいたのですが、だいぶ消費しました。会場がガラガラだったらどうしようと思っていたのですが、多くの方に参加していただきありがとうございました。

セッションの最後にもお話しさせていただいた通り、私自身もGitHubが使えるのであればそちらを使ったほうが間違いなくよいと思っています。しかし諸事情によりGitHubが使えないという場合はまずGitBucketでコストをかけずにGitを導入し、GitHubへの移行の足がかりにしていただくのもよいかもしれません。そのような形であっても開発現場の皆様のお役に立てれば幸いです。

ちなみにTISさんではかなり大規模にGitBucketをご利用いただいているようです。

もちろんGitBucketの開発にご協力いただけるのが一番嬉しいのですが、独自プラグインの開発、バグレポートや機能追加の要望などのフィードバック、ユーザサポートのヘルプなどなんでも構いませんので可能な範囲でサポートいただけるとありがたいです。よろしくお願いしますw