rubyにコントリビュートする方法
rubyのバグらしき挙動を見つけたのでパッチを書いて送ってみたら、すぐに取り込んでもらえました。
https://bugs.ruby-lang.org/issues/12948
https://github.com/ruby/ruby/commit/f6e77b9d3555c1fbaa8aab1cdc0bd6bde95f62c6
rubyはGithub上でもPullRequestを受け付けているようなのですが、せっかくの機会なので正規のルートでパッチを送ってみることにしました。
やり方について調べてみたことを、次の機会のためにここに記しておきます。
バグの発見
Loggerがおかしな挙動をしていることを同僚の方が発見したので調べてみました。
ずっと昔にrubyのバージョンを2.2系にあげたのですが、そのタイミングからログファイルがローテーションされていないようなのです。
すでに存在しているログファイルがどれだけ過去のものであろうと、Loggerはローテーションせずに書き込みをしてしまいます。
require 'logger'
File.open("tsuka.log", "w") {}
File.utime(*[Time.mktime(2010, 1, 1)]*2, "tsuka.log")
logger = Logger.new("tsuka.log", "daily")
logger.info "test"
logger.close
p Dir.glob("tsuka.log*")
ruby2.2以降
["tsuka.log"]
ruby2.1以前
["tsuka.log", "tsuka.log.20161117"]
調べてみたところ、ruby2.2以降と2.1以前とで挙動が変わっています。
本当にバグか
バグの報告については正規のドキュメントがあります。
HowToReportJa
最新版で確かめてみる
最新版(2016/11/18現在では2.3.2) で確かめたところ、2.2と同じ挙動になりました。
仕様の変更の可能性
ただ単に仕様が変更された可能性もあります。ChangeLogを読んでみたりググったりしてみました。
ChangeLogから、ローテートまわりに手が加えられたことはわかりました。しかしそれはバグの修正であり、仕様の変更ではなさそうです。
2.2で変わったこと、みたいなweb上の記事にもLoggerの仕様が変わったというような話は見つかりませんでした。
すでに報告済みかどうか
これがバグだとして、すでに報告されている可能性もあります。
しかし軽くググってみたり、Ruby Issue Tracking System を検索してみましたが、この現象に関する報告らしきものはありませんでした。
rubyの開発環境を整えてデバッグする
rubyの本当の最新状態はsubversionで管理されているリポジトリのtrunkになります。
Github上のリポジトリと、本家のリポジトリを見比べてみたところ、差異はないようでしたので、Githubからコードをとってくることにしました。
コードの取得
git clone https://github.com/ruby/ruby.git
開発環境の用意
開発のための手引きは DeveloperHowtoJaにあります。
ビルドに必要なものはここに記載されていました。
autoconfの現在のバージョンを見てみます。
$ autoconf --version
autoconf (GNU Autoconf) 2.69
2.60以降のため、問題なさそうです。
$ bison --version
bison (GNU Bison) 2.3
bisonも2.2以降です。
このあたりが足りなかったり、バージョンが低かったりしたときは、個々のプラットフォームにあわせてインストールしたりバージョンアップしましょう。
ビルド
$ autoconf
$ ./configure
$ make
テストの実行
とりあえずテストを走らせてみます。
今回はパッチも書くつもりなので、ruby全体を壊していないことを担保するために全体テストも実施します。
$ make update-rubyspec
$ make test-rubyspec
update-rubyspec
はspecの更新、 test-rubyspec
はspecへの適合をテストします。
テストも実行します。
$ make check
check
は test
と test-all
を実施します。test
は簡単なテストの実施、test-all
は詳細なテストの実施です。
Loggerのローテートまわりの責務を持っているのは、Logger::LogDeviceのようですので、それだけを対象としたテストもパッチを書きながら都度実施したいところです。
check
は全テストなので時間がかかります。単体のテストファイルを実施するには以下のようにします。
$ make test-all TESTS=test/logger/test_logdevice.rb
デバッグ中はこれを使っていきます。
デバッグ
これはやるだけです。テストもちゃんと書きます。
完了した後、rubyを壊していないかを確かめるために以下を再度実行して問題がないことを確認しておきます。
$ make update-rubyspec
$ make test-rubyspec
$ make check
パッチをそえてバグを報告する
パッチの作り方
git上で修正したのなら、ローカルリポジトリにコミットした上で以下を実行します。
$ git diff --no-prefix HEAD~ > name_of_patch.patch
Isuueの登録
Ruby Issue Tracking Systemにバグを報告します。
- トラッカーは Bug
- 題名を60文字程度で書く
- 説明には、バグについてとそれを再現可能なコードなどを書く。期待する挙動と、実際の挙動を書いて何が問題なのかをわかりやすく
- ステータスと優先度はデフォルトのまま。優先度を自分の勝手な判断で
High
とかにしないように - 担当者は空で
- ruby -vは、バグを発見した環境の
ruby -v
の結果をはる。 - 報告先は日本語か英語かで選択
- パッチやバックトレース、ログ等があれば添付する
日本語で書いても大丈夫のようですが、つたなくても英語で書いたほうがいいと思います。今回は自分の英語で表現できる内容では十分でないように感じたので、日本語での補足も書きました。
以下は私が報告したIssueです。
https://bugs.ruby-lang.org/issues/12948
待つ
リアクションがあるまで気長に待ちます。
今回の場合、報告してから1時間もしないうちにtrunkにパッチを取り込んでもらえました。
https://github.com/ruby/ruby/commit/f6e77b9d3555c1fbaa8aab1cdc0bd6bde95f62c6
エラーが出てテストが通らないとき
たとえば、LoadError: cannot load such file -- openssl
などのエラーがでて、make test-rubyspec
などが通らないことがあります。
この場合はそれぞれの環境に応じて、.configure
にオプションを渡してあげる必要があります。
私の環境はMacで、ほとんどのパッケージはhomebrewで管理しています。
opensslのエラーが出たので以下のように対応しました。これでテストが通るようになりました。
$ brew --prefix openssl
/usr/local/opt/openssl
$ ./configure --with-openssl-dir=/usr/local/opt/openssl
$ make