Как мне проанализировать Gemfile, чтобы найти внутренние драгоценные камни не внутри исходного блока?

#ruby #bundler #gemfile

#ruby #bundler #gemfile

Вопрос:

В целях безопасности на внутренние драгоценные камни Ruby в the Gemfile всегда следует ссылаться внутри source блока, чтобы он никогда не пытался извлечь их из rubygems.org . Я хотел бы автоматизировать поиск там, где люди не могут этого сделать, поэтому хотел бы проанализировать Gemfile , найти любые драгоценные камни, соответствующие нашим внутренним именам, и проверить это rubygems.org этого нет в их списке возможных источников.

 source 'https://rubygems.org'

gem 'rails'

gem 'my-private-gem1' # this should be in the source block below

source PRIVATE_GEM_REPO do
  gem 'my-private-gem2'
end
 

Я видел, что вы можете анализировать Gemfile

 Bundler::Definition.build('Gemfile', '', {})
 

Но не могу найти ничего в возвращаемой структуре данных, которая показывает мне доступные / разрешенные источники для каждого драгоценного камня

Если я включу Gemfile.lock , я увижу больше информации об источнике, но это кажется неправильным, потому что в каждом gem перечислены все мои источники, независимо от того, находятся ли они в исходном блоке

 Bundler::Definition.build('Gemfile', 'Gemfile.lock', {}).
  locked_gems.
  specs.
  map {|g| [g.full_name, g.source.remotes.map(amp;:hostname).join(', ')]}
=> ["rails-6.0.3.4", "my.private.gemserver, rubygems.org"],
   ["my-private-gem1-1.0.0", "my.private.gemserver, rubygems.org"],
   ["my-private-gem2-1.0.0", "my.private.gemserver, rubygems.org"]]
 

Есть мысли о том, как проанализировать Gemfile , чтобы найти то, что my-private-gem1 находится за пределами исходного блока?

Ответ №1:

Наконец-то разобрался, просто потребовалось некоторое время, чтобы разобраться в методах Bundler — и помощи коллеги.

 Bundler::Definition.
  build('Gemfile', '', nil).
  dependencies.
  map {|dep| [dep.name, dep.sourceamp;.remotesamp;.map(amp;:hostname)amp;.join(', ')]}
=>
[["rails", nil],
 ["my-private-gem1", nil],
 ["my-private-gem2", "my.private.gemserver"]]
 

Теперь я могу легко искать в этой результирующей структуре данных любые частные драгоценные камни, которые не привязаны к моему частному серверу драгоценных камней.

Ответ №2:

Предисловие

Пока я писал этот ответ, OP нашел ответ, специфичный для пакета. Тем не менее, я предлагаю более обобщенное решение ниже. Это решение также предлагает отзывы пользователей, которые могут упростить исправление файла.

Поиск драгоценных камней-кандидатов по выравниванию столбцов с белым списком

Если вы можете с уверенностью предположить, что ваш Gemfile всегда имеет правильный отступ, решением KISS может быть простое определение драгоценных камней, которые не имеют отступов в определении группы. Например:

 # example Gemfile to test against
GEMFILE = <<~'EOF'
  source 'https://rubygems.org'
  gem 'rails'
  gem 'my-private-gem1' # this should be in the source block below
  source PRIVATE_GEM_REPO do
    gem 'my-private-gem2'
  end
EOF

# gems that are acceptable in a non-group context
whitelist = Regexp.new %w[rails sass-rails webpacker].join(?|)

UngroupedGem   = Struct.new :line_no, :line_txt, :gem_name
ungrouped_gems = []

GEMFILE.lines.each_with_index do |line_txt, line_no|
  next if line_txt =~ whitelist or line_txt !~ /^s*gem/
  gem_name = line_txt.match(/(?<=(['"]))(.*?)(?=1)/)[0]
  ungrouped_gems.append(
    UngroupedGem.new line_no.succ, line_txt, gem_name
  ).compact!
end

# tell the user what actions to take
if ungrouped_gems.any?
  puts "Line No.tGem Name"
  ungrouped_gems.each { printf "%dtt%sn", _1.line_no, _1.gem_name }
else
  puts "No gems need to be moved."
end
 

В этом примере он будет печатать:

 Line No.  Gem Name
3         my-private-gem1
5         my-private-gem2
 

это даст вам четкое представление о том, какие строки в Gemfile необходимо переместить, и какие конкретные драгоценные камни задействованы.