Redmineで細かなバグの扱いで悩んだけど、使い方の改善だけでなんとかなりそう

1つあたり平均5分もあれば直せそうな細かなバグが数十個とか報告されて、Redmine上での扱いをどうしようか悩んだ。

Redmineの使い方は割と普通。デフォルトからあまりいじっていない。プラグインも入れていない。ちょっと変わっているのが、自分一人で使っているということくらいだけど、ま今回はあまり関係ない。

RedmineとGitの連携はしていないが、チケット単位でブランチを切っている。また、作業時間のログを別途取っているのだが、それもチケット単位で、かつ30分単位でやっている。

という感じの前提。

まず思ったのが、こんな報告一つにつきチケット一つなんて面倒臭えよ、ってこと。

ただ、なんとなく面倒臭えよと思ってるだけじゃ駄目なので、具体的になにを面倒臭いと感じているのか、考えてみた。考えたというよりただ思い付いたことをメモっただけか。

  • 細かなバグがたくさんある。
  • いちいちチケットにするの面倒。
  • ぜんぶチケットにしたら、わざわざブランチ切ったり、作業時間のログ切り替えたりするの面倒。
  • ぜんぶチケットにしても、同じ原因のバグとかどうするの。
  • Redmineのチケット一覧性いまいちなんでまとめた後に内容を確認するのが面倒。
  • Redmineのチケット、テンプレートとかなくて不定形になるのでそこも面倒。

こうして羅列したものを一つずつ、どうすればいいか考えていった。

  • 細かなバグがたくさんあるのは、面倒だけど仕方ない。
  • ブランチや作業時間のログとの不一致は俺の作業方法の問題。ただこれは、Redmineの親チケット機能でまとめればなんとかなりそう。
  • 同じ原因のバグは、後から重複チケットとしてまとめればいい。
  • チケット切ること自体の面倒さと、テンプレートがない件は、URLクエリでデフォルト値を突っ込む方法 http://atotto.hatenadiary.jp/entry/2013/08/27/212556 で緩和できそう。
  • 一覧性の問題は、カスタムクエリで頑張れ、かな。今回知ったが一応チケットの本文も一覧に出すことはできるっぽい。

ということで、ほとんどの問題は解決するか、完全にはしなくても緩和できそうだった。


特にオチもないのだが、つらいと思ったときに思っただけで終わってちゃ駄目だよね、という話。

WindowsでVagrantでPageant使ってSSHエージェント転送

なんかはてなブログの下書きの仕様が変わったのか、書いてたの途中で消えちゃったので面倒なので適当に。

WindowsVagrantでPageant使ってSSHエージェント転送するのは簡単だよという話。provisionでGitとか叩くときとかに必要になるアレ。

  • GIT_SSHplink.exeのパスを。
  • Vagrantfileにconfig.ssh.forward_agent = trueを。
  • もちろんPageantにキー突っ込んでおく。

だけで行ける。簡単。

ただこれだけだと、provisionerからroot以外にsuとかsudoするとかした場合にそのままだと行けない。ので、

  • provisionerでSSHする前に、Defaults env_keep += "SSH_AUTH_SOCK"とかをsudoersに突っ込んで、環境変数を渡しつつ、
  • setfacl -R -m u::rwx "${SSH_AUTH_SOCK%/*}"なりして、権限も与える。

とやる。

SSH Agent-Forwarding works, but what about sudo -u username no shell/ permissions? composer - Unix & Linux Stack Exchange

その他数ヶ所参考にしたんだが、どこだったやら……。

vagrant-cachierはvagrant-vbguestと競合するっぽい

WindowsVagrant 1.9.1にcachier, vbguestのプラグインを入れた状態で、

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.synced_folder ".", "/vagrant", type: "virtualbox"

  config.vm.provision "shell", inline: "sudo yum update -y kernel"

  config.cache.scope = :box
end

みたいなVagrantfileを用意。vagrant upして、続いてvagrand reloadすると、

$ vagrant reload
==> default: Attempting graceful shutdown of VM...
==> default: Checking if box 'centos/7' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
==> default: Machine booted and ready!
[default] No installation found.
Loaded plugins: fastestmirror


Error making cache directory: /var/cache/yum/x86_64/7/base error was: [Errno 2] No such file or directory: '/var/cache/yum/x86_64'

