たごもりすメモ

コードとかその他の話とか。

LinuxCon Japan 2016に行ってきた&しゃべってきた

LinuxCon Japan、今回は ContainerCon Japanとの併催。サブトラックみたいなのもいくつかあった。
とにかく普段に自分が行くカンファレンスとぜんぜん空気が違ってて、東京都内で行われてるカンファレンスなのに会場の感じとか食事・飲み物の提供とか冷房のキツさとか、あれこれがだいぶ海外のカンファレンスっぽい。参加費が高いからできることなんだろうけど。そして海外からと思しき参加者も非常に多かった。すごいな。
日本国内からも大手メーカー系のスポンサードと参加者が非常に多かった。普段見ないあたりの世界だなあ。

しゃべってきた

プロポーザルを出してみたら通ったので初めての参加&発表だった。行ったことないので全体的にどういう空気なのかも分からないまま、初日のキーノート後の通常の発表枠の中で最初に時間だった。お、おう……。

今回はロギングに関してのアーキテクチャを議論するよ、ということで、特にコンテナを使うのが当たりまえという世界でロギングってどうやるんだっけ、どうすればちゃんとスケールさせられるんだっけ、という話をあれこれやった。

実例で特にFluentdを取り上げているけど、話の内容自体は一般論として何でもやれるはず。アプリケーション側をできるだけ単純にしつつ、ログのトラフィックの増大にどう対応するか、ログの種類の増大にどう対応するか、ストレージの性能特性によってどのように構成を考える必要があるか、などなど。
ちょっと英語でのスピーチがうまくやれなかったなと思ってたけど、聴衆から参考になったって感想言いにきてくれた人がいたので良かった。ありがたいことです。

そのほか

最近 Treasure Data が Linux Foundation のプロジェクトのひとつであるCNCFに参加したということもあって、LinuxConの分科会のひとつとしてCNCFのトラックもあって、そっちでは @repeatedly がFluentdの話をしていた。これはこれで、普段リーチしてない層に届いたのかなあ、という感じ。
あとはふらふらと各セッションを巡ってたんだけど、面白いのもあればなんだこりゃ、というのもあった。総じて、うーん、もうちょっとこう……まあカンファレンスごとのノリもあるしね、難しいよね、みたいな感じはする。

そして期間中ひたすら強烈な冷房を浴びつづけたせいか、しまいには盛大に体調を崩してしまった。きびしい。

YAPC::Asia Hachiojiに行ってきた&しゃべってきた

この週末に開催されていた YAPC::Asia Hachioji に参加してきた。2日目は体調崩してダウンしてたので1日目だけだったのが残念だけど、楽しかったー。
yapcasia8oji-2016mid.hachiojipm.org

しゃべってきた

普段あんまりプログラミングテクニックそのものについてはプレゼンをやる機会がないんだけど、Fluentd v0.14で使わざるをえなかったあれこれとか一度しゃべっとくかということで出してたので、やった。主に黒魔術について。なんだろう、使っても許される黒魔術の用途と実践、みたいな感じ?

30分という時間*1で何故そういうハックが必要なのかを説明して実装を説明して、ということになって、また大分駆け足になってしまった。が、後で聞いた感想によると前提の説明があったから良かったという話だったので、まあよかったんじゃないかなー。たぶん。
最近はアーキテクチャの話とかもっとエモめの話とかをすることが多かったので、コードそのものの話はやってて楽しかった。

いってきた

あんまり多くのセッションを聞いてないけど、みんな自分のやったことについて楽しそうに話してるなー、という感じで、参加してても面白かった。
主催のかたがた、たいへんお疲れさまでした!

*1:もっと長い時間で申請しとけばよかったって超思った

Fluentd v0.14.0 をリリースした & Fluentd meetup 2016 Summer をやってしゃべってきた

最近めっきり対外的なアウトプットが減っていたのは、ぜんぶこいつのコードを書きまくってたからです。すごい書いた。

Fluentd v0.14.0 has been released | Fluentd

