Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component method in main Gemfile generates error when running 'bundle install' #3

Open
maiksimov opened this issue Feb 19, 2021 · 11 comments

Comments

@maiksimov
Copy link

maiksimov commented Feb 19, 2021

I am trying to attempt your code into my project. I added component and eval_gemfile_patch scripts the lib folder of my main application. I have an admin_panel engine that is included in the main Gemfile as written in the guide:

component 'admin_panel'

Engine Gemfile looks like:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gemspec
eval_gemfile './Gemfile.runtime'

Engine admin_panel.gemspec looks like:

$LOAD_PATH.push File.expand_path('lib', __dir__)
require 'admin_panel/version'

Gem::Specification.new do |spec|
  spec.name        = 'admin_panel'
  spec.version     = AdminPanel::VERSION
  spec.summary     = 'AdminPanel.'
  spec.description = 'AdminPanel provides functionality to manage project entities'

  spec.add_dependency 'activeadmin'
  spec.add_dependency 'devise'
  spec.add_dependency 'draper'
  spec.add_dependency 'dry-validation', '~> 1.5'
  spec.add_dependency 'omniauth', '~> 1.9.1'
  spec.add_dependency 'omniauth-google-oauth2'
  spec.add_dependency 'omniauth-rails_csrf_protection'
  spec.add_dependency 'rails', '~> 6.0.3', '>= 6.0.3.2'
  spec.add_dependency 'reform', '~> 2.3'
  spec.add_dependency 'sassc-rails'
  spec.add_dependency 'trailblazer', '~> 2.1'

  spec.add_development_dependency 'bundler'
  spec.add_development_dependency 'combustion', '~> 1.3'
  spec.add_development_dependency 'factory_bot'
  spec.add_development_dependency 'ffaker'
  spec.add_development_dependency 'pg'
  spec.add_development_dependency 'pry-byebug'
  spec.add_development_dependency 'rake', '~> 13.0'
  spec.add_development_dependency 'rspec', '~> 3.0'
  spec.add_development_dependency 'rspec-rails'
  spec.add_development_dependency 'strong_migrations'
end

When I run bundle install I had an error:

[!] There was an error parsing `Gemfile`: 
[!] There was an error parsing `Gemfile`: You cannot specify the same gem twice coming from different sources.
You specified that admin_panel (>= 0) should come from source at `engines/admin_panel` and source at `.`
. Bundler cannot continue.

 #  from engines/admin_panel/Gemfile:6
 #  -------------------------------------------
 #  
 >  gemspec
 #  
 #  -------------------------------------------
. Bundler cannot continue.

 #  from /app/Gemfile:171
 #  -------------------------------------------
 #  # Admin panel
 >  component 'admin_panel'
 #  -------------------------------------------

If I remove the gemspec call from the engine Gemfile, everything works fine, but it looks strange because I want to reuse this engine in other applications.
The same will happen if I use your generators and create some kind of test engine or gem. It generates engine with Gemfile with gemspec call inside. And "bundle install" will throw an error again.

@palkan
Copy link
Owner

palkan commented Feb 19, 2021

You specified that admin_panel (>= 0) should come from source at engines/admin_panel and source at .

Interesting; why .?

Which Bundler version do you use?

@maiksimov
Copy link
Author

maiksimov commented Feb 22, 2021

Gemfile.lock:

BUNDLED WITH
   1.17.3

@palkan
Copy link
Owner

palkan commented Feb 23, 2021

That's probably the reason.

I couldn't find a relevant issue nor personal notes, but I had a feeling that we specifically upgraded to Bundler 2 to make eval_gemfile work as we expected.

@maiksimov
Copy link
Author

I updated the version of the bundler to 2. But nothing changed, the errors remained the same

@palkan
Copy link
Owner

palkan commented Feb 26, 2021

Unfortunately, I don't have an access to any engined codebase right now; would you be able to provide a minimal reproduction, so I can debug it?

@luccasmaso
Copy link

Hi. I'm having this same problem. But I actually did not understand where to place class Bundler::Dsl component function to be accessible inside the root Gemfile. I've tried placing inside /lib/scripts/component.rb, /lib/scripts/bunder/component.rb... but only because @maiksimov pointed out.

Thanks in advance

@palkan
Copy link
Owner

palkan commented Mar 2, 2021

where to place class Bundler::Dsl component function to be accessible inside the root Gemfile

You can put the patch anywhere you want, just don't forget to require it at the top of the Gemfile.

We put the patch right in the Gemfile:

# frozen_string_literal: true

unless Bundler::Dsl.instance_methods.include?(:eval_gemfile_original)
  class Bundler::Dsl
    alias eval_gemfile_original eval_gemfile

    def eval_gemfile(gemfile, contents = nil)
      expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile&.parent)
      return if @gemfiles.any? { |path| path == expanded_gemfile_path }

      eval_gemfile_original(gemfile, contents)
    end

    alias eval_gemfile_without_duplication eval_gemfile

    def component(name, namespace: "engines")
      Dir.chdir(__dir__) do
        group name.to_sym do
          group :default do
            # Add engine as a dependency
            gem name, path: "#{namespace}/#{name}"

            # Add runtime non-RubyGems specs
            if File.readable?("#{namespace}/#{name}/Gemfile.runtime")
              eval_gemfile_without_duplication "#{namespace}/#{name}/Gemfile.runtime"
            end
          end

          # Add development deps to development and test groups
          expanded_spec_path = Pathname.new("#{namespace}/#{name}/#{name}.gemspec").expand_path(@gemfile&.parent)

          spec = Gem::Specification.load(expanded_spec_path.to_s)

          spec.dependencies.select { |s| s.type == :development }.each do |dep|
            next if @dependencies.find { |current_dep| current_dep.name == dep.name }

            gem dep.name, dep.requirement, group: [:development, :test]
          end
        end
      end
    end
  end
end

source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby File.read(File.join(__dir__, ".ruby-version")).strip

rails_version = File.read(File.join(__dir__, ".rails-version"))

gem "rails", rails_version

# == Core ==
gem "pg"
gem "puma"
gem "redis"
gem "webpacker"

# ...

group :development, :test do
  # ...
end

group :development do
  # ...
end

group :test do
  # ...
end

# == Engines ==

# NOTE: components must be loaded after everything to ensure we do not
# load already defined deps twice (we do check for that in the #component method).
#
# Loading the same dependency twice makes Bundler crazy in some cases.

# Core engine
component "core"

# Authentication engine
component "auth"

# Admin dashboard engine
component "admin"

@maiksimov btw, check the commend above; do you have component calls in the end of the Gemfile? Looks like there were some "crazy" issues I don't remember 🙂

@palkan
Copy link
Owner

palkan commented Mar 2, 2021

@maiksimov Have you added the #eval_gemfile patch?

@maiksimov
Copy link
Author

maiksimov commented Mar 2, 2021

@palkan Hello! I created a public rails test project, added your scripts and created a test gem inside as it was written in the manual. I have errors like above (when run bundle install). Can you check it out? Maybe I did something wrong.

https://github.com/maiksimov/test-rails-project

@palkan
Copy link
Owner

palkan commented Mar 3, 2021

Thanks for the demo project!

I found the problem: evaling Gemfile within gemspec inside doesn't really work (we actually didn't have this line in our setup, don't know where it came from).

I've updated the guides and docs to fix this: 27a77c5

tl;dr We need Gemfile.dev as well 🙂

Here is the fix for the demo project: https://github.com/palkan/test-rails-project/commit/a3079f4b9b3932946a742544122aafd23c2bad4b

@maiksimov
Copy link
Author

@palkan Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants