How to ensure private gems are up to date? - ruby-on-rails

We have a number of private (common) gems which we include in all of our ruby projects. We include them from GitHub, and use release tags to specify a version.
gem 'aswesome_gem', :git => 'git#github.com:evantahler/aswesome_gem.git', :tag => 'v2.0.28'
However, we have been rapidly iterating on our gems, and it is becoming a pain to keep all of our projects up to date. I would prefer not to host our own gem server (Gem in a Box, etc). The reason we use tags and not branches (:branch => 'production') is that bundler will not update the branch if it exists.
Is there an extension to bundler that would let me specify that every time bundle install is run, bundler would forcibly update the local cached copy to the branch in question (even though it might already be checked out)? I think that I essentially want to git pull on every git-based gem (which happens to be specified by a :branch) Bundler's default behavior assumes a gem is up to date if the branch exists (regardless of parity with origin).
Help?

I think you need to do bundle update to get the latest versions of your gems.

Related

Developing Multiple Rails Plugins with Dependencies

I'm starting to build a series of plugins and engines in a project I'm developing and I've run into the issue of having to list the paths to dependencies in all of the Gemfiles for the main application and the plugins/engines if I want rake to work.
Rake works fine for the main application because it's Gemfile lists the relative paths to the plugins/engines I want, but when a plugin/engine is dependent on another and does not have the relative paths all listed, using rake rdoc I'll get an error like the following (presumably I'll get the same error trying to run tests/the dummy application/etc):
Bundler could not find compatible versions for gem "user":
In Gemfile:
auth (>= 0) ruby depends on
user (>= 0) ruby
Could not find gem 'user (>= 0) ruby', which is required by gem 'auth (>= 0) ruby', in any of the sources.
Rather than having to use paths, I've tried specifying the git repository in the plugins/engines like so:
# User engine
gem 'user', git: 'https://localhost/git/project/user.git', branch: 'master'
And then using bundler config local.user /path/to/local/repo command to make it point to a local repository for development. This appeared to work perfectly... until I change the version of the plugin in the local repo, then it spits out this error in any dependent plugin/engine/application:
Could not find user-0.0.1 in any of the sources
Run `bundle install` to install missing gems.
Whilst that isn't really much of an issue-- the version number will be changed at the end anyway --it also turns out that it will throw the following error if you're on a branch in the local repo instead of master:
Local override for user at /path/to/local/repo is using branch deleteme but Gemfile specifies master
And omitting the branch option from the Gemfile leaves me with this error:
Cannot use local override for user at /path/to/local/repo because :branch is not specified in Gemfile. Specify a branch or use `bundle config --delete` to remove the local override
So am I just stuck with having , path: "../local-repo-directory" strewn about all of the Gemfiles for plugins/engines with dependencies on one another whilst in development or is there a way of developing multiple interdependent plugins/engines for Rails at the same time that doesn't use a really sloppy/inelegant solution?
I'm drawing blanks on other ways to do this, so any help would be greatly appreciated. I hope I've explained this well enough, but if there's anything else I can clarify, let me know.
Thanks!
Stick with specifying git repositories in your Gemfile and using bundle local overrides to work on them.
Possible problems with solutions:
1. Local override for user at /path/to/local/repo is using branch deleteme but Gemfile specifies master
If your Gemfile specifies branch "master" then the local override should have branch "master" checked out. This is because the goal of a local override is so that you can work on a gem in a local folder while running and testing the application. In production it will check out the branch and revision specified in the Gemfile and Gemfile.lock and it should offcourse be exactly what you are running with your local override.
2. Could not find user-0.0.1 in any of the sources
Run `bundle install` to install missing gems.
When you run bundle install it places a version number for each gem in the Gemfile.lock. This file is added to git so that other developers and your production server runs the same versions of the gems as you do. Your Gemfile.lock needs to specify the same version of your gem as what is returned in the local override gemspec file. If you incremented the version number in the local override you need to run "bundle update gemname" in the application that uses it so that it updates the Gemfile.lock. Note that bundler caches everything in a gemspec file until you increment the version. Thus you can't add new dependencies or change dependency versions in a gemspec if you don't increase the version number in that gemspec.
The git-bundle gem
If you use a git repository in your Gemfile with local overrides bundler will store git revision hashes in your Gemfile.lock as mentioned above. Example:
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
After you commit in the local override 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 and commit it. 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
The activesupport-decorators gem
As a sidenote, when you need to extend classes between your gems you can use the decorator pattern which is implemented elegantly by the activesupport-decorators gem:
https://github.com/EPI-USE-Labs/activesupport-decorators

Local override for {gem} at /path/to/local/git/repo is using branch develop but Gemfile specifies develop

I'm running bundler v1.3.0.pre.2 and trying to get bundler to bundle a local git repository holding a gem, into a rails app.
Gemfile :
gem 'mygem', :github => 'myrepo/mygem', :branch => 'develop'
Config :
bundle config local.mygem /path/to/local/git/repo
Bundle install throws the error :
Local override for mygem at /path/to/local/git/repo is using branch
develop but Gemfile specifies develop
Is this a bug ? I see that the branch names are exactly the same. What could be wrong ? Got the same error for Bundler v1.2.3 as well
You can use a local gem and even the branch you are working on like this
gem 'rspec-rails', path: '~/forks/rspec-rails', branch: 'feature-branch'
Just change github to path, Then
bundle install
Also as far as bundler config goes, although it is in the docs, I have never needed to change the local config like you did above.
With this method I have never needed to remove Gemfile.lock, it just picks up the changes to your local repo.
Although I don't recommend it, you could disable the branch checking feature used by bundler to make sure you are using the correct branch when developing
bundle config disable_local_branch_check true
If you just need to point to a branch within a local repository you're using like a gem, in gemfile:
gem 'gem-name', :path=> 'relative/path/to/directory'
Then create bundler configuration for that "gem" before bundle-ing
(Keep in mind the repository name may be different than the gem's name, although this is not the norm).
bundle config local.repository-name relative/path/to/directory
Magically, whatever branch is currently checked out locally will be active when you start a local server. You'll likely need to restart your server if you need to make changes or change branches (unless you have some type of automatic reloading feature).
One gotcha is when a configuration setting is already established (let's say via the mechanism above), and you need to use/reference a remote git gem - you don't need bundler configuration to use a remote git gem (if you have an active configuration, you'll get the local override error).
Check to make sure you don't have local settings for given gem:
bundle config local.gem-name
If you do, remove configuration for that gem:
bundle config --delete local.gem-name
Then point to remote repo and branch, in gemfile:
gem 'gem-name', :path => 'https://github.com/reponame.git', :branch => 'branch_name'
More information:
Git Gems: http://bundler.io/v1.7/git.html
"bundle config": http://bundler.io/v1.7/man/bundle-config.1.html
This GitHub issue suggests that the workaround may be to remove Gemfile.lock and do bundle install again.
The branch you reference in your Gemfile needs to be the same as you have checked out in the local repository. Note that after you commit in the local 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 and commit it. 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
Full detail of what happens:
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

Local Gem assets not updating

I've forked a gem, and in trying to change it, decided to change the the gemfile from my git repository (which had been updating fine):
gem 'bootstrap-wysihtml5-rails', :git => 'git://github.com/Asherlc/bootstrap-wysihtml5-rails.git'
to the local directory (just the cloned git repository):
gem 'bootstrap-wysihtml5-rails', :path => '/Users/ashercohen/Documents/bootstrap-wysihtml5-rails'
Upon running either bundle update or bundle install, it shows the correct version number (updated since switching gem sources) in the readout. However, none of the files in the /vendor/assetspath seem to be getting updated in my Rails app. Is there some kind of caching thing I need to clear out?
I don't have a /vendor/cache file in my Rails app, and I'm confident that since the gem version is updating correctly in the bundler readout that the path is correct.
Is there some step I'm missing here?
Turns out Chrome was just aggressively caching the JS.

What's the easiest way to maintain a patched set of rails gems, with bundler?

We're transitioning from 'frozen' rails gems to using bundler and would like to maintain the rails gems with patches, merges etc. say from an external git source. What's the easiest way to set this up, adding gemspecs to the patch branches etc.?
I would store them on a place accessible to bundler (like a public repo on github), in your gemfile use the :git=> option like
gem "nokogiri", :git =>
"git://github.com/tenderlove/nokogiri.git"

Getting started with Ruby Gem Development

Recently I started using a gem called blackbook. The gem has a few issues that I would like to fix. I cloned the git repo and installed the gem locally, hoping I could mess with the source code. When I edit the source code nothing happens, so now I am thinking that I must rebuild the gem every time I make a change.
My question is this:
Should I be able to edit the source code of the gem and see results immediately, or should I use the source code as a plugin to my rails app, and then rebuild the gem only when I have made significant progress?
Thank you,
Tony
I use this rake task to make keeping my gem up to date while working on it. It uses a version number stored in a file at the root named 'VERSION'
desc "Build and install homer gem"
task :update do
version = File.open('VERSION') { |f| f.read }.to_s
`gem build homer.gemspec`
`gem install ./homer-#{version}.gem`
end
and in the gem spec:
s.version = File.open('VERSION') { |f| f.read }.to_s
You can mess with the source code of the installed gem to change the behavior of what you have installed. But unless you are playing path games this won't affect the gem itself even if you rebuild.
What I generally do is this:
Set up a development area where I can make changes & test them (e.g. run unit tests, spec, etc.)
Do most of my work there
When I've got something I like, rebuild the gem and try a test install
If that works to my satisfaction, push it.
Also, if you are using git hub they should automatically rebuild the gem for you every time you push a commit with an updated gemspec (e.g., you've changed the version number).

Resources