ということで出ました、Fluentd v0.14.0。だいぶいろいろ良くなってるはずだけど、そのあたりはこれからv0.14対応プラグインが増えてきたりすると分かってくるかなと思う。ユーザにとっても嬉しい変更が山盛りです。
で、まずそのことをアピールしなければならんということで、Fluentd meetupではがっつりとしゃべってきた。

Fluentd meetup 2016 Summer - dots. [ドッツ]


元々45分の予定だったのに90分弱くらいしゃべってしまったらしい。すまんかった。しかし省略できそうな場所が無かった。

これからドキュメントとかいっぱい書くんだけど、他にまだまだ機能を v0.14.x のバージョンで載せていかないとだし、あれこれやるぞー、という気分。ユーザ&プラグイン開発者のみなさんからもいっぱいフィードバックいただけると嬉しいですね!

Travis CI で目当ての言語バージョンとOSの組合せを指定する

世の中のみんなは今日も頑張ってOSSミドルウェアを書いていることと思いますが、そんな我々に欠かせないのがTravis CIというサービスでして、OSSならCI環境を無料で使わせてもらえる! マジで最高のサービスだと思います。日本からだとUSの人達が元気な時間帯とズレてるせいか、pushしたあとビルドが走るのが早くて本当にありがたい。*1

で、CIを回すからには対象の言語バージョンといっしょにOSの違いも確認したい。標準の環境の Linux (Ubuntu) 以外に最近ではなんとOSX環境もあるので、ミドルウェアプログラミング野郎としてはやっぱり両方で動かしておきたいわけです。言語バージョンももちろんあれやこれや、古いの*2から新しいのまで色々動かしたい。

しかしそこには問題があって、有限のリソースというものがある以上、野放図に指定はできないわけです。

普通にバージョンを指定

単に組合せで指定したい場合は、こう:

# .travis.yml

language: ruby

rvm:
  - 2.1
  - 2.2.3
  - 2.3.0
  - ruby-head
  - rbx

os:
  - linux
  - osx

この設定を与えると Travis CI は rvm(rubyのバージョン) と os の組合せを掛け算して、5バージョン 2環境 の10ビルドを実行する。ただしこれは失敗してもいいやというものはあって、例えば ruby-head や rbx ではビルドは動かしておきたい、がコケても失敗とは見做さない*3、とかしたいことがある。この場合は allow_failures というやつでその指定をすることになる。

matrix:
  allow_failures:
    - rvm: ruby-head
    - rvm: rbx

ビルド条件をもっと細かく特定して指定

ただしこれも色々あって、言語バージョンの指定が割とざっくり("2.1" とか)しているならいいんだけど、細かくバージョンを指定したくなった場合、実はあれこれ制約が出てくる。Ruby 2.1といっても2.1.xの最新版で実行したいとなったりすると、まずどのバージョンがTravis上で使えるのかを調べる必要がある。Rubyの場合は以下のページ(言語ごとにあるのでドキュメントページから探そう)。

Travis CI: Precompiled Ruby Versions

これを見るとわかるのが、各OSのバージョンごとに使える言語バージョンが決まっている、ということだ。細かい言語バージョンまで指定する場合、それが動く環境を選ぶようにしてやる必要がある。*4
ということで、例えば Ruby 2.1.10 でテストを実行したければ OSX 10.10 もしくは 10.11 を指定する必要がある……んだけど、Travis CIのドキュメントを見てもぱっとわかるページがない。困ってたところ教えてもらった。ここにあった。

Building an Objective-C Project - Travis CI

Objective-C! いやまあ実際にはObjective-C環境もXcode自体も(直接的には)要らないんだけど、これを経由して間接的にOSXのバージョンを指定してやることができる。
これが本当にMacでしか動かないでいいビルドなら設定全体に osx_image を指定してやればいい。つまり、こう。

language: ruby

rvm:
  - 2.1
  - 2.2.3
  - 2.3.0
  - ruby-head
  - rbx

os:
  - osx

osx_image: xcode7.3

matrix:
  allow_failures:
    - rvm: ruby-head
    - rvm: rbx

しかし我々はLinuxでも走らせたいのでこれでは困る。ちなみに上記の設定で単純に Linux でも動かすようにすると*5、以下のようになる(ビルドがこけてるのは別の理由)。もしかしたら実害はないのかもしれないが、キモいしギョッとするのでこれはイヤだ。

f:id:tagomoris:20160419130017p:plain

ということで、環境の組合せを直接指定することになって、これは matrix のもうひとつの機能であるところの includes を使う。

language: ruby

# http://rubies.travis-ci.org/
# See here for osx_image -> OSX versions: https://docs.travis-ci.com/user/languages/objective-c
matrix:
  include:
    - rvm: 2.1.10
      os: linux
    - rvm: 2.2.4
      os: linux
    - rvm: 2.3.0
      os: linux
    - rvm: ruby-head
      os: linux
    - rvm: 2.1.0
      os: osx
      osx_image: xcode7.3 # OSX 10.11
    - rvm: 2.2.4
      os: osx
      osx_image: xcode7.1 # OSX 10.10
    - rvm: ruby-head
      os: osx
      osx_image: xcode 7.3 # OSX 10.11
  allow_failures:
    - rvm: ruby-head

これは勝手な想像だけど、Travis CIの内部的には rvm や os の組合せから matrix を作っているんじゃないかなーという気がする。で、この指定方法はその内部表現(に近いもの)を直接指定していることになる、んじゃないかな、たぶん。
やること自体はこれだけだけど、探し回ってもあんまり良い設定サンプルが無かったので、ここに書いておこうと思った。これで求めているビルド環境の組合せが作れた。

f:id:tagomoris:20160419130629p:plain

なお、matrixの元になる掛け算対象の設定項目リストは、それぞれの言語のドキュメントページにその名も "Build Matrix" として項目がある。

https://docs.travis-ci.com/user/languages/ruby#Build-Matrix

まとめ

Travis CIさんにはいつもいつもお世話になっております。ありがとうございます。
あとWindows環境は AppVeyor を使わせてもらってます。こっちもお世話になっています。ありがとうございます。

*1:USのお昼にpushするとマジでビルドが走るまでの時間が違うのが体感できる……気がする

*2:ほどほどに古い、サポート対象にしても構わないもの、という意味

*3:GitHub上でのpull-requestのCIとかはグリーンつまり成功と表示される

*4:Linuxの場合はUbuntu 12.04が標準の環境だからか、困ったことはない。14.04だけにしか無いバージョンを指定する必要があったらどうするんだろう?

*5:逆に言うと普通にLinuxでも動かす設定に osx_image を加えると

GradleでMaven Centralにライブラリを公開する

前にこんなエントリを書いたが、このときはmavenから実行してた。今回はgradleから。参考にしたエントリはいくつかあったけど、ずばりというのがなくてつらかった。あれこれ試して組み合わせた。

はじめてのmaven central 公開 - たごもりすメモ

あとMaven Central(というかSonaType OSS)もちょっと変わってるのでそのへんも。なお環境は適当なMacに適当にgradleを入れた。以上。

前と変わらないところ

  • GPGのセットアップ
  • パッケージ名前空間を決める
  • アカウント登録

パッケージ名前空間は今回は前のと違ったので、申請は今回もやった。前と同じようにやってさくっと完了。

gradle環境の設定

"$HOME/.gradle/gradle.properties" に行う。

org.gradle.daemon=true
signing.keyId=DEADBEEF
signing.password=mypassphrase_for_gpgkey
signing.secretKeyRingFile=/Users/tagomoris/.gnupg/secring.gpg
sonatypeUsername=tagomoris
sonatypePassword=mypassword_for_sonatype

最初の1行は普通の便利設定で、他はJarの公開用。
パスワードやパスフレーズを毎回コンソールで聞かせる設定とかにする流儀もあるみたいだけど、とりあえずパス。ベタ書き。ここに書いておけばgradleの maven plugin が読んでくれる。

build.gradle の記述

がんばった。全体はここにあるので、ポイントをいくつか抜き出して書く。

apply plugin: "java"
apply plugin: "application"
apply plugin: "maven"
apply plugin: "signing"

