knife-changelog 1.0.6 → 1.0.7
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/.rubocop.yml +6 -0
- data/knife-changelog.gemspec +20 -18
- data/lib/chef/knife/changelog.rb +37 -37
- data/lib/knife/changelog/version.rb +1 -1
- data/lib/policyfile.rb +194 -0
- data/spec/data/Policyfile.lock.json +30 -41
- data/spec/data/Policyfile.rb +3 -5
- data/spec/data/tmp_dir/Policyfile.lock.json +61 -0
- data/spec/spec_helper.rb +7 -3
- data/spec/unit/changelog_spec.rb +1 -61
- data/spec/unit/policyfile_spec.rb +260 -0
- metadata +43 -11
- data/lib/knife/changelog/policyfile.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69172c86c7b7796d3ec52bc1738688d33dcef55ccdf98d4f171cff25b9ee03a1
|
4
|
+
data.tar.gz: 94329ddcd6763e6d6ab8d510ce5e06850f93798e026405bf3d114fd51e13a7cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2eef04a07df70eae15e9d5b8158c5956fb7782e5ad678545d65164b027aacf17e80c17d2efd9100644b46aed638b85f6cdd437f0877a31d7041351d7a8b3f8f6
|
7
|
+
data.tar.gz: 43a215deba3fae621e9c156acfbc8a0ebb8101a94c15932e355fefbfba6532457fe31f25bd277c9e054bdcd8afcd868270e78ac8155780dee75220d06069bb9a
|
data/.rubocop.yml
CHANGED
data/knife-changelog.gemspec
CHANGED
@@ -1,34 +1,36 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'knife/changelog/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'knife-changelog'
|
8
9
|
spec.version = Knife::Changelog::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
10
|
+
spec.authors = ['Gregoire Seux']
|
11
|
+
spec.email = ['kamaradclimber@gmail.com']
|
12
|
+
spec.summary = 'Facilitate access to cookbooks changelog'
|
13
|
+
spec.description = ''
|
14
|
+
spec.homepage = 'https://github.com/kamaradclimber/knife-changelog'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
17
|
spec.files = `git ls-files -z`.split("\x0")
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
-
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "rspec"
|
24
|
-
spec.add_development_dependency "rubocop"
|
25
|
-
spec.add_development_dependency "webmock"
|
26
|
-
spec.add_development_dependency "pry"
|
20
|
+
spec.require_paths = ['lib']
|
27
21
|
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
23
|
+
spec.add_development_dependency 'pry'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'rubocop'
|
27
|
+
spec.add_development_dependency 'webmock'
|
28
28
|
|
29
29
|
spec.add_dependency 'berkshelf'
|
30
|
-
spec.add_dependency 'rest-client'
|
31
|
-
spec.add_dependency 'mixlib-shellout'
|
32
30
|
spec.add_dependency 'chef'
|
33
31
|
spec.add_dependency 'chef-dk'
|
32
|
+
spec.add_dependency 'deep_merge'
|
33
|
+
spec.add_dependency 'git'
|
34
|
+
spec.add_dependency 'mixlib-shellout'
|
35
|
+
spec.add_dependency 'rest-client'
|
34
36
|
end
|
data/lib/chef/knife/changelog.rb
CHANGED
@@ -1,68 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'chef/knife'
|
2
4
|
require 'mixlib/shellout'
|
3
5
|
|
4
6
|
class Chef
|
5
7
|
class Knife
|
6
8
|
class Changelog < Knife
|
7
|
-
|
8
9
|
banner 'knife changelog COOKBOOK [COOKBOOK ...]'
|
9
10
|
|
10
11
|
deps do
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
12
|
+
require 'knife/changelog/version'
|
13
|
+
require 'knife/changelog/changelog'
|
14
|
+
require 'knife/changelog/berksfile'
|
15
|
+
require 'berkshelf'
|
16
|
+
require 'policyfile'
|
16
17
|
end
|
17
18
|
|
18
19
|
option :linkify,
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
short: '-l',
|
21
|
+
long: '--linkify',
|
22
|
+
description: 'add markdown links where relevant',
|
23
|
+
boolean: true
|
23
24
|
|
24
25
|
option :markdown,
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
short: '-m',
|
27
|
+
long: '--markdown',
|
28
|
+
description: 'use markdown syntax',
|
29
|
+
boolean: true
|
29
30
|
|
30
31
|
option :ignore_changelog_file,
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
long: '--ignore-changelog-file',
|
33
|
+
description: 'Ignore changelog file presence, use git history instead',
|
34
|
+
boolean: true
|
34
35
|
|
35
36
|
option :allow_update_all,
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
long: '--allow-update-all',
|
38
|
+
description: 'If no cookbook given, check all Berksfile',
|
39
|
+
boolean: true,
|
40
|
+
default: true
|
40
41
|
|
41
42
|
option :submodules,
|
42
|
-
|
43
|
-
|
43
|
+
long: '--submodules SUBMODULE[,SUBMODULE]',
|
44
|
+
description: 'Submoduless to check for changes as well (comma separated)'
|
44
45
|
|
45
46
|
option :policyfile,
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
long: '--policyfile PATH',
|
48
|
+
description: 'Link to policyfile, defaults to "Policyfile.rb"',
|
49
|
+
default: 'Policyfile.rb'
|
49
50
|
|
50
51
|
option :update,
|
51
|
-
|
52
|
-
|
52
|
+
long: '--update',
|
53
|
+
description: 'Update Berksfile'
|
53
54
|
|
54
55
|
def run
|
55
56
|
Log.info config
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
if config[:policyfile] && File.exist?(config[:policyfile])
|
58
|
+
PolicyChangelog.new(@name_args, config[:policyfile]).generate_changelog
|
59
|
+
else
|
60
|
+
berksfile = Berkshelf::Berksfile.from_options({})
|
61
|
+
puts KnifeChangelog::Changelog::Berksfile
|
62
|
+
.new(berksfile, config)
|
63
|
+
.run(@name_args)
|
64
|
+
end
|
64
65
|
end
|
65
66
|
end
|
66
|
-
|
67
67
|
end
|
68
68
|
end
|
data/lib/policyfile.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'chef'
|
4
|
+
require 'chef/knife'
|
5
|
+
require 'chef-dk/command/update'
|
6
|
+
require 'deep_merge'
|
7
|
+
require 'git'
|
8
|
+
require 'json'
|
9
|
+
require 'rest-client'
|
10
|
+
|
11
|
+
class PolicyChangelog
|
12
|
+
TMP_PREFIX = 'knife-changelog'
|
13
|
+
|
14
|
+
# Initialzes Helper class
|
15
|
+
#
|
16
|
+
# @param cookbooks [Array<String>] cookbooks to update (@name_args)
|
17
|
+
# @param policyfile [String] policyfile path
|
18
|
+
def initialize(cookbooks, policyfile)
|
19
|
+
@cookbooks_to_update = cookbooks
|
20
|
+
@policyfile_path = File.expand_path(policyfile)
|
21
|
+
@policyfile_dir = File.dirname(@policyfile_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Updates the Policyfile.lock to get version differences.
|
25
|
+
#
|
26
|
+
# @return update_dir [String] tmp directory with updated Policyfile.lock
|
27
|
+
def update_policyfile_lock
|
28
|
+
update_dir = Dir.mktmpdir
|
29
|
+
%w[Policyfile.rb Policyfile.lock.json].each do |file|
|
30
|
+
FileUtils.cp(
|
31
|
+
File.join(@policyfile_dir, file),
|
32
|
+
update_dir
|
33
|
+
)
|
34
|
+
end
|
35
|
+
updater = ChefDK::Command::Update.new
|
36
|
+
updater.run([
|
37
|
+
File.join(update_dir, 'Policyfile.rb'),
|
38
|
+
@cookbooks_to_update
|
39
|
+
].flatten)
|
40
|
+
update_dir
|
41
|
+
end
|
42
|
+
|
43
|
+
# Parses JSON in Policyfile.lock.
|
44
|
+
#
|
45
|
+
# @param dir [String] directory containing Policyfile.lock
|
46
|
+
# @return [Hash] contents of Policyfile.lock
|
47
|
+
def read_policyfile_lock(dir)
|
48
|
+
lock = File.join(dir, 'Policyfile.lock.json')
|
49
|
+
raise "File #{lock} does not exist" unless File.exist?(lock)
|
50
|
+
content = JSON.parse(File.read(lock))
|
51
|
+
raise 'Policyfile.lock empty' if content.empty?
|
52
|
+
content
|
53
|
+
end
|
54
|
+
|
55
|
+
# Extracts current or target versions from Policyfile.lock data depending
|
56
|
+
# on the type value provided.
|
57
|
+
#
|
58
|
+
# @param locks [Hash] cookbook data from Policyfile.lock
|
59
|
+
# @param type [String] version type - current or target
|
60
|
+
# @return [Hash] cookbooks with their versions
|
61
|
+
def versions(locks, type)
|
62
|
+
raise 'Use "current" or "target" as type' unless %w[current target].include?(type)
|
63
|
+
raise 'Cookbook locks empty or nil' if locks.nil? or locks.empty?
|
64
|
+
cookbooks = {}
|
65
|
+
locks.each do |name, data|
|
66
|
+
cookbooks[name] = { "#{type}_version" => data['version'] }
|
67
|
+
end
|
68
|
+
cookbooks
|
69
|
+
end
|
70
|
+
|
71
|
+
# Extracts Git source URL from cookbook 'source_options' data depending
|
72
|
+
# on the source type - Supermarket or Git
|
73
|
+
#
|
74
|
+
# @param s [Hash] source_options for a cookbook in the Policyfile.lock
|
75
|
+
# @return [String] Git source code URL
|
76
|
+
def get_source_url(s)
|
77
|
+
if s.keys.include?('artifactserver')
|
78
|
+
{ 'source_url' => supermarket_source_url(s['artifactserver'][%r{(.+)\/versions\/.*}, 1]) }
|
79
|
+
else
|
80
|
+
{ 'source_url' => s['git'] }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Fetches cookbook metadata from Supermarket and extracts Git source URL
|
85
|
+
#
|
86
|
+
# @param url [String] Supermarket cookbook URL
|
87
|
+
# @return [String] Git source code URL
|
88
|
+
def supermarket_source_url(url)
|
89
|
+
source_url = JSON.parse(RestClient::Request.execute(
|
90
|
+
url: url,
|
91
|
+
method: :get,
|
92
|
+
verify_ssl: false
|
93
|
+
))['source_url']
|
94
|
+
source_url = "#{source_url}.git" unless source_url.end_with?('.git')
|
95
|
+
source_url
|
96
|
+
end
|
97
|
+
|
98
|
+
# Clones a Git repo in a temporary directory and generates a commit
|
99
|
+
# changelog between two version tags
|
100
|
+
#
|
101
|
+
# @param source_url [String] Git repository URL
|
102
|
+
# @param current [String] current cookbook version tag
|
103
|
+
# @param target [String] target cookbook version tag
|
104
|
+
# @return [String] changelog between tags for one cookbook
|
105
|
+
def git_changelog(source_url, current, target)
|
106
|
+
dir = Dir.mktmpdir(TMP_PREFIX)
|
107
|
+
repo = Git.clone(source_url, dir)
|
108
|
+
if tag_format(repo) == 'v'
|
109
|
+
c_tag, t_tag = correct_tags("v#{current}", "v#{target}", repo)
|
110
|
+
repo.log.between(c_tag, t_tag)
|
111
|
+
else
|
112
|
+
c_tag, t_tag = correct_tags(current, target, repo)
|
113
|
+
repo.log.between(c_tag, t_tag)
|
114
|
+
end.map do |commit|
|
115
|
+
"#{commit.sha[0, 7]} #{commit.message.lines.first.strip}"
|
116
|
+
end.join("\n")
|
117
|
+
end
|
118
|
+
|
119
|
+
# Used to make #git_changelog method more readable
|
120
|
+
#
|
121
|
+
# @param current [String] current cookbook version tag
|
122
|
+
# @param target [String] target cookbook version tag
|
123
|
+
# @param repo [Git::Base] Git repository object
|
124
|
+
# @return [true, false]
|
125
|
+
def correct_tags(current, target, repo)
|
126
|
+
[git_tag(current, repo), git_tag(target, repo)]
|
127
|
+
end
|
128
|
+
|
129
|
+
# Tries to convert a supermarket tag to a git tag
|
130
|
+
# if there is a difference in formatting between the two.
|
131
|
+
# This is issue is present for the 'java' cookbook.
|
132
|
+
# https://github.com/agileorbit-cookbooks/java/issues/450
|
133
|
+
#
|
134
|
+
# @param tag [String] version tag
|
135
|
+
# @param repo [Git::Base] Git repository object
|
136
|
+
# @return [String]
|
137
|
+
def git_tag(tag, repo)
|
138
|
+
return tag if repo.checkout(tag)
|
139
|
+
rescue ::Git::GitExecuteError
|
140
|
+
begin
|
141
|
+
rescue_tag = tag.chomp('.0') if tag[/\.0$/]
|
142
|
+
return rescue_tag if repo.checkout(rescue_tag)
|
143
|
+
rescue ::Git::GitExecuteError
|
144
|
+
raise 'Difference between Git and Supermarket tags'
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Detects the format of a Git tag - v1.0.0 or 1.0.0
|
149
|
+
#
|
150
|
+
# @param repo [Git::Base] Git repository object
|
151
|
+
# @return [String] Git tag versioning type
|
152
|
+
def tag_format(repo)
|
153
|
+
repo.tags.last.name[/^v/] ? 'v' : ''
|
154
|
+
end
|
155
|
+
|
156
|
+
# Prints out commit changelog in a nicely formatted way
|
157
|
+
#
|
158
|
+
# @param name [String] cookbook name
|
159
|
+
# @param data [Hash] cookbook versions and source url data
|
160
|
+
def print_commit_changelog(name, data)
|
161
|
+
output = "\nChangelog for #{name}: #{data['current_version']}->#{data['target_version']}"
|
162
|
+
puts output
|
163
|
+
puts '=' * output.size
|
164
|
+
puts git_changelog(data['source_url'], data['current_version'], data['target_version'])
|
165
|
+
end
|
166
|
+
|
167
|
+
# Filters out cookbooks which are not updated, are not used after update or
|
168
|
+
# are newly added as dependencies during update
|
169
|
+
#
|
170
|
+
# @param [Hash] cookbook versions and source url data
|
171
|
+
# @return [true, false]
|
172
|
+
def reject_version_filter(data)
|
173
|
+
raise 'Data containing versions is nil' if data.nil?
|
174
|
+
data['current_version'] == data['target_version'] ||
|
175
|
+
data['current_version'].nil? ||
|
176
|
+
data['target_version'].nil?
|
177
|
+
end
|
178
|
+
|
179
|
+
# Generates Policyfile changelog
|
180
|
+
def generate_changelog
|
181
|
+
lock_current = read_policyfile_lock(@policyfile_dir)
|
182
|
+
current = versions(lock_current['cookbook_locks'], 'current')
|
183
|
+
|
184
|
+
lock_target = read_policyfile_lock(update_policyfile_lock)
|
185
|
+
target = versions(lock_target['cookbook_locks'], 'target')
|
186
|
+
|
187
|
+
updated_cookbooks = current.deep_merge(target).reject { |_name, data| reject_version_filter(data) }
|
188
|
+
sources = {}
|
189
|
+
updated_cookbooks.each_key do |name|
|
190
|
+
sources[name] = get_source_url(lock_target['cookbook_locks'][name]['source_options'])
|
191
|
+
end
|
192
|
+
updated_cookbooks.deep_merge(sources).each { |name, data| print_commit_changelog(name, data) }
|
193
|
+
end
|
194
|
+
end
|
@@ -1,41 +1,34 @@
|
|
1
1
|
{
|
2
|
-
"revision_id": "
|
2
|
+
"revision_id": "ca956e1f3b6bcbb1bd98e6f2aa58d22ae73191e4960f4039b3dea7225915205c",
|
3
3
|
"name": "test_policy",
|
4
4
|
"run_list": [
|
5
|
-
"recipe[
|
5
|
+
"recipe[users::default]",
|
6
|
+
"recipe[sudo::default]"
|
7
|
+
],
|
8
|
+
"included_policy_locks": [
|
9
|
+
|
6
10
|
],
|
7
11
|
"cookbook_locks": {
|
8
|
-
"
|
9
|
-
"version": "
|
10
|
-
"identifier": "
|
11
|
-
"dotted_decimal_identifier": "
|
12
|
-
"cache_key": "
|
13
|
-
"origin": "https://
|
14
|
-
"source_options": {
|
15
|
-
"artifactserver": "https://mysupermarket2.io:443/api/v1/cookbooks/uptodate/versions/1.0.0/download",
|
16
|
-
"version": "1.0.0"
|
17
|
-
}
|
18
|
-
},
|
19
|
-
"outdated1": {
|
20
|
-
"version": "1.0.0",
|
21
|
-
"identifier": "c29076b3a9aae74c7edd9790343eb1502e2fa8f1",
|
22
|
-
"dotted_decimal_identifier": "54764984976648935.21531588425692222.194957930375411",
|
23
|
-
"cache_key": "outdated1-1.0.0-mysupermarket2.io",
|
24
|
-
"origin": "https://mysupermarket2.io:443/api/v1/cookbooks/outdated1/versions/1.0.0/download",
|
12
|
+
"sudo": {
|
13
|
+
"version": "3.5.0",
|
14
|
+
"identifier": "35c2f73f9f88d16c8556b80297c4c00fa104fdba",
|
15
|
+
"dotted_decimal_identifier": "15132540945795281.30545904985610180.211173358501306",
|
16
|
+
"cache_key": "sudo-3.5.0-supermarket.chef.io",
|
17
|
+
"origin": "https://supermarket.chef.io:443/api/v1/cookbooks/sudo/versions/3.5.0/download",
|
25
18
|
"source_options": {
|
26
|
-
"artifactserver": "https://
|
27
|
-
"version": "
|
19
|
+
"artifactserver": "https://supermarket.chef.io:443/api/v1/cookbooks/sudo/versions/3.5.0/download",
|
20
|
+
"version": "3.5.0"
|
28
21
|
}
|
29
22
|
},
|
30
|
-
"
|
31
|
-
"version": "
|
32
|
-
"identifier": "
|
33
|
-
"dotted_decimal_identifier": "
|
34
|
-
"cache_key": "
|
35
|
-
"origin": "https://
|
23
|
+
"users": {
|
24
|
+
"version": "4.0.0",
|
25
|
+
"identifier": "5920ea9767ce2e71fb17b2107888abe89043ee53",
|
26
|
+
"dotted_decimal_identifier": "25087464861847086.32082751558547592.189015341133395",
|
27
|
+
"cache_key": "users-4.0.0-supermarket.chef.io",
|
28
|
+
"origin": "https://supermarket.chef.io:443/api/v1/cookbooks/users/versions/4.0.0/download",
|
36
29
|
"source_options": {
|
37
|
-
"artifactserver": "https://
|
38
|
-
"version": "
|
30
|
+
"artifactserver": "https://supermarket.chef.io:443/api/v1/cookbooks/users/versions/4.0.0/download",
|
31
|
+
"version": "4.0.0"
|
39
32
|
}
|
40
33
|
}
|
41
34
|
},
|
@@ -48,24 +41,20 @@
|
|
48
41
|
"solution_dependencies": {
|
49
42
|
"Policyfile": [
|
50
43
|
[
|
51
|
-
"
|
52
|
-
"=
|
44
|
+
"sudo",
|
45
|
+
"= 3.5.0"
|
53
46
|
],
|
54
47
|
[
|
55
|
-
"
|
56
|
-
"=
|
57
|
-
],
|
58
|
-
[
|
59
|
-
"second_out_of_date",
|
60
|
-
"= 1.0.0"
|
48
|
+
"users",
|
49
|
+
"= 4.0.0"
|
61
50
|
]
|
62
51
|
],
|
63
52
|
"dependencies": {
|
64
|
-
"
|
65
|
-
|
66
|
-
"outdated1 (1.0.0)": [
|
53
|
+
"sudo (3.5.0)": [
|
54
|
+
|
67
55
|
],
|
68
|
-
"
|
56
|
+
"users (4.0.0)": [
|
57
|
+
|
69
58
|
]
|
70
59
|
}
|
71
60
|
}
|
data/spec/data/Policyfile.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
name 'test_policy'
|
2
2
|
|
3
3
|
run_list [
|
4
|
-
'recipe[
|
5
|
-
'recipe[
|
6
|
-
'recipe[outdated1]'
|
4
|
+
'recipe[users]',
|
5
|
+
'recipe[sudo]',
|
7
6
|
]
|
8
7
|
|
9
|
-
default_source :supermarket,
|
10
|
-
default_source :supermarket, 'https://mysupermarket2.io'
|
8
|
+
default_source :supermarket, "https://supermarket.chef.io"
|
@@ -0,0 +1,61 @@
|
|
1
|
+
{
|
2
|
+
"revision_id": "3ec29adf59408f8bac3408f9e284bae035b470eccda904544c4d1f541018289d",
|
3
|
+
"name": "test_policy",
|
4
|
+
"run_list": [
|
5
|
+
"recipe[users::default]",
|
6
|
+
"recipe[sudo::default]"
|
7
|
+
],
|
8
|
+
"included_policy_locks": [
|
9
|
+
|
10
|
+
],
|
11
|
+
"cookbook_locks": {
|
12
|
+
"sudo": {
|
13
|
+
"version": "3.5.0",
|
14
|
+
"identifier": "35c2f73f9f88d16c8556b80297c4c00fa104fdba",
|
15
|
+
"dotted_decimal_identifier": "15132540945795281.30545904985610180.211173358501306",
|
16
|
+
"cache_key": "sudo-3.5.0-supermarket.chef.io",
|
17
|
+
"origin": "https://supermarket.chef.io:443/api/v1/cookbooks/sudo/versions/3.5.0/download",
|
18
|
+
"source_options": {
|
19
|
+
"artifactserver": "https://supermarket.chef.io:443/api/v1/cookbooks/sudo/versions/3.5.0/download",
|
20
|
+
"version": "3.5.0"
|
21
|
+
}
|
22
|
+
},
|
23
|
+
"users": {
|
24
|
+
"version": "5.3.1",
|
25
|
+
"identifier": "41c2bf84fe2476bbbe2dbe79362e6726a3ea47c7",
|
26
|
+
"dotted_decimal_identifier": "18510001311982710.52844924323313198.113415656458183",
|
27
|
+
"cache_key": "users-5.3.1-supermarket.chef.io",
|
28
|
+
"origin": "https://supermarket.chef.io:443/api/v1/cookbooks/users/versions/5.3.1/download",
|
29
|
+
"source_options": {
|
30
|
+
"artifactserver": "https://supermarket.chef.io:443/api/v1/cookbooks/users/versions/5.3.1/download",
|
31
|
+
"version": "5.3.1"
|
32
|
+
}
|
33
|
+
}
|
34
|
+
},
|
35
|
+
"default_attributes": {
|
36
|
+
|
37
|
+
},
|
38
|
+
"override_attributes": {
|
39
|
+
|
40
|
+
},
|
41
|
+
"solution_dependencies": {
|
42
|
+
"Policyfile": [
|
43
|
+
[
|
44
|
+
"sudo",
|
45
|
+
"= 3.5.0"
|
46
|
+
],
|
47
|
+
[
|
48
|
+
"users",
|
49
|
+
"= 5.3.1"
|
50
|
+
]
|
51
|
+
],
|
52
|
+
"dependencies": {
|
53
|
+
"sudo (3.5.0)": [
|
54
|
+
|
55
|
+
],
|
56
|
+
"users (5.3.1)": [
|
57
|
+
|
58
|
+
]
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require 'knife/changelog/changelog'
|
4
|
+
require 'knife/changelog/berksfile'
|
5
|
+
require 'policyfile'
|
6
|
+
|
7
|
+
require 'webmock/rspec'
|
8
|
+
|
9
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
6
10
|
|
7
11
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
8
12
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
data/spec/unit/changelog_spec.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../spec_helper'
|
4
|
-
require 'webmock/rspec'
|
5
3
|
require 'berkshelf'
|
6
|
-
|
7
|
-
WebMock.disable_net_connect!
|
4
|
+
require 'spec_helper'
|
8
5
|
|
9
6
|
RSpec.shared_examples 'changelog generation' do
|
10
7
|
# this supposes that "changelog" is an instance of KnifeChangelog::Changelog
|
@@ -117,63 +114,6 @@ describe KnifeChangelog::Changelog do
|
|
117
114
|
end
|
118
115
|
end
|
119
116
|
end
|
120
|
-
|
121
|
-
context 'in policyfile mode' do
|
122
|
-
let(:policyfile_path) { File.join(File.dirname(__FILE__), '../data/Policyfile.rb') }
|
123
|
-
|
124
|
-
let(:options) do
|
125
|
-
{}
|
126
|
-
end
|
127
|
-
|
128
|
-
let(:changelog) do
|
129
|
-
KnifeChangelog::Changelog::Policyfile.new(policyfile_path, options)
|
130
|
-
end
|
131
|
-
|
132
|
-
before(:each) do
|
133
|
-
allow(changelog.policy).to receive(:cache_fixed_version_cookbooks)
|
134
|
-
end
|
135
|
-
|
136
|
-
include_examples 'changelog generation'
|
137
|
-
|
138
|
-
context 'with --update' do
|
139
|
-
let(:options) do
|
140
|
-
{ update: true }
|
141
|
-
end
|
142
|
-
it 'fails with not implemented error' do
|
143
|
-
mock_git('outdated1', <<-EOH)
|
144
|
-
aaaaaa commit in outdated1
|
145
|
-
bbbbbb bugfix in outdated1
|
146
|
-
EOH
|
147
|
-
expect { changelog.run(%w[outdated1]) }.to raise_error(NotImplementedError)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
context 'whith --allow-update-all ' do
|
152
|
-
let(:options) do
|
153
|
-
{ "allow_update_all": true }
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'should compute the changelog of all dependencies' do
|
157
|
-
mock_git('second_out_of_date', <<-EOH)
|
158
|
-
aaaaaa commit in second_out_of_date
|
159
|
-
bbbbbb bugfix in second_out_of_date
|
160
|
-
EOH
|
161
|
-
mock_git('outdated1', <<-EOH)
|
162
|
-
aaaaaa commit in outdated1
|
163
|
-
bbbbbb bugfix in outdated1
|
164
|
-
EOH
|
165
|
-
mock_git('uptodate', '')
|
166
|
-
|
167
|
-
expect(changelog).to receive(:supermarkets_for).with('outdated1')
|
168
|
-
.and_return(["https://mysupermarket2.io"])
|
169
|
-
expect(changelog).to receive(:supermarkets_for).with('second_out_of_date')
|
170
|
-
.and_return(["https://mysupermarket2.io"])
|
171
|
-
expect(changelog).to receive(:supermarkets_for).with('uptodate')
|
172
|
-
.and_return(["https://mysupermarket2.io"])
|
173
|
-
changelog.run([])
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
117
|
end
|
178
118
|
|
179
119
|
class Hash
|
@@ -0,0 +1,260 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'git'
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
RSpec.describe PolicyChangelog do
|
7
|
+
let(:pf_dir) do
|
8
|
+
File.expand_path(File.join(File.dirname(__FILE__), '../data'))
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:tmp_dir) do
|
12
|
+
File.join(pf_dir, 'tmp_dir')
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:changelog) do
|
16
|
+
PolicyChangelog.new('users', File.join(pf_dir, 'Policyfile.rb'))
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:lock_current) do
|
20
|
+
JSON.parse(File.read(File.join(pf_dir, 'Policyfile.lock.json')))
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:lock_target) do
|
24
|
+
JSON.parse(File.read(File.join(tmp_dir, 'Policyfile.lock.json')))
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:current_versions) do
|
28
|
+
{
|
29
|
+
'sudo' => { 'current_version' => '3.5.0' },
|
30
|
+
'users' => { 'current_version' => '4.0.0' }
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:target_versions) do
|
35
|
+
{
|
36
|
+
'sudo' => { 'target_version' => '3.5.0' },
|
37
|
+
'users' => { 'target_version' => '5.3.1' }
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:url) { 'https://supermarket.chef.io/api/v1/cookbooks/users' }
|
42
|
+
|
43
|
+
before(:each) do
|
44
|
+
stub_request(:get, 'https://supermarket.chef.io/api/v1/cookbooks/users').to_return(
|
45
|
+
status: 200,
|
46
|
+
body: '{
|
47
|
+
"name": "users",
|
48
|
+
"maintainer": "chef",
|
49
|
+
"description": "Creates users from a databag search",
|
50
|
+
"category": "Other",
|
51
|
+
"latest_version": "https://supermarket.chef.io/api/v1/cookbooks/users/versions/5.3.1",
|
52
|
+
"external_url": "https://github.com/chef-cookbooks/users",
|
53
|
+
"source_url": "https://github.com/chef-cookbooks/users",
|
54
|
+
"issues_url": "https://github.com/chef-cookbooks/users/issues",
|
55
|
+
"average_rating": null,
|
56
|
+
"created_at": "2010-07-27T05:34:01.000Z",
|
57
|
+
"updated_at": "2017-12-15T18:08:26.990Z",
|
58
|
+
"up_for_adoption": null,
|
59
|
+
"deprecated": false,
|
60
|
+
"versions": [],
|
61
|
+
"metrics": {}
|
62
|
+
}'
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#read_policyfile_lock' do
|
67
|
+
context 'when Policyfile.lock.json does not exist' do
|
68
|
+
it 'raises an exception' do
|
69
|
+
expect { changelog.read_policyfile_lock('/does/not/exist') }.to raise_error(RuntimeError)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when Policyfile.lock.json is empty' do
|
74
|
+
it 'raises an exception' do
|
75
|
+
allow(File).to receive(:read).and_return('')
|
76
|
+
expect { changelog.read_policyfile_lock('') }.to raise_error(RuntimeError)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#versions' do
|
82
|
+
context 'when type is current' do
|
83
|
+
it 'returns correct current versions' do
|
84
|
+
expect(changelog.versions(lock_current['cookbook_locks'], 'current')).to eq(current_versions)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when type is target' do
|
89
|
+
it 'returns correct target versions' do
|
90
|
+
expect(changelog.versions(lock_target['cookbook_locks'], 'target')).to eq(target_versions)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when type is not current nor target' do
|
95
|
+
it 'raises an exception' do
|
96
|
+
expect { changelog.versions(lock_current['cookbook_locks'], 'toto') }.to raise_error(RuntimeError)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when cookbooks locks are empty or nil' do
|
101
|
+
it 'raises an exception' do
|
102
|
+
expect { changelog.versions({}, 'current') }.to raise_error(RuntimeError)
|
103
|
+
expect { changelog.versions(nil, 'current') }.to raise_error(RuntimeError)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#get_source_url' do
|
109
|
+
context 'when extracting source url' do
|
110
|
+
it 'returns an http url for supermarket' do
|
111
|
+
supermarket_source = { 'artifactserver' => 'https://url.example/cookbook/name/versions/3.5.0/download' }
|
112
|
+
allow(changelog).to receive(:supermarket_source_url).and_return('https://url.example')
|
113
|
+
expect(changelog.get_source_url(supermarket_source)['source_url'])
|
114
|
+
.to match(%r{^(http|https):\/\/.+$})
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'raises exception for invalid supermarket url' do
|
118
|
+
bad_supermarket_source = { 'artifactserver' => 'https://url.example' }
|
119
|
+
expect { changelog.get_source_url(bad_supermarket_source)['source_url'] }
|
120
|
+
.to raise_error(ArgumentError)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'returns a git repo url for git' do
|
124
|
+
git_source = { 'git' => 'https://url.example.git' }
|
125
|
+
expect(changelog.get_source_url(git_source)['source_url'])
|
126
|
+
.to match(%r{^(http|https):\/\/.+\.git$})
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#supermarket_source_url' do
|
132
|
+
context 'when response not empty' do
|
133
|
+
it 'returns valid git repository url' do
|
134
|
+
expect(changelog.supermarket_source_url(url)).to match(%r{^(http|https):\/\/.+\.git$})
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'when cookbook does not exist' do
|
139
|
+
it 'raises an error' do
|
140
|
+
response = '{ "error_messages":["Resource does not exist."],"error_code":"NOT_FOUND" }'
|
141
|
+
stub_request(:get, url).to_return(status: 404, body: response)
|
142
|
+
expect { changelog.supermarket_source_url(url) }.to raise_error(RestClient::NotFound)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#git_changelog' do
|
148
|
+
let(:git) { Git }
|
149
|
+
|
150
|
+
let(:git_repo) { double(Git::Base.new) }
|
151
|
+
|
152
|
+
let(:git_commit) do
|
153
|
+
double(
|
154
|
+
sha: 'e1b971a32f3a582766e4f62022ef7ed88e5eb8ba',
|
155
|
+
message: "Add test commit message\nThis line should not be shown"
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'when given two tags' do
|
160
|
+
it 'generates a changelog between two tags' do
|
161
|
+
allow(changelog).to receive(:tag_format).and_return('v')
|
162
|
+
allow(git).to receive(:clone).and_return(git_repo)
|
163
|
+
allow(changelog).to receive(:correct_tags)
|
164
|
+
.and_return(['v1.0.0', 'v1.0.1'])
|
165
|
+
allow(git_repo).to receive_message_chain(:log, :between)
|
166
|
+
.with('v1.0.0', 'v1.0.1')
|
167
|
+
.and_return([git_commit])
|
168
|
+
|
169
|
+
expect(changelog.git_changelog('https://url.example.git', '1.0.0', '1.0.1'))
|
170
|
+
.to eq('e1b971a Add test commit message')
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe '#git_tag' do
|
176
|
+
let(:repo) { double('repo') }
|
177
|
+
|
178
|
+
context 'when tag valid' do
|
179
|
+
it 'returns correct git tag' do
|
180
|
+
allow(repo).to receive(:checkout).with('1.0.0').and_return(true)
|
181
|
+
|
182
|
+
expect(changelog.git_tag('1.0.0', repo)).to eq('1.0.0')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context 'when tag invalid and able to correct' do
|
187
|
+
it 'returns correct git tag' do
|
188
|
+
allow(repo).to receive(:checkout).with('1.0.0').and_raise(::Git::GitExecuteError)
|
189
|
+
allow(repo).to receive(:checkout).with('1.0').and_return(true)
|
190
|
+
|
191
|
+
expect(changelog.git_tag('1.0.0', repo)).to eq('1.0')
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'when tags invalid and unable to correct' do
|
196
|
+
it 'raises exception' do
|
197
|
+
allow(repo).to receive(:checkout).with('1.0.0').and_raise(::Git::GitExecuteError)
|
198
|
+
allow(repo).to receive(:checkout).with('1.0').and_raise(::Git::GitExecuteError)
|
199
|
+
|
200
|
+
expect { changelog.git_tag('1.0.0', repo) }
|
201
|
+
.to raise_error(RuntimeError, 'Difference between Git and Supermarket tags')
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe '#tag_format' do
|
207
|
+
context 'when it receives a tag' do
|
208
|
+
let(:repo) { Git::Base }
|
209
|
+
|
210
|
+
it 'detects type for regular tag' do
|
211
|
+
allow(repo).to receive_message_chain(:tags, :last, :name).and_return('1.0.0')
|
212
|
+
expect(changelog.tag_format(repo)).to eq('')
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'detects type for v-tag' do
|
216
|
+
allow(repo).to receive_message_chain(:tags, :last, :name).and_return('v1.0.0')
|
217
|
+
expect(changelog.tag_format(repo)).to eq('v')
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe '#reject_version_filter' do
|
223
|
+
context 'when current equal to target' do
|
224
|
+
it 'returns true' do
|
225
|
+
data = { 'current_version' => '1.0.0', 'target_version' => '1.0.0' }
|
226
|
+
expect(changelog.reject_version_filter(data)).to be true
|
227
|
+
end
|
228
|
+
end
|
229
|
+
context 'when current not equal to target' do
|
230
|
+
it 'returns false' do
|
231
|
+
data = { 'current_version' => '1.0.0', 'target_version' => '1.0.1' }
|
232
|
+
expect(changelog.reject_version_filter(data)).to be false
|
233
|
+
end
|
234
|
+
end
|
235
|
+
context 'when current or target do not exist' do
|
236
|
+
it 'returns true' do
|
237
|
+
expect(changelog.reject_version_filter('target_version' => '1.0.0')).to be true
|
238
|
+
expect(changelog.reject_version_filter('current_version' => '1.0.0')).to be true
|
239
|
+
end
|
240
|
+
end
|
241
|
+
context 'when data is nil' do
|
242
|
+
it 'raises an exception' do
|
243
|
+
expect { changelog.reject_version_filter(nil) }.to raise_error
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
describe '#generate_changelog' do
|
249
|
+
context 'when generating a changelog' do
|
250
|
+
it 'detects type for regular tag' do
|
251
|
+
allow(changelog).to receive(:update_policyfile_lock)
|
252
|
+
.and_return(tmp_dir)
|
253
|
+
allow(changelog).to receive(:git_changelog)
|
254
|
+
.and_return('e1b971a Add test commit message')
|
255
|
+
|
256
|
+
expect { changelog.generate_changelog }.not_to raise_error(RuntimeError)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-changelog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregoire Seux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,13 +95,13 @@ dependencies:
|
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: berkshelf
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: '0'
|
90
|
-
type: :
|
104
|
+
type: :runtime
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
@@ -95,7 +109,7 @@ dependencies:
|
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: chef
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
@@ -109,7 +123,7 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: chef-dk
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - ">="
|
@@ -123,7 +137,7 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: deep_merge
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - ">="
|
@@ -137,7 +151,7 @@ dependencies:
|
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
154
|
+
name: git
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
157
|
- - ">="
|
@@ -151,7 +165,21 @@ dependencies:
|
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
168
|
+
name: mixlib-shellout
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rest-client
|
155
183
|
requirement: !ruby/object:Gem::Requirement
|
156
184
|
requirements:
|
157
185
|
- - ">="
|
@@ -183,16 +211,18 @@ files:
|
|
183
211
|
- lib/knife/changelog/berksfile.rb
|
184
212
|
- lib/knife/changelog/changelog.rb
|
185
213
|
- lib/knife/changelog/git.rb
|
186
|
-
- lib/knife/changelog/policyfile.rb
|
187
214
|
- lib/knife/changelog/version.rb
|
215
|
+
- lib/policyfile.rb
|
188
216
|
- resources/Berksfile
|
189
217
|
- resources/Berksfile.lock
|
190
218
|
- spec/data/Berksfile
|
191
219
|
- spec/data/Berksfile.lock
|
192
220
|
- spec/data/Policyfile.lock.json
|
193
221
|
- spec/data/Policyfile.rb
|
222
|
+
- spec/data/tmp_dir/Policyfile.lock.json
|
194
223
|
- spec/spec_helper.rb
|
195
224
|
- spec/unit/changelog_spec.rb
|
225
|
+
- spec/unit/policyfile_spec.rb
|
196
226
|
homepage: https://github.com/kamaradclimber/knife-changelog
|
197
227
|
licenses:
|
198
228
|
- MIT
|
@@ -213,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
213
243
|
version: '0'
|
214
244
|
requirements: []
|
215
245
|
rubyforge_project:
|
216
|
-
rubygems_version: 2.7.
|
246
|
+
rubygems_version: 2.7.4
|
217
247
|
signing_key:
|
218
248
|
specification_version: 4
|
219
249
|
summary: Facilitate access to cookbooks changelog
|
@@ -222,5 +252,7 @@ test_files:
|
|
222
252
|
- spec/data/Berksfile.lock
|
223
253
|
- spec/data/Policyfile.lock.json
|
224
254
|
- spec/data/Policyfile.rb
|
255
|
+
- spec/data/tmp_dir/Policyfile.lock.json
|
225
256
|
- spec/spec_helper.rb
|
226
257
|
- spec/unit/changelog_spec.rb
|
258
|
+
- spec/unit/policyfile_spec.rb
|
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'changelog'
|
4
|
-
|
5
|
-
class KnifeChangelog
|
6
|
-
class Changelog
|
7
|
-
class Policyfile < Changelog
|
8
|
-
attr_reader :policy, :lock
|
9
|
-
|
10
|
-
def initialize(policyfile_path, config)
|
11
|
-
require 'chef-dk'
|
12
|
-
require 'chef-dk/policyfile_compiler'
|
13
|
-
lock_path = policyfile_path.gsub(/.rb$/, '.lock.json')
|
14
|
-
@policy = ChefDK::PolicyfileCompiler.evaluate(File.read(policyfile_path), policyfile_path)
|
15
|
-
@lock = ChefDK::PolicyfileLock.new(policy.storage_config).build_from_lock_data(JSON.parse(File.read(lock_path)))
|
16
|
-
super(config)
|
17
|
-
end
|
18
|
-
|
19
|
-
def all_cookbooks
|
20
|
-
policy.solution_dependencies.cookbook_deps_for_lock.map { |k, v| k.scan(/(.*) \(.*\)/).last.first }
|
21
|
-
end
|
22
|
-
|
23
|
-
# return true if cookbook is not already listed as dependency
|
24
|
-
def new_cookbook?(name)
|
25
|
-
policy.send(:best_source_for, name).nil?
|
26
|
-
end
|
27
|
-
|
28
|
-
# return true if cookbook is downloaded from supermarket
|
29
|
-
def supermarket?(name)
|
30
|
-
# it's hard to get location_specs for supermarket cookbooks without having policy_compiler starting to download all cookbooks
|
31
|
-
# in the meantime, we procede by elimination
|
32
|
-
!(git?(name) || local?(name))
|
33
|
-
end
|
34
|
-
|
35
|
-
def guess_version_for(name)
|
36
|
-
lock.solution_dependencies.cookbook_dependencies.keys.find { |dep| dep.name == name }.version
|
37
|
-
end
|
38
|
-
|
39
|
-
# return true if cookbook is downloaded from git
|
40
|
-
def git?(name)
|
41
|
-
# cookbook_location_specs contains only cookbooks refered via git and path
|
42
|
-
policy.cookbook_location_specs[name] && policy.cookbook_location_specs[name].source_type == :git
|
43
|
-
end
|
44
|
-
|
45
|
-
# return true if cookbook is downloaded from local path
|
46
|
-
def local?(name)
|
47
|
-
# cookbook_location_specs contains only cookbooks refered via git and path
|
48
|
-
policy.cookbook_location_specs[name] && policy.cookbook_location_specs[name].source_type.nil?
|
49
|
-
end
|
50
|
-
|
51
|
-
# return a Changelog::Location for a given cookbook
|
52
|
-
def git_location(name)
|
53
|
-
return nil unless git?(name)
|
54
|
-
spec = lock.cookbook_locks[name].source_options
|
55
|
-
Location.new(spec[:git], spec[:revision], spec[:branch])
|
56
|
-
end
|
57
|
-
|
58
|
-
def update(cookbooks)
|
59
|
-
raise NotImplementedError
|
60
|
-
end
|
61
|
-
|
62
|
-
# return a list of supermarket uri for a given cookbook
|
63
|
-
# example: [ 'https://supermarket.chef.io' ]
|
64
|
-
def supermarkets_for(name)
|
65
|
-
[policy.send(:best_source_for, name).uri]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|