==> default: Checking for guest additions in VM...
    default: No guest additions were detected on the base box for this VM! Guest
    default: additions are required for forwarded ports, shared folders, host only
    default: networking, and more. If SSH fails on this machine, please install
    default: the guest additions and repackage the box to continue.
    default:
    default: This is not an error message; everything may continue to work properly,
    default: in which case you may ignore this message.
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

yum install -y kernel-devel-`uname -r` gcc binutils make perl bzip2

Stdout from the command:

Loaded plugins: fastestmirror


Stderr from the command:



Error making cache directory: /var/cache/yum/x86_64/7/base error was: [Errno 2] No such file or directory: '/var/cache/yum/x86_64'

こんな感じのログを吐いて失敗する。

vagrant reloadでなく、vagrant haltしてからvagrant upだったり、あるいはcachierプラグインが入っていなかったりする場合は問題ない。

(なお、もう一つVMが立ち上がっているためポートが競合しているが、そこは本題とは関係ない)

かなり調べても原因が確定できなかったのだが、とにかくvagrant reloadの場合、GuestAdditionsインストールのためのyum update前にcachierのディレクトリが用意できないとか、その辺の理由で失敗しているようだ。

この問題自体もやっかいだが、この問題を調べている途中に気付いた以下の点がさらに酷いと感じている。Vagrantは正直、仕事で使いたいと思わない。

  1. 公式ドキュメントに書いてある"The equivalent of running a halt followed by an up."が思い切り嘘であること。
  2. プラグインを一時的に無効にすることなどが不可能なこと。
  3. 同じVagrantfileでもインストールされているプラグイン次第で挙動が変わること。

つらい。

追記。

追試しやすいようVagrantfileを最小限にしたからアレな感じになったけど、yum updateでぜんぶ更新、とかやると(カーネルを更新しないよう除外していなければ)同じようになる。

じっさい、Ansibleでyum: name='*' state=latestしてはまった。

composer updateでよくわからないエラーメッセージが出たが、指定したブランチがないだけだった

あるアプリケーションが依存している Git リポジトリがあったのだが、master 以外のブランチを参照することになった。ので、composer.json を更新して composer update したら、

The requested package <VENDOR>/<REPO> <BRANCH> exists as <VENDOR>/<REPO>[dev-master] but these are rejected by your constraint.

というよくわからないエラーが出た。

指定したブランチが別名で(というか master として)存在しているがあなたの制約でリジェクトされた、ってどういうこと?

いろいろ調べたがけっきょくわからず、もしやと思って依存リポジトリの方を確認したらけっきょく、参照したいブランチがリモートに push されていなかっただけだった。

master はあるけど指定されたブランチはないよ、master はあなたが指定していないから使わないよ、と言いたかったのだろうか。わからんって。

Vagrantのsynced_folderにはあまり期待してはいけない

そもそもなにがしたかったか

Vagrant + VirtualBoxで開発環境を作ろうとしていて、デフォルトのvagrantユーザで作業するのもアレなんでprovision(今回はansible_local)でユーザを作って、そのユーザのホームディレクトリをホストOSと共有したかった。

試したことと当たった問題

  1. config.vm.synced_folderowner, groupにユーザ名・グループ名を普通に指定。
    • id: magai: no such user
    • フォルダの同期→provisioningの順番なのか。
  2. provisioner側でmountする。
    • mounting failed with the error: Protocol errorとか言われる。
    • どうも、ホストOS側からVirtualBoxに指示(GUIなどから?)しないとホストOS側のパスが見えない? ちょっとここ原因が最後までわからなかった。
  3. 仕方ないので、synced_folderで、uid, gidで直接指定しつつ、provisioner側で、uid, gid指定でユーザ、グループを作成。
    • mount_optionsがおかしいのか、これも動かない。普通にvagrant:vagrantのままになっていた。

そして、解決しないままいろいろ試していて気付いたのだが、ホームディレクトリを共有するとなると、~/.ssh/なども共有することになるが、ご存知の通りこの辺パーミッションが厳密でないと動作しない。

なのにsynced_folderではディレクトリ・ファイルのパーミッションを1つ設定するだけで、細かいことはできないし、そもそもホームディレクトリを共有しても問題ばかりで駄目かなと。

あきらめた。

おまけ: 関連して引っかかった細かい問題

  1. Ansibleのmountモジュールのpathパラメータが、今回使ったバージョンのAnsibleではまだnameだった。
  2. Ansibleのsudo: yesがbecome: yesになっていた。
  3. Ansibleのuserモジュールにgidパラメータがなかった。issueは立っているので、今後修正されるかもだが、今はいちいちgidを指定してgroupを作ってから……と二度手間になる。