group = "net.isucon.bench"
archivesBaseName = "isucon-bench"
version = "0.1.1"
description = "Benchmark framework for Web applications, especially for ISUCON"

java と application プラグインはビルドと実行用のもの、maven と signing がmaven centralでの公開用のもの。その下はパッケージのメタデータ宣言用。あとで使う。

maven-publish プラグインというのもあるみたいだったが、あれこれ試したところそれは自分で maven repository server を作って運用するようなときに、そこにpushするためのものっぽい。code signingと組み合わせるとうまく動かないという話が多くて、自分もやってみたところどうもダメな感じだった。なんかものすごい色々コード書けばできる的な話もあったけど、何のためにプラグイン使ってんのか分からなくなる的な展開が見えて避けた。

//set build variables based on build type (release, continuous integration, development)
def isDevBuild
def isCiBuild
def isReleaseBuild
def sonatypeRepositoryUrl
if (hasProperty("release")) {
    isReleaseBuild = true
    sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
} else if (hasProperty("ci")) {
    isCiBuild = true
    version += "-SNAPSHOT"
    sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
} else {
    isDevBuild = true
    version += "-SNAPSHOT"
}

repositories {
    mavenCentral()
}

普通にビルドしただけでSonaTypeに公開されたらたまらんのでリリース作業用の設定を明示的に行うように変更。CIの場合はSNAPSHOTを公開用とは別の場所に上げるようにしている。まあCIまわしてないんだけど……他で(ちゃんとやるケースで)真似したくなったときのために。

dependency, compileJava, mainClassName, run あたりは普通に java, application なビルド/実行のためのものなので割愛。javadocJar, sourcesJar, artifacts は見ればわかるので割愛。

signing {
    required { isReleaseBuild }
    sign configurations.archives
}

uploadArchives {
    repositories {
        if (isDevBuild) {
            mavenLocal()
        }
        else {
            mavenDeployer {
                if(isReleaseBuild) {
                    beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
                }

                repository(url: sonatypeRepositoryUrl) {
                    authentication(userName: sonatypeUsername, password: sonatypePassword)
                }

                pom.project {
                    name 'isucon-bench'
                    packaging 'jar'
                    description 'Benchmark framework for Web applications, especially for ISUCON'
                    url 'http://www.example.com/example-application'

                    scm {
                        url "scm:git@github.com:isucon/isucon-bench-java.git"
                        connection "scm:git@github.com:isucon/isucon-bench-java.git"
                        developerConnection "scm:git@github.com:isucon/isucon-bench-java.git"
                    }
                    licenses {
                        license {
                            name 'MIT'
                            url 'https://opensource.org/licenses/MIT'
                        }
                    }
                    developers {
                        developer {
                            id 'tagomoris'
                            name 'Satoshi Tagomori'
                            email 'tagomoris@gmail.com'
                        }
                    }
                }
            }
        }
    }
}

このへんも見ればだいたいわかるが、丸っと書いてあるページがなくて難儀した。開発時ビルドにはスキップする設定で、書名とかパッケージのメタデータとかが書いてある。

この設定を書いておいたら、あとはコマンドでは "gradle clean && gradle uploadArchives -Prelease" すればSonaTypeのリポジトリにアップロードまでやれる。単に uploadArchives するとなんか変なゴミが含まれたJarが作られてしまった気がしたのでいちおう今のところはこうしている。それは不要だとか、綺麗なJarを一発で作る方法があったら教えてほしい。

まあなんにしろ、これでうまくいく。

$ gradle clean && gradle uploadArchives -Prelease
:clean

BUILD SUCCESSFUL

