何らかの理由で外部に公開はできないgemがあって、それを使ったRubyアプリケーションをデプロイする場合にどうしたらいいのか調べてみた。
何らかの理由というのは、まだ開発途中で試験的に使ってみたいとか、ビジネスに特化した機能であって外に公開できないなど、いくつかあると思う。複数のRubyアプリケーションを扱っている会社なんかだと、共通する機能をgemにしたりするだろうから、ありえるシナリオだと思う。
もくじ
TL;DR
- GitHubのプライベートリポジトリにアクセスできるパーソナルアクセストークンを発行
- ローカル環境では、
bundle config github.com *********:x-oauth-basic
(*********
はパーソナルアクセストークン) でクレデンシャルを設定 - デプロイ先の実行環境では、
export BUNDLE_GITHUB__COM=*********:x-oauth-basic
などで環境変数でクレデンシャルを設定
Gitリポジトリで公開されているgemを使う
bunlderでは、rubygems.org やパッケージ管理サービスで配布しているものだけでなく、gitやgithub上のgitリポジトリで公開されているgemも使用することができる。
qiita.com Bundler: How to install gems from git repositories
Gemfile
内で、gem
にgit
オプションを付けることで
source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } # gem "rails" gem 'sample_private_gem', git: 'https://github.com/satoryu/sample_private_gem.git' gem "rack", "~> 2.0"
プライベートリポジトリで公開されているgemを使おうとするとどうなるか
ここで登録されているsample_private_gem
がGitHub上のプライベートリポジトリで公開されている場合、デプロイすると何が起こるのか。
試しに、Heroku上にデプロイしてみると、途中で該当のgemを取得できずにデプロイが失敗する。
$ git push heroku master Enumerating objects: 7, done. Counting objects: 100% (7/7), done. Delta compression using up to 4 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 699 bytes | 699.00 KiB/s, done. Total 4 (delta 0), reused 0 (delta 0) remote: Compressing source files... done. remote: Building source: remote: remote: -----> Ruby app detected remote: -----> Compiling Ruby/Rack remote: -----> Using Ruby version: ruby-2.5.3 remote: -----> Installing dependencies using bundler 2.0.1 remote: Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment remote: Fetching gem metadata from https://rubygems.org/.............. remote: Fetching https://github.com/satoryu/sample_private_gem.git remote: fatal: could not read Username for 'https://github.com': No such device or address remote: remote: Retrying `git clone 'https://github.com/satoryu/sample_private_gem.git' "/tmp/build_0902676fab2649d6da106b713a8423d7/vendor/bundle/ruby/2.5.0/cache/bundler/git/sample_private_gem-b3cd9b512dc81bc540e01f090efba0b37ff88c98" --bare --no-hardlinks --quiet` due to error (2/4): Bundler::Source::Git::GitCommandError Git error: command `git clone 'https://github.com/satoryu/sample_private_gem.git' "/tmp/build_0902676fab2649d6da106b713a8423d7/vendor/bundle/ruby/2.5.0/cache/bundler/git/sample_private_gem-b3cd9b512dc81bc540e01f090efba0b37ff88c98" --bare --no-hardlinks --quiet` in directory /tmp/build_0902676fab2649d6da106b713a8423d7 has failed. remote: fatal: could not read Username for 'https://github.com': No such device or address
プライベートリポジトリのgemを使うための設定
bundler の設定でプライベートリポジトリにアクセスする際のクレデンシャルを指定することができる。
このように、GitHubのユーザー名とパスワードを登録することでアクセスできる。 ローカルでの開発環境で設定する際は使用しているGitHubユーザーのアカウントとパスワードで良いが、デプロイ先の環境でそれを使うのはセキュリティ上良くないので、GitHubのパーソナルアクセストークンを使う方が良いと思う。
GitHubのパーソナルアクセストークンを発行
今回はプライベートリポジトリにアクセスするため、発行するときのスコープをrepo 全体にする。
下記のコマンド中の*********
は、ここで発行したパーソナルアクセストークンに置き換えて使用する。
ローカル環境での設定
クレデンシャルの設定の方法は、ホスト単位、リポジトリ単位の2通りある。
ホスト単位
今後も同様なgemが増えるのであれば、予めGitリポジトリのホスト(今回はGitHub)に対して設定しておくと良さそう。
bundle config github.com *********:x-oauth-basic
リポジトリ単位
bundle config https://github.com/satoryu/sample_private_gem.git *********:x-oauth-basic
デプロイ先の実行環境
bundle
コマンドが実行できるのであれば、ローカル環境と同じように設定すると良い。
しかし、HerokuなどPaaSでは、ホスト上でのシェルが実行できないため、代わりに環境変数を用いて同様の設定をする。
例えば、Herokuの場合、heroku
コマンドを使って、アプリの環境変数を指定できる。
$ heroku config:set BUNDLE_GITHUB__COM=*************************:x-oauth-basic Setting BUNDLE_GITHUB__COM and restarting ⬢ sample-private-app... done, v5 BUNDLE_GITHUB__COM: *************************:x-oauth-basic
おまけ
HerokuみたいにGitリポジトリへのプッシュをトリガーにしてデプロイする環境だと、再度デプロイするために無理やり何か変更する必要があると思ってたけど、gitは空のコミットを作ることができるので、それを使うといいらしい。
git commit --allow-empty -m 'Redeploy'