Help us understand the problem. What is going on with this article?

【曲芸】社内向けツールをGemで、Gem Serverなし・バージョンつきで配布する方法

More than 3 years have passed since last update.

実用性はともかく曲芸として個人的に面白かったので共有しておきます。

社内向けのツール、その名もtoolsを下記のような要件で配布したくなりました。

  • CLI
  • gemとして配布
  • gem server無し
  • バージョンを表示できる

まず、

  • gemとして配布
  • gem server無し

これは https://github.com/rdp/specific_install を使うとできる。

$ gem install specific_install
$ gem install git@github.com:your-company/tools.git

次に

  • バージョンを表示できる

これを実現するにはいくつか課題がある。

  • Tools::VERSIONを更新する
    • どうせ頻繁に更新されるんだし、いちいちインクリメントするのが面倒くさい。絶対忘れる。
  • Gitのcommit hashを出力する
    • 当然コミット毎に一意に定まるので頻繁に更新されるツールのバージョニングとしては悪くない。
    • $ tools --sha$ git log --pretty="%h" -1の結果を出せばいいのでは?
    • gemはtools.pkgにファイルをまとめた形で配布される。これはGitリポジトリではないので、gitコマンドは使えない。

ということで、試行錯誤の末、gemspecの中でTools::VERSIONにcommit hashを文字列リテラルとして更新するコードを生成するという方法で実現しました。gemspecはRubyのDSLとして実行されるので、その途中でファイルを書くことは可能なのです。
さらに、specific_installは一時ディレクトリでgit clone してrake installしているので、gitコマンドが使える。

下記、具体的な手順です。

元となるファイルはこんな感じでコミットしておく。

lib/tools/sha.rb

module Tools
  SHA = "undefined"
end

tools.gemspec

Gem::Specification.new do |spec|

  # Update sha.rb
  sha = `git log --pretty="%h" -1`.chomp

  sha_rb = <<SHA
module Tools
  SHA = "#{sha}"
end
SHA
  File.open(File.expand_path('./lib/tools/sha.rb'), 'w') { |f| f << sha_rb }

# 以下略

これで$ gem build tools.gemspecすると

module Tools
  SHA = "cd570fa"
end

というふうに最新のcommit hashを代入するコードが生成され、それがGemとしてパッケージングされる。

バージョンを表示するには、このTools::SHA を適宜出力すればよい。

以上です。もうちょっとまともな方法がある気がするので、妙案があれば是非教えてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away