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?
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
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)
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With