Forking or cloning a private gem - ruby-on-rails

I have a gem in my Gemfile which reads from a custom source, and requires authentication -- as below:
source "https://gems.xxxxx.com/gems" do
gem "xyz", "~> 1.2.4"
end
I want to remove the dependancy on this provider and on the "remote" gem, incase something happens to the remote source.
Is there a way for me to fork/clone a private gem (I have authentication details), and host it myself?

Bundler allows you to configure credentials for any gem source, which allows you to avoid putting secrets into your Gemfile.
$ bundle config xxxxx.com username:password
See the documentation for the bundle config command. You can also use an ENV var:
export BUNDLE_GEMS__XXXXX__COM="username:password"
This is per domain (not sure how it works with subdomains). If you need to set credentials for a specific repo use:
bundle config https://gems.xxxxx.com/gems/awesome_gem.git username:password
Is there a way for me to fork/clone a private gem (I have authentication details), and host it myself?
Yes. Provided you can access a git repo then you should be able to clone it (practically - not legally). Forking is actually a workflow and not a specific command so the the details may vary depending on the host. Github allows you to fork private repo's which enables the fork & pull model - your fork might not actually be private by default and you may need to pay to be able to make it private. With bundler you can provide gems from either your local machine or any http(s) address.

I found the way this is possible, without necessarily cloning it:
Look in your Gemfile for the gem name.
Run: gem unpack --target vendor/gems
Take a look in the vendor/gems directory and see what the vendored gem directory name is for the next step.
Update the Gemfile to point the gem reference to the newly vendored gem path.
gem '', 'VERSION_NUMBER_GOES_HERE', path:
"vendor/gems/"
Run: bundle update
This will remove the reliance on the remote vendor and store it locally, although it will not receive version updates.

Related

Rails: Extract and Edit Source Code of Specific Gem

