Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local Gem Path For Development And Remote Git Repo For Production

I have a gem I'm working on locally which is used by a project.

If I specify the gem's location using path in the , I can make a change and the project picks up the fresh code:

gem 'example', :path => "~/path/to/gems/example"

However, when I push to Heroku, bundling fails because Heroku can't access the gem source on my local machine.

So I can push the gem source to a remote repo and point the gem source there:

gem 'example', :github => 'example/example', :branch => 'example_feature'

However I now need to push changes to this repo, then update the gem to get the fresh changes in my project:

$ cd ~/path/to/gems/example
$ git c -a -m "Update gem"
$ git push origin example_feature
$ cd ~/path/to/projects/project
$ gem update example

I can make this slightly less painful by setting a local override to my local repo:

$ bundle config local.example ~/path/to/gems/example

But I still need to add changed files to git, commit, then $ gem update example every time I change the gem source if I want fresh changes in my project.

Is there any way to have my project pick up local changes automatically (as it does when I use path), but still use the remote repo in production?

like image 733
Undistraction Avatar asked Nov 12 '13 22:11

Undistraction


3 Answers

As mentioned by @bbozo, when you use a git repository in your gemfile you can use bundle local overrides for development which will store revision hashes in your Gemfile.lock. On production these exact revision hashes will be checked out when it runs bundle install.

Gemfile: gem 'example', git: 'https://github.com/your_name/example.git', branch: :master

Bundle config shell command: bundle config local.example /path/to/local/git/repository

Gemfile.lock (auto generated): GIT remote: https://github.com/your_name/example.git revision: b9270e61abb89e1ff77fb8cfacb463e4d04388ad branch: master

Note that after you commit in the "example" git repository you will need to run bundle install on your main application so that it rebuilds the Gemfile.lock to include the new revision hash. I recommend using the gem below as it automates this process for you and also aids in other scenarios. See the gem page for exact detail:

https://github.com/EPI-USE-Labs/git-bundle

like image 66
Pierre Pretorius Avatar answered Oct 24 '22 15:10

Pierre Pretorius


Bundler before v1.2

Via Gemfile,

group :development, :test do
  gem 'example', :path => "~/path/to/gems/example"
end

group :production do
  gem 'example', :github => 'example/example', :branch => 'example_feature'
end

...or, use relative path to the gem and make sure Heroku see the gem in same location,

gem 'example', :path => "../../gems/example"

...or, try playing with --deployment flag in bundler http://bundler.io/v1.3/deploying.html, it should bundle your gem sources with the app which you can then commit to your app's git so in theory Heroku should then use the local copy and not use git to fetch the gem sources (I'm saying in theory because Heroku has its own quirks)

Bundler v1.2 and beyond

http://bundler.io/v1.2/man/bundle-config.1.html#LOCAL-GIT-REPOS says

Bundler also allows you to work against a git repository locally instead of using the remote version. This can be achieved by setting up a local override:

bundle config local.GEM_NAME /path/to/local/git/repository

For example, in order to use a local Rack repository, a developer could call:

bundle config local.rack ~/Work/git/rack

Now instead of checking out the remote git repository, the local override will be used. Similar to a path source, every time the local git repository change, changes will be automatically picked up by Bundler. This means a commit in the local git repo will update the revision in the Gemfile.lock to the local git repo revision. This requires the same attention as git submodules. Before pushing to the remote, you need to ensure the local override was pushed, otherwise you may point to a commit that only exists in your local machine.

Bundler does many checks to ensure a developer won't work with invalid references. Particularly, we force a developer to specify a branch in the Gemfile in order to use this feature. If the branch specified in the Gemfile and the current branch in the local git repository do not match, Bundler will abort. This ensures that a developer is always working against the correct branches, and prevents accidental locking to a different branch. Finally, Bundler also ensures that the current revision in the Gemfile.lock exists in the local git repository. By doing this, Bundler forces you to fetch the latest changes in the remotes.

like image 23
bbozo Avatar answered Oct 24 '22 16:10

bbozo


Best solution which I found on the internet https://rossta.net/blog/how-to-specify-local-ruby-gems-in-your-gemfile.html

bundle config local.tacokit /path/to/tacokit

And in the Gemfile use gem "tacokit", github: "rossta/tacokit", branch: "master"

This stuff is working and tested solution

like image 21
Evgeniy B Avatar answered Oct 24 '22 16:10

Evgeniy B