Module: Ra10ke::Solve

Included in:
RakeTask
Defined in:
lib/ra10ke/solve.rb

Instance Method Summary collapse

Instance Method Details

#define_task_solve_dependencies(*_args) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ra10ke/solve.rb', line 15

def define_task_solve_dependencies(*_args)
  desc 'Find missing or outdated module dependencies'
  task :solve_dependencies, [:allow_major_bump] do |_t, args|
    require 'r10k/puppetfile'
    require 'r10k/module/git'
    require 'r10k/module/metadata_file'
    require 'puppet_forge'

    allow_major_bump = false
    allow_major_bump = true if args[:allow_major_bump]

    # Same as in the dependencies task, but oh well.
    PuppetForge.user_agent = "ra10ke/#{Ra10ke::VERSION}"
    puppetfile = get_puppetfile
    puppetfile.load!
    PuppetForge.host = puppetfile.forge if puppetfile.forge =~ /^http/

    # ignore file allows for "don't tell me about this"
    ignore_modules = []
    if File.exist?('.r10kignore')
      ignore_modules = File.readlines('.r10kignore').each(&:chomp!)
    end
    # Actual new logic begins here:
    cache = (ENV['XDG_CACHE_DIR'] || File.expand_path('~/.cache'))

    FileUtils.mkdir_p(cache)
    
    # Metadata cache, since the Forge is slow:
    @metadata_cache = YAML::Store.new File.join(cache, 'ra10ke.metadata_cache')
    # The graph of available module versions
    @graph = Solve::Graph.new
    # Set of modules that we have already added to the graph
    @processed_modules = Set.new
    # The set of "demands" we make of the solver. Will be a list of module names
    # Could also demand certain version constraints to hold, but the code does not do it
    # Can be either "module-name" or ["module-name", "version-constraint"]
    @demands = Set.new
    # List of modules we have in the Puppetfile, as [name, version] pairs
    @current_modules = []

    puppetfile.modules.each do |puppet_module|
      next if ignore_modules.include? puppet_module.title
      if puppet_module.class == R10K::Module::Forge
        module_name = puppet_module.title.tr('/', '-')
        installed_version = puppet_module.expected_version
        puts "Processing Forge module #{module_name}-#{installed_version}"
        @current_modules << [module_name, installed_version]
        @graph.artifact(module_name, installed_version)
        constraint = '>=0.0.0'
        unless allow_major_bump
          ver = Semverse::Version.new installed_version
          if ver.major.zero?
            constraint = "~>#{installed_version}"
          else
            nver = Semverse::Version.new([ver.major + 1, 0, 0])
            constraint = "<#{nver}"
          end
        end
        puts "...Adding a demand: #{module_name} #{constraint}"

        @demands.add([module_name, constraint])
        puts '...Fetching latest release version information'
        forge_rel = PuppetForge::Module.find(module_name).current_release
        mod = @graph.artifact(module_name, forge_rel.version)
        puts '...Adding its requirements to the graph'
        meta = (module_name, forge_rel)
        add_reqs_to_graph(mod, meta)
      end

      next unless puppet_module.class == R10K::Module::Git
      # This downloads the git module to modules/modulename
      meta = (puppet_module)
      version = get_key_or_sym(meta, :version)
      module_name = puppet_module.title.tr('/', '-')
      @current_modules << [module_name, version]
      # We should add git modules with exact versions, or the system might recommend updating to a
      # Forge version.
      puts "Adding git module #{module_name} to the list of required modules with exact version: #{version}"
      @demands.add([module_name, version])
      mod = @graph.artifact(module_name, version)
      puts "...Adding requirements for git module #{module_name}-#{version}"
      add_reqs_to_graph(mod, meta)
    end
    puts
    puts 'Resolving dependencies...'
    if allow_major_bump
      puts 'WARNING:  Potentially breaking updates are allowed for this resolution'
    end
    result = Solve.it!(@graph, @demands, sorted: true)
    puts
    print_module_diff(@current_modules, result)
  end
end