Search code examples
rubyrubygemschef-infrarakebundle

Gemfile.lock should sort via dependency priority rather than alphabetical order


Since we don't have access to rubygems website, we are planning to solve the gems and its dependency locally via Chef cookbook. We would like to add a rakefile to this process. The process we followed in Rakefile is as follows

  1. Create Gemfile with proper version (inspec)
  2. bundle install
  3. Got Gemfile.lock <== Here is the problem. It sorts in alphabetical order
  4. We need to create an array with dependency in order so that it doesn't conflict to install gems in a loop. This array is needed for automating the process to future releases.

The array created follows the alphabetical order which results out an error during installation.

The Gemfile we have is

source 'https://rubygems.org'

gem "inspec", "0.22.1"

When we run "bundle install" a Gemfile.lock is created as follows:

GEM
  remote: https://rubygems.org/
  specs:
    builder (3.2.2)
    coderay (1.1.1)
    diff-lcs (1.2.5)
    docker-api (1.26.2)
      excon (>= 0.38.0)
      json
    erubis (2.7.0)
    excon (0.49.0)
    ffi (1.9.10-x86-mingw32)
    gssapi (1.2.0)
      ffi (>= 1.0.1)
    gyoku (1.3.1)
      builder (>= 2.1.2)
    hashie (3.4.4)
    httpclient (2.8.0)
    inspec (0.22.1)
      hashie (~> 3.4)
      json (~> 1.8)
      method_source (~> 0.8)
      pry (~> 0)
      r-train (~> 0.12)
      rainbow (~> 2)
      rspec (~> 3)
      rspec-its (~> 1.2)
      rubyzip (~> 1.1)
      thor (~> 0.19)
    json (1.8.3)
    little-plugger (1.1.4)
    logging (2.1.0)
      little-plugger (~> 1.1)
      multi_json (~> 1.10)
    method_source (0.8.2)
    mixlib-shellout (2.2.6-universal-mingw32)
      win32-process (~> 0.8.2)
      wmi-lite (~> 1.0)
    multi_json (1.12.0)
    net-scp (1.2.1)
      net-ssh (>= 2.6.5)
    net-ssh (3.1.1)
    nori (2.6.0)
    pry (0.10.3)
      coderay (~> 1.1.0)
      method_source (~> 0.8.1)
      slop (~> 3.4)
    r-train (0.12.0)
      docker-api (~> 1.26.2)
      json (~> 1.8)
      mixlib-shellout (~> 2.0)
      net-scp (~> 1.2)
      net-ssh (>= 2.9, < 4.0)
      winrm (~> 1.6)
      winrm-fs (~> 0.3)
    rainbow (2.1.0)
    rspec (3.4.0)
      rspec-core (~> 3.4.0)
      rspec-expectations (~> 3.4.0)
      rspec-mocks (~> 3.4.0)
    rspec-core (3.4.4)
      rspec-support (~> 3.4.0)
    rspec-expectations (3.4.0)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.4.0)
    rspec-its (1.2.0)
      rspec-core (>= 3.0.0)
      rspec-expectations (>= 3.0.0)
    rspec-mocks (3.4.1)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.4.0)
    rspec-support (3.4.1)
    rubyntlm (0.6.0)
    rubyzip (1.2.0)
    slop (3.6.0)
    thor (0.19.1)
    win32-process (0.8.3)
      ffi (>= 1.0.0)
    winrm (1.8.1)
      builder (>= 2.1.2)
      gssapi (~> 1.2)
      gyoku (~> 1.0)
      httpclient (~> 2.2, >= 2.2.0.2)
      logging (>= 1.6.1, < 3.0)
      nori (~> 2.0)
      rubyntlm (~> 0.6.0)
    winrm-fs (0.4.2)
      erubis (~> 2.7)
      logging (>= 1.6.1, < 3.0)
      rubyzip (~> 1.1)
      winrm (~> 1.5)
    wmi-lite (1.0.0)