How to extract source code of specific gem so that it is possible to edit it locally? Shall I add it to my Rails application folder?
I need that to be able to make changes to the gem's code.
If you find an error in gem, you'd better make pull request on GitHub. But let's suppose you need your private fork of gem. Best workflow for that:
Download the gem source code from GitHub: git clone https://github.com/author/awesome_gem.git.
In your project's Gemfile add gem awesome_gem, path: "/local/path/to/awesome_gem"
Run bundle install
Now you can make changes to the gem locally, and have your project use local copy of it. When you are done making initial changes, push your Gem to your github repository, and change Gemfile line to something like:
gem awesome_gem, github: 'QQQ/awesome_gem' ('QQQ' being your Github's account name)

using devise WITHOUT the gem, can I simply copy the files?

Could I simply copy the devise app and lib (and gem?) folders into my respective project folders and have them work just as if I was using the gem? I'd like to do this so that I can really see all the code, possibly do some customization, and also avoid some "cannot find" errors in my IDE.
Is this a bad idea? If this is something that would work would I simply need to remove the gem and copy over the necessary files or would I need to "undo" things that the gem has done. Could this create problems down the road with updates?
Lastly, how exactly is devise working when I do not have all of the code in my project? It works when I'm offline so is the code just stored in some secret invisible file or something? Do some gems require an internet connection to retrieve their functionality or could any gem simply be copied and used in a project without declaring it in the gem file.
See http://bundler.io/v1.5/git.html
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
Also
http://ryanbigg.com/2013/08/bundler-local-paths/
"There's a little known feature of Bundler that allows you to use a local Git repository while developing locally, and a remote Git repo when deploying. This feature means that you no longer have to constantly switch between local paths:"
gem 'spree', :path => "~/Projects/gems/spree"
And remote paths:
gem 'spree', :github => 'spree/spree', :branch => 'master'
Whether this is possible, short answer: Yes. Is this a bad idea? Definitely! In fact, the code is not in your project, but when you install a gem, all its contents will be stored somewhere in your local machine. Therefore, once downloaded, you don't have to be online to use it. Well, though it's not common (and not recommended), you can clone the gem's repository to your project and set the path in the project's Gemfile.

Where are the gem files located?

Where are the gem files located ?
I'm new to rails and trying o understand how the whole gem functionality works.
My question is how can i follow a gem installation in order to confirm a gem is been installed ?
Where are the installed files located ?
From within your rails app, you can list out all of the gems being used, their versions, and the local path:
bundle show --paths
There's no reason to modify any of these files though. Configuration is typically done through an initializer in /app/initializers, but it depends on the gem being used.
If you need to modify something about the gem, you should fork it on Github and then reference the git location in your Gemfile until your pull request makes it back into the gem:
gem 'some_gem', '4.1.1', git: 'https://github.com/some_github_repo/some_gem.git'

bitbucket private repository on heroku

I have a rails app which requires a gem. I host this gem on bitbucket in a private repository.
In my Gemfile I added the gem like following:
gem "my-gem", :git => "git#bitbucket.org:my-username/my-gem.git", :branch => 'master'
I want to deploy my rails app on heroku with
git push heroku master
Now I always get following error
Fetching git#bitbucket.org:my-username/my-git-repo.git
Host key verification failed.
fatal: The remote end hung up unexpectedly
I understand the error, because the repository is set to private. But how can I solve this problem?
I already read this question: Deploying to Heroku using git on bitbucket, but I donĀ“t really get the answer :)..
Bitbucket allows for HTTP basic auth on repository URLs similar to github. Specify the URL for the gem as https://username:password#bitbucket.org/username/gemrepo.git.
It does mean having your username and password in your Gemfile, which itself is version controlled, and that's not a good practice, but on the other hand that's what Heroku recommends, so...
The proper way to achieve this is using bundle config, which saves the configuration on your home directory .bundle/config so it stays outside the repo.
bundle config bitbucket.org user:pwd
And then on Heroku you have to set a simple configuration in a special way:
heroku config:set BUNDLE_BITBUCKET__ORG=user:pwd
And in your Gemfile you just use the URL without the credentials.
gem 'gemname', git: "https://bitbucket.org/User/gemname.git"
I had the same problem, but I ended up doing the following as a workaround to providing the Bitbucket password in the Gemfile.
The basic idea is to clone the gem from Bitbucket into a local directory, add it to your app and package it into vendor/cache so Heroku can use it. My exact steps are below:
Clone your gem to a local directory:
git clone git#bitbucket.org:me/my_private_gem.git /home/me/my_private_gem
Add the gem to your Gemfile as a 'fake' Bitbucket repo:
gem 'my_private_gem', :git => 'git#bitbucket.org:me/my_private_gem.git', :branch => 'master' # this repo will not be used
Configure Bundler to work against the local repository (where you cloned the gem in step 1):
bundle config local.my_private_gem /home/me/my_private_gem
Run bundle install as usual, you should see something like this:
Using my_private_gem (0.0.1) from git#bitbucket.org:me/my_private_gem.git (at /home/me/my_private_gem)
Package all your gems into /vendor
bundle package --all
Add /vendor to your repo
git add vendor && git commit -m 'add my_private_gem to /vendor/cache'
Push to Heroku (don't forget to commit your updated Gemfile and Gemfile.lock first), you should see something like the following:
Using my_private_gem (0.0.1) from git://github.com/my_private_gem/my_private_gem.git (at /tmp/build_19fmj3tup0zy2/vendor/cache/my_private_gem-8bc6f436e2c8)
References:
Bundler - Local Git Repos
Bundler - package
I would suggest to use ENV vars instead of a new user like:
https://#{ENV['BITBUCKET_USER']}:#{ENV['BITBUCKET_PWD']}....
Then set them using:
heroku config:add BITBUCKET_X=value
For your development environment you can use the dotenv gem to define the credentials.
See also: How can I specify a gem to pull from a private github repository?

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

Resources