今後確認すること

  1. ユーザが存在する場合のみsynced_folderを設定する、ということはできないか?
  2. VirtualBoxの共有機能のパーミッション周りにはどれくらい制限があるか。

plenvでバージョン指定して実行できるやつを作った

Perlで書いたWebアプリケーションのデプロイにはCinnamon使っているのだけど、これはPerl 5.14以上が必要。Perl 5.10 でやらなきゃならない案件があって、plenv local 5.10.1とかしているので、Cinnamonが使えない。さあ困ったとなった。

回避策として考えられたのは、

  • PATH="$PLENV_ROOT/versions/5.18.0/bin:$PATH" cinnamon ...みたいに実行する。plenv-execのヘルプに書いてあるやり方。
    • ダーティだし忘れそう。
  • $SHELL -lc 'plenv shell 5.18.0; cinnamon ...'みたいにplenv shellでアレする。
    • 上のよりはわかりやすいけど、ハックっぽいし補完効かないし。

ということで素直に作ることにした。plenv execほぼそのままで、plenv exec-withというのを書いてみた。

github.com

せっかくなのでGitHubにアップしてみた。GitHubリポジトリ作るの初めてだってのは自分でもおどろき。

今後はもうちょっとGitHub活していきたい。いい仕事欲しいしね。

SQL::Translator の罠

今までデータベースのマイグレーション

DBIx::Migration - Seamless DB schema up- and downgrades - metacpan.org

を使っていた。スキーマを変えるためのクエリをそのまま保存すれば migrate できるので非常にお手軽。ではあったものの、変更の数があまり多くなると現在のスキーマを確認するのが面倒臭くなってきたので、別の方法を探していたところ、

papix.hatenablog.com

などを見つけた。が、 Anego も GitDDL も、ちょっと求めているものとは違う感じなので、 SQL::Translator を生で使おうかといろいろ試したのだが、これがまあ酷い品質だった。

本当はもっときっちりまとめたかったが、数が数なんで箇条書きで。なお GitHub で一応開発は続いているようで、このうちの1つ2つは直っているっぽい。ちゃんと確認はしていないが。

  • ファイルの読み込みで encode してくれないので、非 ASCII 文字は化ける。 filename() は使わず自前で読み込んで、 data() に渡せばおけ。
  • SQL::Translator::Schema::Table->options にデータを追加する方法がわかりづらい。 ListAttr という独自の Moo::Role を使っている上、 options を読み込む SQL::Translator::Producer::MySQL 側のコードもわかりづらい。
    • $table->options({ $key => $value }, { ... }, ...)の形か、追加モードなので options() を複数回実効してもいい、模様。
  • SQL::Translator::Parser::DBI::MySQL からスキーマを持って来ると、 AUTO_INCREMENT の初期値まで入るので鬱陶しいが、その初期値を SQL::Translator::Schema::Table->options から削除するのがまたやっかい。
  • DBI->connect の第4引数が固定。つまり mysql_enable_utf8 とか使えない……。 dbh を生で渡せるので、自前で用意して渡す。ただし、 SQL::Translator::Parser::DBI 側のデフォルトの第4引数に追加する形にしないと問題が出うる。
  • ほとんどのメソッドが die せず戻り値が偽であることによってエラーを表現している。ぜんぶチェックするのは大変なので、 new() か translate() あたりにぜんぶパラメータ突っ込んで、まとめて対応するのがよさそう。
  • filters() 周りの挙動が、ドキュメントと実装でかなり異なっている。
  • SQL::Translator::Filter::DefaultExtra がどうも完全に壊れている。十分に検証はできていないが。
  • SQL::Translator::Parser::MySQL でコメント周りのパースがおかしく、コメントの位置によっては落ちる。
  • これは MySQL の仕様的なところもあるが、 BOOL などはデータベースから引いてくると tinyint(1) になるがその辺を吸収してくれない。

どうにもコードが汚くて読むのが本当につらかった。これ Moo ベースなんだけど、せめて Moo なしだったならもうちょっと読みやすかったんじゃないだろうか。

あと、自分の使い方的には INSERT も見て欲しいんだけどそこは無視される。まあ仕方ないけど、どうしたもんだろう。

機能的には便利なので、これベースで簡単なスクリプト書いて DBIx::Migration の代わりにするつもり。