PLATFORMS
  x86-mingw32

DEPENDENCIES
  inspec (= 0.22.1)

BUNDLED WITH
   1.11.2

Rakefile:

require 'bundler'
require 'json/pure'

  parsed_Gemfile_lock = Bundler::LockfileParser.new( File.read(File.dirname(__FILE__) + "\\Gemfile.lock"))

  # Print a Ruby Array
  parsed_Gemfile_lock.specs.each do |spec|
    gem_array = spec.to_s.split
    gem_name = gem_array[0]
    gem_version = gem_array[1]
    gem_version = gem_version.gsub(/[()]/,"'")
    print "'" + gem_name + "'=>" + gem_version + ", "
  end

Result:

'builder'=>'3.2.2', 'coderay'=>'1.1.1', 'diff-lcs'=>'1.2.5', 'docker-api'=>'1.26.2', 'erubis'=>'2.7.0', 'excon'=>'0.49.0', 'ffi'=>'1.9.10', 'gssapi'=>'1.2.0', 'gyoku'=>'1.3.1', 'hashie'=>'3.4.4', 'httpclient'=>'2.8.0', 'inspec'=>'0.22.1', 'json'=>'1.8.3', 'little-plugger'=>'1.1.4', 'logging'=>'2.1.0', 'method_source'=>'0.8.2', 'mixlib-shellout'=>'2.2.6', 'multi_json'=>'1.12.0', 'net-scp'=>'1.2.1', 'net-ssh'=>'3.1.1', 'nori'=>'2.6.0', 'pry'=>'0.10.3', 'r-train'=>'0.12.0', 'rainbow'=>'2.1.0', 'rspec'=>'3.4.0', 'rspec-core'=>'3.4.4', 'rspec-expectations'=>'3.4.0', 'rspec-its'=>'1.2.0', 'rspec-mocks'=>'3.4.1', 'rspec-support'=>'3.4.1', 'rubyntlm'=>'0.6.0', 'rubyzip'=>'1.2.0', 'slop'=>'3.6.0', 'thor'=>'0.19.1', 'win32-process'=>'0.8.3', 'winrm'=>'1.8.1', 'winrm-fs'=>'0.4.2', 'wmi-lite'=>'1.0.0',

Error while executing via chef cookbook:

===============================================================================
Error executing action `upgrade` on resource 'chef_gem[inspec]'
================================================================================

Mixlib::ShellOut::ShellCommandFailed
------------------------------------
Expected process to exit with [0], but received '2'
---- Begin output of /opt/chef/embedded/bin/gem install /var/chef/cache/rubygems/inspec-0.22.1.gem -q --no-rdoc --no-ri -v "0.22.1" --local ----
STDOUT:
STDERR: ERROR:  Could not find a valid gem 'r-train' (~> 0.12) in any repository
---- End output of /opt/chef/embedded/bin/gem install /var/chef/cache/rubygems/inspec-0.22.1.gem -q --no-rdoc --no-ri -v "0.22.1" --local ----
Ran /opt/chef/embedded/bin/gem install /var/chef/cache/rubygems/inspec-0.22.1.gem -q --no-rdoc --no-ri -v "0.22.1" --local returned 2

Let me know if there are any alternate/easy solution to this issue or guide me out in creating the proper Rakefile to this process.


Solution

  • I have found an alternate solution.

    namespace :gem_attribute_array do
    desc 'Generate gems attribute array'
    task :generate do
    puts "Generating gems attribute array and downloading all the dependent gem packages to ./vendor/cache :"
    result = Mixlib::ShellOut.new('bundle package')
    result.run_command
    result.stdout.split("\n").each do |line|
      if line =~ /Using / or line =~ /Installing / then
        str=line.split(" ")
        gem_name=str[1]
        gem_version=str[2]
        print "'" + gem_name + "'=>'" + gem_version + "', "
      end #if loop
    end # foreach loop
    puts "\n" #Dummy line
    end  #task
    end  #namespace