ra10ke 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +12 -0
- data/lib/ra10ke/solve.rb +227 -0
- data/lib/ra10ke/version.rb +1 -1
- data/lib/ra10ke.rb +7 -4
- data/ra10ke.gemspec +1 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4483e49e41d8b69e98d4730662b79084a670580b
|
4
|
+
data.tar.gz: 0bf2f4d16f66755a60f3653852900e46983136f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de78be1d8e3146d55b207bd48f100f00cd36e310f857d3de3d2cb831dc894c63b3196fa1aa75dd8fda9964c46e1f6f0412507ebb22863a2ec8e19a37bf39fb2c
|
7
|
+
data.tar.gz: 36087c043bb91a4a4b034fb86fc5695c6d2ea74c4ed5ababcb3737b2477ee9714fe30afb8544741feb73a306deacc41633341a7acbf41a354203480776ca223e
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
=========
|
3
3
|
|
4
|
+
0.3.0
|
5
|
+
-----
|
6
|
+
|
7
|
+
2017-10-08
|
8
|
+
|
9
|
+
* [#6](https://github.com/voxpupuli/ra10ke/pull/6) Add a dependency solver based on the Ruby Solve library (thanks to [Jarkko Oranen](https://github.com/oranenj))
|
10
|
+
* [#8](https://github.com/voxpupuli/ra10ke/pull/8) Add numeric tag convention support (thanks to [Hervé MARTIN](https://github.com/HerveMARTIN))
|
11
|
+
|
4
12
|
0.2.0
|
5
13
|
-----
|
6
14
|
|
data/README.md
CHANGED
@@ -40,6 +40,18 @@ Ignoring specific modules:
|
|
40
40
|
Under specific conditions you may not wish to report on specific modules being out of date,
|
41
41
|
to ignore a module create `.r10kignore` file in the same directory as your Puppetfile.
|
42
42
|
|
43
|
+
### r10k:solve_dependencies
|
44
|
+
|
45
|
+
Reads the Puppetfile in the current directory and uses the ruby 'solve' library to find
|
46
|
+
missing and outdated dependencies based on their metadata.
|
47
|
+
|
48
|
+
The solver does not allow major version bumps according to SemVer by default. To allow
|
49
|
+
major upgrades, call the rake task with any parameter.
|
50
|
+
|
51
|
+
The rake task will download git modules into the modules/ directory to access their metadata.json.
|
52
|
+
It will also cache forge metadata in ̃$XDG_CACHE_DIR/ra10ke.metadata_cache in order to make subsequent
|
53
|
+
runs faster.
|
54
|
+
|
43
55
|
#### Limitations
|
44
56
|
|
45
57
|
* It works only with modules from the [Forge](https://forge.puppetlabs.com), and Git.
|
data/lib/ra10ke/solve.rb
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
require 'ra10ke/version'
|
4
|
+
require 'git'
|
5
|
+
require 'set'
|
6
|
+
require 'solve'
|
7
|
+
require 'yaml/store'
|
8
|
+
require 'semverse/version'
|
9
|
+
|
10
|
+
# How many versions to fetch from the Forge, at most
|
11
|
+
FETCH_LIMIT = 3
|
12
|
+
|
13
|
+
module Ra10ke::Solve
|
14
|
+
class RakeTask < ::Rake::TaskLib
|
15
|
+
def initialize(*_args)
|
16
|
+
namespace :r10k do
|
17
|
+
desc 'Find missing or outdated module dependencies'
|
18
|
+
task :solve_dependencies, [:allow_major_bump] do |_t, args|
|
19
|
+
require 'r10k/puppetfile'
|
20
|
+
require 'r10k/module/git'
|
21
|
+
require 'r10k/module/metadata_file'
|
22
|
+
require 'puppet_forge'
|
23
|
+
|
24
|
+
allow_major_bump = false
|
25
|
+
allow_major_bump = true if args[:allow_major_bump]
|
26
|
+
|
27
|
+
# Same as in the dependencies task, but oh well.
|
28
|
+
PuppetForge.user_agent = "ra10ke/#{Ra10ke::VERSION}"
|
29
|
+
puppetfile = R10K::Puppetfile.new('.')
|
30
|
+
puppetfile.load!
|
31
|
+
|
32
|
+
# ignore file allows for "don't tell me about this"
|
33
|
+
ignore_modules = []
|
34
|
+
if File.exist?('.r10kignore')
|
35
|
+
ignore_modules = File.readlines('.r10kignore').each(&:chomp!)
|
36
|
+
end
|
37
|
+
# Actual new logic begins here:
|
38
|
+
cache = (ENV['XDG_CACHE_DIR'] || File.expand_path('~/.cache'))
|
39
|
+
# Metadata cache, since the Forge is slow:
|
40
|
+
@metadata_cache = YAML::Store.new File.join(cache, 'ra10ke.metadata_cache')
|
41
|
+
# The graph of available module versions
|
42
|
+
@graph = Solve::Graph.new
|
43
|
+
# Set of modules that we have already added to the graph
|
44
|
+
@processed_modules = Set.new
|
45
|
+
# The set of "demands" we make of the solver. Will be a list of module names
|
46
|
+
# Could also demand certain version constraints to hold, but the code does not do it
|
47
|
+
# Can be either "module-name" or ["module-name", "version-constraint"]
|
48
|
+
@demands = Set.new
|
49
|
+
# List of modules we have in the Puppetfile, as [name, version] pairs
|
50
|
+
@current_modules = []
|
51
|
+
|
52
|
+
puppetfile.modules.each do |puppet_module|
|
53
|
+
next if ignore_modules.include? puppet_module.title
|
54
|
+
if puppet_module.class == R10K::Module::Forge
|
55
|
+
module_name = puppet_module.title.tr('/', '-')
|
56
|
+
installed_version = puppet_module.expected_version
|
57
|
+
puts "Processing Forge module #{module_name}-#{installed_version}"
|
58
|
+
@current_modules << [module_name, installed_version]
|
59
|
+
@graph.artifact(module_name, installed_version)
|
60
|
+
constraint = '>=0.0.0'
|
61
|
+
unless allow_major_bump
|
62
|
+
ver = Semverse::Version.new installed_version
|
63
|
+
if ver.major.zero?
|
64
|
+
constraint = "~>#{installed_version}"
|
65
|
+
else
|
66
|
+
nver = Semverse::Version.new([ver.major + 1, 0, 0])
|
67
|
+
constraint = "<#{nver}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
puts "...Adding a demand: #{module_name} #{constraint}"
|
71
|
+
|
72
|
+
@demands.add([module_name, constraint])
|
73
|
+
puts '...Fetching latest release version information'
|
74
|
+
forge_rel = PuppetForge::Module.find(module_name).current_release
|
75
|
+
mod = @graph.artifact(module_name, forge_rel.version)
|
76
|
+
puts '...Adding its requirements to the graph'
|
77
|
+
meta = get_release_metadata(module_name, forge_rel)
|
78
|
+
add_reqs_to_graph(mod, meta)
|
79
|
+
end
|
80
|
+
|
81
|
+
next unless puppet_module.class == R10K::Module::Git
|
82
|
+
# This downloads the git module to modules/modulename
|
83
|
+
meta = fetch_git_metadata(puppet_module)
|
84
|
+
version = get_key_or_sym(meta, :version)
|
85
|
+
module_name = puppet_module.title.tr('/', '-')
|
86
|
+
@current_modules << [module_name, version]
|
87
|
+
# We should add git modules with exact versions, or the system might recommend updating to a
|
88
|
+
# Forge version.
|
89
|
+
puts "Adding git module #{module_name} to the list of required modules with exact version: #{version}"
|
90
|
+
@demands.add([module_name, version])
|
91
|
+
mod = @graph.artifact(module_name, version)
|
92
|
+
puts "...Adding requirements for git module #{module_name}-#{version}"
|
93
|
+
add_reqs_to_graph(mod, meta)
|
94
|
+
end
|
95
|
+
puts
|
96
|
+
puts 'Resolving dependencies...'
|
97
|
+
if allow_major_bump
|
98
|
+
puts 'WARNING: Potentially breaking updates are allowed for this resolution'
|
99
|
+
end
|
100
|
+
result = Solve.it!(@graph, @demands, sorted: true)
|
101
|
+
puts
|
102
|
+
print_module_diff(@current_modules, result)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
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
|
114
|
+
end
|
115
|
+
end
|
116
|
+
meta
|
117
|
+
end
|
118
|
+
|
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: []
|
130
|
+
}
|
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
|
140
|
+
|
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
|
145
|
+
|
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
|
152
|
+
|
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]
|
166
|
+
end
|
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
|
175
|
+
|
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}"
|
200
|
+
end
|
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
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
Ra10ke::Solve::RakeTask.new
|
data/lib/ra10ke/version.rb
CHANGED
data/lib/ra10ke.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/tasklib'
|
3
3
|
require 'ra10ke/version'
|
4
|
+
require 'ra10ke/solve'
|
4
5
|
require 'git'
|
5
6
|
|
6
7
|
module Ra10ke
|
@@ -52,12 +53,14 @@ module Ra10ke
|
|
52
53
|
when 'sha'
|
53
54
|
latest_ref = remote_refs['head'][:sha]
|
54
55
|
when 'tag'
|
55
|
-
# we have to be opinionated here, due to multiple conventions only
|
56
|
-
#
|
57
|
-
if ref.match(/^[vV]
|
56
|
+
# we have to be opinionated here, due to multiple conventions only the two main will be accepted
|
57
|
+
# v#.#.# or #.#.# is what we will pick.
|
58
|
+
if ref.match(/^[vV]?\d[\.\d]*/)
|
58
59
|
tags = remote_refs['tags']
|
59
|
-
version_tags = tags.select { |f| /^[vV]
|
60
|
+
version_tags = tags.select { |f| /^[vV]?\d[\.\d]*/.match(f) }
|
60
61
|
latest_ref = version_tags.keys.sort.last
|
62
|
+
else
|
63
|
+
latest_ref = "undef (tags don't match v#.#.# or #.#.#)"
|
61
64
|
end
|
62
65
|
else
|
63
66
|
raise "Unable to determine ref_type for #{puppet_module.title}"
|
data/ra10ke.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ra10ke
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Theo Chatzimichos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: solve
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
description: R10K and Puppetfile rake tasks
|
70
84
|
email:
|
71
85
|
- tampakrap@gmail.com
|
@@ -79,6 +93,7 @@ files:
|
|
79
93
|
- LICENSE.txt
|
80
94
|
- README.md
|
81
95
|
- lib/ra10ke.rb
|
96
|
+
- lib/ra10ke/solve.rb
|
82
97
|
- lib/ra10ke/version.rb
|
83
98
|
- ra10ke.gemspec
|
84
99
|
homepage: https://github.com/voxpupuli/ra10ke
|
@@ -101,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
116
|
version: '0'
|
102
117
|
requirements: []
|
103
118
|
rubyforge_project:
|
104
|
-
rubygems_version: 2.
|
119
|
+
rubygems_version: 2.6.11
|
105
120
|
signing_key:
|
106
121
|
specification_version: 4
|
107
122
|
summary: Syntax check for the Puppetfile, check for outdated installed puppet modules
|