ra10ke 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +16 -0
- data/README.md +59 -1
- data/Rakefile +7 -1
- data/lib/ra10ke/dependencies.rb +71 -0
- data/lib/ra10ke/install.rb +32 -0
- data/lib/ra10ke/monkey_patches.rb +28 -0
- data/lib/ra10ke/puppetfile_parser.rb +83 -0
- data/lib/ra10ke/solve.rb +185 -189
- data/lib/ra10ke/syntax.rb +18 -0
- data/lib/ra10ke/validate.rb +126 -0
- data/lib/ra10ke/version.rb +1 -1
- data/lib/ra10ke.rb +29 -122
- data/ra10ke.gemspec +2 -0
- data/spec/fixtures/Puppetfile +43 -0
- data/spec/fixtures/Puppetfile_test +12 -0
- data/spec/fixtures/Puppetfile_with_bad_refs +10 -0
- data/spec/fixtures/reflist.txt +290 -0
- data/spec/ra10ke/puppetfile_parser_spec.rb +103 -0
- data/spec/ra10ke/validate_spec.rb +81 -0
- data/spec/ra10ke_spec.rb +73 -0
- data/spec/spec_helper.rb +3 -0
- metadata +45 -2
data/lib/ra10ke/solve.rb
CHANGED
@@ -11,218 +11,214 @@ require 'semverse/version'
|
|
11
11
|
FETCH_LIMIT = 3
|
12
12
|
|
13
13
|
module Ra10ke::Solve
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
require 'r10k/module/metadata_file'
|
22
|
-
require 'puppet_forge'
|
14
|
+
def define_task_solve_dependencies(*_args)
|
15
|
+
desc 'Find missing or outdated module dependencies'
|
16
|
+
task :solve_dependencies, [:allow_major_bump] do |_t, args|
|
17
|
+
require 'r10k/puppetfile'
|
18
|
+
require 'r10k/module/git'
|
19
|
+
require 'r10k/module/metadata_file'
|
20
|
+
require 'puppet_forge'
|
23
21
|
|
24
|
-
|
25
|
-
|
22
|
+
allow_major_bump = false
|
23
|
+
allow_major_bump = true if args[:allow_major_bump]
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
# Same as in the dependencies task, but oh well.
|
26
|
+
PuppetForge.user_agent = "ra10ke/#{Ra10ke::VERSION}"
|
27
|
+
puppetfile = get_puppetfile
|
28
|
+
puppetfile.load!
|
29
|
+
PuppetForge.host = puppetfile.forge if puppetfile.forge =~ /^http/
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
puppetfile.modules.each do |puppet_module|
|
54
|
-
next if ignore_modules.include? puppet_module.title
|
55
|
-
if puppet_module.class == R10K::Module::Forge
|
56
|
-
module_name = puppet_module.title.tr('/', '-')
|
57
|
-
installed_version = puppet_module.expected_version
|
58
|
-
puts "Processing Forge module #{module_name}-#{installed_version}"
|
59
|
-
@current_modules << [module_name, installed_version]
|
60
|
-
@graph.artifact(module_name, installed_version)
|
61
|
-
constraint = '>=0.0.0'
|
62
|
-
unless allow_major_bump
|
63
|
-
ver = Semverse::Version.new installed_version
|
64
|
-
if ver.major.zero?
|
65
|
-
constraint = "~>#{installed_version}"
|
66
|
-
else
|
67
|
-
nver = Semverse::Version.new([ver.major + 1, 0, 0])
|
68
|
-
constraint = "<#{nver}"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
puts "...Adding a demand: #{module_name} #{constraint}"
|
31
|
+
# ignore file allows for "don't tell me about this"
|
32
|
+
ignore_modules = []
|
33
|
+
if File.exist?('.r10kignore')
|
34
|
+
ignore_modules = File.readlines('.r10kignore').each(&:chomp!)
|
35
|
+
end
|
36
|
+
# Actual new logic begins here:
|
37
|
+
cache = (ENV['XDG_CACHE_DIR'] || File.expand_path('~/.cache'))
|
38
|
+
# Metadata cache, since the Forge is slow:
|
39
|
+
@metadata_cache = YAML::Store.new File.join(cache, 'ra10ke.metadata_cache')
|
40
|
+
# The graph of available module versions
|
41
|
+
@graph = Solve::Graph.new
|
42
|
+
# Set of modules that we have already added to the graph
|
43
|
+
@processed_modules = Set.new
|
44
|
+
# The set of "demands" we make of the solver. Will be a list of module names
|
45
|
+
# Could also demand certain version constraints to hold, but the code does not do it
|
46
|
+
# Can be either "module-name" or ["module-name", "version-constraint"]
|
47
|
+
@demands = Set.new
|
48
|
+
# List of modules we have in the Puppetfile, as [name, version] pairs
|
49
|
+
@current_modules = []
|
72
50
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
51
|
+
puppetfile.modules.each do |puppet_module|
|
52
|
+
next if ignore_modules.include? puppet_module.title
|
53
|
+
if puppet_module.class == R10K::Module::Forge
|
54
|
+
module_name = puppet_module.title.tr('/', '-')
|
55
|
+
installed_version = puppet_module.expected_version
|
56
|
+
puts "Processing Forge module #{module_name}-#{installed_version}"
|
57
|
+
@current_modules << [module_name, installed_version]
|
58
|
+
@graph.artifact(module_name, installed_version)
|
59
|
+
constraint = '>=0.0.0'
|
60
|
+
unless allow_major_bump
|
61
|
+
ver = Semverse::Version.new installed_version
|
62
|
+
if ver.major.zero?
|
63
|
+
constraint = "~>#{installed_version}"
|
64
|
+
else
|
65
|
+
nver = Semverse::Version.new([ver.major + 1, 0, 0])
|
66
|
+
constraint = "<#{nver}"
|
80
67
|
end
|
81
|
-
|
82
|
-
next unless puppet_module.class == R10K::Module::Git
|
83
|
-
# This downloads the git module to modules/modulename
|
84
|
-
meta = fetch_git_metadata(puppet_module)
|
85
|
-
version = get_key_or_sym(meta, :version)
|
86
|
-
module_name = puppet_module.title.tr('/', '-')
|
87
|
-
@current_modules << [module_name, version]
|
88
|
-
# We should add git modules with exact versions, or the system might recommend updating to a
|
89
|
-
# Forge version.
|
90
|
-
puts "Adding git module #{module_name} to the list of required modules with exact version: #{version}"
|
91
|
-
@demands.add([module_name, version])
|
92
|
-
mod = @graph.artifact(module_name, version)
|
93
|
-
puts "...Adding requirements for git module #{module_name}-#{version}"
|
94
|
-
add_reqs_to_graph(mod, meta)
|
95
68
|
end
|
96
|
-
puts
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
puts
|
103
|
-
|
69
|
+
puts "...Adding a demand: #{module_name} #{constraint}"
|
70
|
+
|
71
|
+
@demands.add([module_name, constraint])
|
72
|
+
puts '...Fetching latest release version information'
|
73
|
+
forge_rel = PuppetForge::Module.find(module_name).current_release
|
74
|
+
mod = @graph.artifact(module_name, forge_rel.version)
|
75
|
+
puts '...Adding its requirements to the graph'
|
76
|
+
meta = get_release_metadata(module_name, forge_rel)
|
77
|
+
add_reqs_to_graph(mod, meta)
|
104
78
|
end
|
79
|
+
|
80
|
+
next unless puppet_module.class == R10K::Module::Git
|
81
|
+
# This downloads the git module to modules/modulename
|
82
|
+
meta = fetch_git_metadata(puppet_module)
|
83
|
+
version = get_key_or_sym(meta, :version)
|
84
|
+
module_name = puppet_module.title.tr('/', '-')
|
85
|
+
@current_modules << [module_name, version]
|
86
|
+
# We should add git modules with exact versions, or the system might recommend updating to a
|
87
|
+
# Forge version.
|
88
|
+
puts "Adding git module #{module_name} to the list of required modules with exact version: #{version}"
|
89
|
+
@demands.add([module_name, version])
|
90
|
+
mod = @graph.artifact(module_name, version)
|
91
|
+
puts "...Adding requirements for git module #{module_name}-#{version}"
|
92
|
+
add_reqs_to_graph(mod, meta)
|
93
|
+
end
|
94
|
+
puts
|
95
|
+
puts 'Resolving dependencies...'
|
96
|
+
if allow_major_bump
|
97
|
+
puts 'WARNING: Potentially breaking updates are allowed for this resolution'
|
105
98
|
end
|
99
|
+
result = Solve.it!(@graph, @demands, sorted: true)
|
100
|
+
puts
|
101
|
+
print_module_diff(@current_modules, result)
|
106
102
|
end
|
103
|
+
end
|
107
104
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
105
|
+
private
|
106
|
+
|
107
|
+
def get_release_metadata(name, release)
|
108
|
+
meta = nil
|
109
|
+
@metadata_cache.transaction do
|
110
|
+
meta = @metadata_cache["#{name}-#{release.version}"]
|
111
|
+
unless meta
|
112
|
+
meta = release.metadata
|
113
|
+
@metadata_cache["#{name}-#{release.version}"] = meta
|
116
114
|
end
|
117
|
-
meta
|
118
115
|
end
|
116
|
+
meta
|
117
|
+
end
|
119
118
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
}
|
132
|
-
end
|
133
|
-
metadata = R10K::Module::MetadataFile.new(metadata_path)
|
134
|
-
metadata = metadata.read
|
135
|
-
{
|
136
|
-
version: metadata.version,
|
137
|
-
name: metadata.name,
|
138
|
-
dependencies: metadata.dependencies
|
119
|
+
def fetch_git_metadata(puppet_module)
|
120
|
+
# No caching here. I don't think it's really possible to do in a sane way.
|
121
|
+
puts "Fetching git module #{puppet_module.title}, saving to modules/"
|
122
|
+
puppet_module.sync
|
123
|
+
metadata_path = Pathname.new(puppet_module.full_path) + 'metadata.json'
|
124
|
+
unless metadata_path.exist?
|
125
|
+
puts 'WARNING: metadata.json does not exist, assuming version 0.0.0 and no dependencies'
|
126
|
+
return {
|
127
|
+
version: '0.0.0',
|
128
|
+
name: puppet_module.title,
|
129
|
+
dependencies: []
|
139
130
|
}
|
140
131
|
end
|
132
|
+
metadata = R10K::Module::MetadataFile.new(metadata_path)
|
133
|
+
metadata = metadata.read
|
134
|
+
{
|
135
|
+
version: metadata.version,
|
136
|
+
name: metadata.name,
|
137
|
+
dependencies: metadata.dependencies
|
138
|
+
}
|
139
|
+
end
|
141
140
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
141
|
+
# Is there a better way? :(
|
142
|
+
def get_key_or_sym(hash, k)
|
143
|
+
hash.fetch(k.to_sym, hash.fetch(k.to_s, nil))
|
144
|
+
end
|
146
145
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
146
|
+
# At least puppet-extlib has malformed metadata
|
147
|
+
def get_version_req(dep)
|
148
|
+
req = get_key_or_sym(dep, :version_requirement)
|
149
|
+
req = get_key_or_sym(dep, :version_range) unless req
|
150
|
+
req
|
151
|
+
end
|
153
152
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
end
|
168
|
-
end
|
169
|
-
missing.each do |m|
|
170
|
-
puts format('MISSING: %-25s %s', *m)
|
171
|
-
end
|
172
|
-
outdated.each do |o|
|
173
|
-
puts format('OUTDATED: %-25s %s -> %s', *o)
|
153
|
+
def print_module_diff(current, resolution)
|
154
|
+
current.sort!
|
155
|
+
resolution.sort!
|
156
|
+
outdated = []
|
157
|
+
missing = []
|
158
|
+
resolution.each do |mod|
|
159
|
+
cur_mod, cur_version = current.shift
|
160
|
+
mod, version = mod
|
161
|
+
if (cur_mod == mod) && cur_version && (cur_version != version)
|
162
|
+
outdated << [mod, cur_version, version]
|
163
|
+
elsif cur_mod != mod
|
164
|
+
missing << [mod, version]
|
165
|
+
current.unshift [cur_mod, cur_version]
|
174
166
|
end
|
175
167
|
end
|
168
|
+
missing.each do |m|
|
169
|
+
puts format('MISSING: %-25s %s', *m)
|
170
|
+
end
|
171
|
+
outdated.each do |o|
|
172
|
+
puts format('OUTDATED: %-25s %s -> %s', *o)
|
173
|
+
end
|
174
|
+
end
|
176
175
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
202
|
-
end
|
203
|
-
# Find the dependency in the forge, unless it's already been processed
|
204
|
-
# and add its releases to the global graph
|
205
|
-
next unless @processed_modules.add?(name)
|
206
|
-
puts "Fetching module info for #{name}"
|
207
|
-
mod = begin
|
208
|
-
PuppetForge::Module.find(name)
|
209
|
-
rescue
|
210
|
-
# It's probably a git module
|
211
|
-
nil
|
212
|
-
end
|
213
|
-
next unless mod # Git module, or non-forge dependency. Skip to next for now.
|
214
|
-
# Fetching metadata for all releases takes ages (which is weird, since it's mostly static info)
|
215
|
-
mod.releases.take(FETCH_LIMIT).each do |rel|
|
216
|
-
meta = get_release_metadata(name, rel)
|
217
|
-
rel_artifact = @graph.artifact(name, rel.version)
|
218
|
-
puts "...Recursively adding requirements for dependency #{name} version #{rel.version}"
|
219
|
-
# We don't want to add the requirements to the list of demands for all versions,
|
220
|
-
# but we need them in the graph to be able to solve dependencies
|
221
|
-
add_reqs_to_graph(rel_artifact, meta, :no_demands)
|
176
|
+
def add_reqs_to_graph(artifact, metadata, no_demands = nil)
|
177
|
+
deps = get_key_or_sym(metadata, :dependencies)
|
178
|
+
my_name = get_key_or_sym(metadata, :name)
|
179
|
+
deps.each do |dep|
|
180
|
+
name = get_key_or_sym(dep, :name).tr('/', '-')
|
181
|
+
# Add dependency to the global set of modules we want, so that we can
|
182
|
+
# actually ask the solver for the versioned thing
|
183
|
+
@demands.add(name) unless no_demands
|
184
|
+
ver = get_version_req(dep)
|
185
|
+
unless ver
|
186
|
+
# no version specified, so anything will do
|
187
|
+
ver = '>=0.0.0'
|
188
|
+
end
|
189
|
+
ver.split(/(?=[<])/).each do |bound|
|
190
|
+
bound.strip!
|
191
|
+
v = begin
|
192
|
+
Semverse::Constraint.new(bound)
|
193
|
+
rescue
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
if v
|
197
|
+
artifact.depends(name, v.to_s)
|
198
|
+
else
|
199
|
+
puts "WARNING: Invalid version constraint: #{bound}"
|
222
200
|
end
|
223
201
|
end
|
202
|
+
# Find the dependency in the forge, unless it's already been processed
|
203
|
+
# and add its releases to the global graph
|
204
|
+
next unless @processed_modules.add?(name)
|
205
|
+
puts "Fetching module info for #{name}"
|
206
|
+
mod = begin
|
207
|
+
PuppetForge::Module.find(name)
|
208
|
+
rescue
|
209
|
+
# It's probably a git module
|
210
|
+
nil
|
211
|
+
end
|
212
|
+
next unless mod # Git module, or non-forge dependency. Skip to next for now.
|
213
|
+
# Fetching metadata for all releases takes ages (which is weird, since it's mostly static info)
|
214
|
+
mod.releases.take(FETCH_LIMIT).each do |rel|
|
215
|
+
meta = get_release_metadata(name, rel)
|
216
|
+
rel_artifact = @graph.artifact(name, rel.version)
|
217
|
+
puts "...Recursively adding requirements for dependency #{name} version #{rel.version}"
|
218
|
+
# We don't want to add the requirements to the list of demands for all versions,
|
219
|
+
# but we need them in the graph to be able to solve dependencies
|
220
|
+
add_reqs_to_graph(rel_artifact, meta, :no_demands)
|
221
|
+
end
|
224
222
|
end
|
225
223
|
end
|
226
224
|
end
|
227
|
-
|
228
|
-
Ra10ke::Solve::RakeTask.new
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ra10ke::Syntax
|
2
|
+
def define_task_syntax(*_args)
|
3
|
+
desc "Syntax check Puppetfile"
|
4
|
+
task :syntax do
|
5
|
+
require 'r10k/action/puppetfile/check'
|
6
|
+
|
7
|
+
puppetfile = R10K::Action::Puppetfile::Check.new({
|
8
|
+
:root => @basedir,
|
9
|
+
:moduledir => @moduledir,
|
10
|
+
:puppetfile => @puppetfile_path
|
11
|
+
}, '')
|
12
|
+
|
13
|
+
unless puppetfile.call
|
14
|
+
abort("Puppetfile syntax check failed")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ra10ke/monkey_patches'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'table_print'
|
6
|
+
require 'ra10ke/puppetfile_parser'
|
7
|
+
require 'English'
|
8
|
+
|
9
|
+
module Ra10ke
|
10
|
+
module Validate
|
11
|
+
|
12
|
+
GOOD_EMOJI = ENV['GOOD_EMOJI'] || '👍'
|
13
|
+
BAD_EMOJI = ENV['BAD_EMOJI'] || '😨'
|
14
|
+
|
15
|
+
# Validate the git urls and refs
|
16
|
+
def define_task_validate(*args)
|
17
|
+
desc 'Validate the git urls and branches, refs, or tags'
|
18
|
+
task :validate do
|
19
|
+
gitvalididation = Ra10ke::Validate::Validation.new(get_puppetfile.puppetfile_path)
|
20
|
+
exit_code = 0
|
21
|
+
if gitvalididation.bad_mods?
|
22
|
+
exit_code = 1
|
23
|
+
message = BAD_EMOJI + ' Not all modules in the Puppetfile are valid. '.red + BAD_EMOJI
|
24
|
+
else
|
25
|
+
message = GOOD_EMOJI + ' Puppetfile looks good. '.green + GOOD_EMOJI
|
26
|
+
end
|
27
|
+
tp gitvalididation.sorted_mods, :name, { url: { width: 50 } }, :ref, :status
|
28
|
+
abort(message) if exit_code.positive?
|
29
|
+
puts message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Validation
|
34
|
+
include Ra10ke::PuppetfileParser
|
35
|
+
|
36
|
+
attr_reader :puppetfile
|
37
|
+
|
38
|
+
def initialize(file)
|
39
|
+
file ||= './Puppetfile'
|
40
|
+
@puppetfile = File.expand_path(file)
|
41
|
+
abort("Puppetfile does not exist at #{puppetfile}") unless File.readable?(puppetfile)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Boolean] - return true if the ref is valid
|
45
|
+
# @param url [String] - the git string either https or ssh url
|
46
|
+
# @param ref [String] - the ref object, branch name, tag name, or commit sha, defaults to HEAD
|
47
|
+
def valid_ref?(url, ref = 'HEAD')
|
48
|
+
raise ArgumentError unless ref
|
49
|
+
found = all_refs(url).find do |sha, data |
|
50
|
+
# we don't need to bother with these types
|
51
|
+
next if data[:type] == :pull || data[:type] == :merge_request
|
52
|
+
# is the name equal to the tag or branch? Is the commit sha equal?
|
53
|
+
data[:name].eql?(ref) || sha.slice(0,8).eql?(ref.slice(0,8))
|
54
|
+
end
|
55
|
+
!found.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Hash] - a hash of all the refs associated with the remote repository
|
59
|
+
# @param url [String] - the git string either https or ssh url
|
60
|
+
# @example
|
61
|
+
# {"0ec707e431367bbe2752966be8ab915b6f0da754"=>{:ref=>"refs/heads/74110ac", :type=>:branch, :subtype=>nil, :name=>"74110ac"},
|
62
|
+
# "07bb5d2d94db222dca5860eb29c184e8970f36f4"=>{:ref=>"refs/pull/74/head", :type=>:pull, :subtype=>:head, :name=>"74"},
|
63
|
+
# "156ca9a8ea69e056e86355b27d944e59d1b3a1e1"=>{:ref=>"refs/heads/master", :type=>:branch, :subtype=>nil, :name=>"master"},
|
64
|
+
# "fcc0532bbc5a5b65f3941738339e9cc7e3d767ce"=>{:ref=>"refs/pull/249/head", :type=>:pull, :subtype=>:head, :name=>"249"},
|
65
|
+
# "8d54891fa5df75890ee15d53080c2a81b4960f92"=>{:ref=>"refs/pull/267/head", :type=>:pull, :subtype=>:head, :name=>"267"} }
|
66
|
+
def all_refs(url)
|
67
|
+
data = `git ls-remote --symref #{url}`
|
68
|
+
raise "Error downloading #{url}" unless $CHILD_STATUS.success?
|
69
|
+
data.lines.reduce({}) do |refs, line|
|
70
|
+
sha, ref = line.split("\t")
|
71
|
+
next refs if sha.eql?('ref: refs/heads/master')
|
72
|
+
_, type, name, subtype = ref.chomp.split('/')
|
73
|
+
next refs unless name
|
74
|
+
type = :tag if type.eql?('tags')
|
75
|
+
type = type.to_sym
|
76
|
+
subtype = subtype.to_sym if subtype
|
77
|
+
type = :branch if type.eql?(:heads)
|
78
|
+
refs[sha] = {ref: ref.chomp, type: type, subtype: subtype, name: name }
|
79
|
+
refs
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [Boolean] - return true if the commit sha is valid
|
84
|
+
# @param url [String] - the git string either https or ssh url
|
85
|
+
# @param ref [String] - the sha id
|
86
|
+
def valid_commit?(url, sha)
|
87
|
+
return false if sha.nil? || sha.empty?
|
88
|
+
return true if valid_ref?(url, sha)
|
89
|
+
Dir.mktmpdir do |dir|
|
90
|
+
`git clone --no-tags #{url} #{dir} 2>&1 > /dev/null`
|
91
|
+
Dir.chdir(dir) do
|
92
|
+
`git show #{sha} 2>&1 > /dev/null`
|
93
|
+
$CHILD_STATUS.success?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [Array[Hash]] array of module information and git status
|
99
|
+
def all_modules
|
100
|
+
begin
|
101
|
+
git_modules(puppetfile).map do |mod|
|
102
|
+
ref = mod[:args][:ref] || mod[:args][:tag] || mod[:args][:branch]
|
103
|
+
valid_ref = valid_ref?(mod[:args][:git], ref) || valid_commit?(mod[:args][:git], mod[:args][:ref])
|
104
|
+
{
|
105
|
+
name: mod[:name],
|
106
|
+
url: mod[:args][:git],
|
107
|
+
ref: ref,
|
108
|
+
valid_ref?: valid_ref,
|
109
|
+
status: valid_ref ? Ra10ke::Validate::GOOD_EMOJI : Ra10ke::Validate::BAD_EMOJI
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return [Boolean] - true if there are any bad mods
|
116
|
+
def bad_mods?
|
117
|
+
all_modules.find_all { |mod| !mod[:valid_ref?] }.count > 0
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [Hash] - sorts the mods based on good/bad
|
121
|
+
def sorted_mods
|
122
|
+
all_modules.sort_by { |a| a[:valid_ref?] ? 1 : 0 }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/ra10ke/version.rb
CHANGED