knife-changelog 1.0.6 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|