Total time: 0.863 secs
:compileJava
注意:入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。
注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。
:processResources UP-TO-DATE
:classes
:jar
:startScripts
:distTar
:distZip
:javadocJar
:sourcesJar
:signArchives
:uploadArchives
Could not find metadata net.isucon.bench:isucon-bench/maven-metadata.xml in remote (https://oss.sonatype.org/service/local/staging/deploy/maven2/)

BUILD SUCCESSFUL

Total time: 1 mins 3.332 secs

なんか通知ぽいものが出ているが、これはSonaTypeのリポジトリが新しくなって以降出る(ことがある)ようになったもの。とりあえず無視してよい。

SonaType Nexus Repositoryでの手続き

これが変わったところ。先程のコマンドでSonaTypeのリポジトリには格納された(stagingになった)はずだが、そこから先の処理をワンステップやらないといけない。新しいWeb UI (Nexus Repository)が登場する。
なお以下のページに案内がある。スクリーンショットとかあって前よりだいぶ分かりやすいので、読むとよい。

Releasing the Deployment

で、具体的にはこのページを開く: https://oss.sonatype.org/index.html#stagingRepositories

認証は作成してあるSonaTypeのアカウントで通れる。(開いてなければ)左側のメニューから "Staging Repositories" をクリックすると、いろいろ見られるリストの中に自分がアップロードしたっぽい名前があることを確認する。

https://i.gyazo.com/d6a722eb1925c3009627bceed2b8f549.png

選択すると上のメニューで "Close" と "Drop" のボタンが有効になるはず。なったら "Close" をクリックして、ダイアログから "confirm" する。このときパッケージになにか問題があるとエラーになるらしい(なったことがない)。問題がなければ該当の staging repository の状態が closed になる。問題なければそのまま "Release" ボタンが有効になるので、押してリリース。

完了したらリポジトリの管理チケットに完了したよとコメントを書くと、staging -> release の手続きの自動化を有効にしてもらえて、一件落着。リリースされたら、Nexus Repository内でパッケージ名で検索したとき、該当バージョンが releases 下にあるように表示されるからわかるはず。

完了!

なお最近試したところ Maven Central の検索画面に出てくるようになるまではだいぶ時間がかかった。が、その状態で pom.xml に書いてみたところ正常にダウンロードできたので、あまり気にする必要はなさそう。
あと一度自動リリースが有効になったリポジトリで staging を手動で close してみたら、なんか変なことになったかも。stagingから出ていかなくなってしまった。焦らず落ち着いて様子を見よう。

なんにしろ、これでできた。やってしまえばなんとかなる。便利。

CROSS 2016に行ってきた&しゃべってきた

2016.cross-party.com

先週金曜に横浜大さん橋ホールであったCROSS 2016に行ってきた。上記のセッションにスピーカーの一人として誘っていただいてたので、参加して、日本で・国をまたいで仕事をするということについて思うところをしゃべったりとか。
これは日本で働くか米国に移住するかみたいな二択では決してなく、いろいろ日本にいながらやれることはあるし、逆に最低限やっておかないといけないことももちろんある*1、でもまあ技術がちゃんとあっていいコード書けることも大事だよね、とか思いながらしゃべっていたが、ちゃんと伝わったかなあ。

いっしょに登壇してた @kuenishi さんの以下のエントリに @hasegaw さんのtweetが引用されてるけど、そうそう、そういう感じなんだよ! という気はします。

エンジニアCROSS 2016で登壇してきました - kuenishi's blog

興味があったら上記CROSSのセッションページに動画があるので、そちらをどうぞ。

CROSSについて

大勢の参加者がいてすばらしいことだけど、セッションのテーマが働きかたとか転職とかにだいぶ寄っているような気はして、(自分もそういう系ので話しておいてなんだけど)だいぶ食傷気味になる、という気がする。これが求められているということなら、自分の好みのカンファレンスとはちょっと違ってきたなあ、という感想になった。

あともうとにかく音響がひどい。自分たちがしゃべっているとき、比較的近くでデイリーポータル(?)の企画かなにかがすごい音量でアナウンスしててつらかった。後ろのほうの席の人、こちらの話し声が聞こえてなさそうだったしなあ。ホールの雰囲気が面白いのはわかるけどあれじゃ本末転倒だ。

終わったあと近くのビアバーで飲んでたけど、途中から合流した某社の若い人になんかおっさんくさいことを説教っぽくしゃべってしまった気がする。おっさん力の向上がつらい。

*1:OSS、コメントやコミットコメントやドキュメントやメールでの英語のやりとりなど