knife-changelog 2.0.0 → 4.0.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/.github/workflows/ci.yml +1 -1
- data/.github/workflows/release.yml +1 -1
- data/Gemfile +0 -2
- data/README.md +1 -1
- data/knife-changelog.gemspec +4 -2
- data/lib/chef/knife/changelog.rb +5 -46
- data/lib/knife/changelog/policyfile.rb +1 -1
- data/spec/spec_helper.rb +1 -2
- data/spec/unit/policyfile_spec.rb +5 -34
- metadata +9 -19
- data/lib/knife/changelog/berksfile.rb +0 -68
- data/lib/knife/changelog/changelog.rb +0 -267
- data/lib/knife/changelog/git.rb +0 -46
- data/lib/knife/changelog/git_submodule.rb +0 -18
- data/spec/data/Berksfile +0 -9
- data/spec/data/Berksfile.lock +0 -11
- data/spec/unit/changelog_spec.rb +0 -125
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 411909df80e256eb6bd9e979757fec2380c12af929364ab6c5dc950e0ae1ad4c
|
4
|
+
data.tar.gz: acd53e149eed37830e7a8f1ab43f6ce43f457bce96ec0a721797a08626365dcd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83f46649c2d333d411f6d0f6207fabd62c6c591253288df58473cd1e70f16d96f280b6693c70bc512f77d5aa1971a942cb961c9d4721b6dafefd61829ac67d7e
|
7
|
+
data.tar.gz: e5f843bfd021fd395c882f306caf9f716a9f1c11b95375a85fc399fb6f6a48114a2b7e75c22a6a7ca5080b2ffd9d76cf04a2ef863553f96e8fe8cced18e9c147
|
data/.github/workflows/ci.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -15,7 +15,7 @@ Options:
|
|
15
15
|
- generate changelogs for some supermarket hosted cookbooks
|
16
16
|
- generate changelogs for all git located cookbooks
|
17
17
|
|
18
|
-
This plugin works in policyfile style repositories
|
18
|
+
This plugin works in policyfile style repositories
|
19
19
|
|
20
20
|
## Todos
|
21
21
|
|
data/knife-changelog.gemspec
CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'knife-changelog'
|
8
|
-
spec.version = '
|
8
|
+
spec.version = '4.0.0'
|
9
9
|
spec.authors = ['Gregoire Seux']
|
10
10
|
spec.email = ['kamaradclimber@gmail.com']
|
11
11
|
spec.summary = 'Facilitate access to cookbooks changelog'
|
@@ -13,6 +13,8 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = 'https://github.com/kamaradclimber/knife-changelog'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
|
+
spec.required_ruby_version = '>= 3.0'
|
17
|
+
|
16
18
|
spec.files = `git ls-files -z`.split("\x0")
|
17
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
@@ -24,11 +26,11 @@ Gem::Specification.new do |spec|
|
|
24
26
|
spec.add_development_dependency 'rubocop'
|
25
27
|
spec.add_development_dependency 'webmock'
|
26
28
|
|
27
|
-
spec.add_dependency 'berkshelf'
|
28
29
|
spec.add_dependency 'chef'
|
29
30
|
spec.add_dependency 'chef-cli'
|
30
31
|
spec.add_dependency 'deep_merge'
|
31
32
|
spec.add_dependency 'git'
|
33
|
+
spec.add_dependency 'knife'
|
32
34
|
spec.add_dependency 'mixlib-shellout'
|
33
35
|
spec.add_dependency 'rest-client'
|
34
36
|
end
|
data/lib/chef/knife/changelog.rb
CHANGED
@@ -9,39 +9,9 @@ class Chef
|
|
9
9
|
banner 'knife changelog COOKBOOK [COOKBOOK ...]'
|
10
10
|
|
11
11
|
deps do
|
12
|
-
require 'knife/changelog/changelog'
|
13
|
-
require 'knife/changelog/berksfile'
|
14
|
-
require 'berkshelf'
|
15
12
|
require 'knife/changelog/policyfile'
|
16
13
|
end
|
17
14
|
|
18
|
-
option :linkify,
|
19
|
-
short: '-l',
|
20
|
-
long: '--linkify',
|
21
|
-
description: 'add markdown links where relevant',
|
22
|
-
boolean: true
|
23
|
-
|
24
|
-
option :markdown,
|
25
|
-
short: '-m',
|
26
|
-
long: '--markdown',
|
27
|
-
description: 'use markdown syntax',
|
28
|
-
boolean: true
|
29
|
-
|
30
|
-
option :ignore_changelog_file,
|
31
|
-
long: '--ignore-changelog-file',
|
32
|
-
description: 'Ignore changelog file presence, use git history instead',
|
33
|
-
boolean: true
|
34
|
-
|
35
|
-
option :allow_update_all,
|
36
|
-
long: '--allow-update-all',
|
37
|
-
description: 'If no cookbook given, check all Berksfile',
|
38
|
-
boolean: true,
|
39
|
-
default: true
|
40
|
-
|
41
|
-
option :submodules,
|
42
|
-
long: '--submodules SUBMODULE[,SUBMODULE]',
|
43
|
-
description: 'Submoduless to check for changes as well (comma separated)'
|
44
|
-
|
45
15
|
option :prevent_downgrade,
|
46
16
|
long: '--prevent-downgrade',
|
47
17
|
description: 'Fail if knife-changelog detect a cookbook downgrade',
|
@@ -59,24 +29,13 @@ class Chef
|
|
59
29
|
boolean: true,
|
60
30
|
default: false
|
61
31
|
|
62
|
-
option :update,
|
63
|
-
long: '--update',
|
64
|
-
description: 'Update Berksfile'
|
65
|
-
|
66
32
|
def run
|
67
33
|
Log.info config.to_s
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
).generate_changelog
|
74
|
-
else
|
75
|
-
berksfile = Berkshelf::Berksfile.from_options({})
|
76
|
-
puts KnifeChangelog::Changelog::Berksfile
|
77
|
-
.new(berksfile, config)
|
78
|
-
.run(@name_args)
|
79
|
-
end
|
34
|
+
puts PolicyChangelog.new(
|
35
|
+
@name_args,
|
36
|
+
config[:policyfile],
|
37
|
+
config[:with_dependencies]
|
38
|
+
).generate_changelog(config[:prevent_downgrade])
|
80
39
|
end
|
81
40
|
end
|
82
41
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -92,35 +92,6 @@ RSpec.describe PolicyChangelog do
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
-
describe '#linkify' do
|
96
|
-
subject { KnifeChangelog::Changelog.new(config) }
|
97
|
-
let(:config) { double('config') }
|
98
|
-
let(:changelog) do
|
99
|
-
['9363423 Leverage criteo-flavor 3.11 to benefit from labels']
|
100
|
-
end
|
101
|
-
context 'when url is gitlab style' do
|
102
|
-
let(:url) { 'https://gitlab.com/chef-cookbooks/criteo-rackguru.git' }
|
103
|
-
|
104
|
-
it 'creates a gitlab style link' do
|
105
|
-
expect(subject.linkify(url, changelog).first).to match(%r{https://gitlab.com/chef-cookbooks/criteo-rackguru/commit/9363423})
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'when url is github style' do
|
110
|
-
let(:url) { 'https://github.com/chef-cookbooks/criteo-rackguru.git' }
|
111
|
-
it 'creates a github style link' do
|
112
|
-
expect(subject.linkify(url, changelog).first).to match(%r{https://github.com/chef-cookbooks/criteo-rackguru/commit/9363423})
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
context 'when url has no known style' do
|
117
|
-
let(:url) { 'https://review.mycompany.com/chef-cookbooks/criteo-rackguru.git' }
|
118
|
-
it 'creates a gerrit style link' do
|
119
|
-
expect(subject.linkify(url, changelog).first).to match(%r{https://review.mycompany.com/#/q/9363423})
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
95
|
describe '#versions' do
|
125
96
|
context 'when type is current' do
|
126
97
|
it 'returns correct current versions' do
|
@@ -229,7 +200,7 @@ RSpec.describe PolicyChangelog do
|
|
229
200
|
|
230
201
|
context 'when tag valid' do
|
231
202
|
it 'returns correct git tag' do
|
232
|
-
allow(repo).to receive(:checkout).with('v1.0.0').and_raise(::Git::
|
203
|
+
allow(repo).to receive(:checkout).with('v1.0.0').and_raise(::Git::Error)
|
233
204
|
allow(repo).to receive(:checkout).with('1.0.0').and_return(true)
|
234
205
|
|
235
206
|
expect(changelog.git_ref('1.0.0', repo)).to eq('1.0.0')
|
@@ -238,13 +209,13 @@ RSpec.describe PolicyChangelog do
|
|
238
209
|
|
239
210
|
context 'when tag invalid and able to correct' do
|
240
211
|
it 'returns correct git tag' do
|
241
|
-
allow(repo).to receive(:checkout).with('1.0.0').and_raise(::Git::
|
212
|
+
allow(repo).to receive(:checkout).with('1.0.0').and_raise(::Git::Error)
|
242
213
|
|
243
214
|
tags = %w[v1.0.0 1.0 v1.0 cookbook_name-1.0.0 cookbook_name-1.0 cookbook_name-v1.0.0 cookbook_name-v1.0]
|
244
215
|
tags.each do |valid_result|
|
245
216
|
allow(repo).to receive(:checkout).with(valid_result).and_return(true)
|
246
217
|
tags.reject { |v| v == valid_result }.each do |invalid_result|
|
247
|
-
allow(repo).to receive(:checkout).with(invalid_result).and_raise(::Git::
|
218
|
+
allow(repo).to receive(:checkout).with(invalid_result).and_raise(::Git::Error)
|
248
219
|
end
|
249
220
|
expect(changelog.git_ref('1.0.0', repo, 'cookbook_name')).to eq valid_result
|
250
221
|
end
|
@@ -254,7 +225,7 @@ RSpec.describe PolicyChangelog do
|
|
254
225
|
context 'when tags invalid and unable to correct' do
|
255
226
|
it 'raises exception' do
|
256
227
|
allow(repo).to receive(:remote).and_return(double('remote', url: 'url.com'))
|
257
|
-
allow(repo).to receive(:checkout).with(any_args).and_raise(::Git::
|
228
|
+
allow(repo).to receive(:checkout).with(any_args).and_raise(::Git::Error)
|
258
229
|
|
259
230
|
expect { changelog.git_ref('1.0.0', repo) }
|
260
231
|
.to raise_error(RuntimeError, /Impossible to find existing/)
|
@@ -297,7 +268,7 @@ RSpec.describe PolicyChangelog do
|
|
297
268
|
end
|
298
269
|
context 'when data is nil' do
|
299
270
|
it 'raises an exception' do
|
300
|
-
expect { changelog.reject_version_filter(nil) }.to raise_error
|
271
|
+
expect { changelog.reject_version_filter(nil) }.to raise_error(RuntimeError)
|
301
272
|
end
|
302
273
|
end
|
303
274
|
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:
|
4
|
+
version: 4.0.0
|
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: 2024-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: chef
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name: chef
|
98
|
+
name: chef-cli
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: deep_merge
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: git
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - ">="
|
@@ -137,7 +137,7 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: knife
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - ">="
|
@@ -195,22 +195,15 @@ files:
|
|
195
195
|
- Rakefile
|
196
196
|
- knife-changelog.gemspec
|
197
197
|
- lib/chef/knife/changelog.rb
|
198
|
-
- lib/knife/changelog/berksfile.rb
|
199
|
-
- lib/knife/changelog/changelog.rb
|
200
|
-
- lib/knife/changelog/git.rb
|
201
|
-
- lib/knife/changelog/git_submodule.rb
|
202
198
|
- lib/knife/changelog/policyfile.rb
|
203
199
|
- resources/Berksfile
|
204
200
|
- resources/Berksfile.lock
|
205
|
-
- spec/data/Berksfile
|
206
|
-
- spec/data/Berksfile.lock
|
207
201
|
- spec/data/Policyfile.lock.json
|
208
202
|
- spec/data/Policyfile.rb
|
209
203
|
- spec/data/Policyfile_git.lock.json
|
210
204
|
- spec/data/Policyfile_git.rb
|
211
205
|
- spec/data/updated/Policyfile.lock.json
|
212
206
|
- spec/spec_helper.rb
|
213
|
-
- spec/unit/changelog_spec.rb
|
214
207
|
- spec/unit/policyfile_spec.rb
|
215
208
|
homepage: https://github.com/kamaradclimber/knife-changelog
|
216
209
|
licenses:
|
@@ -224,25 +217,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
224
217
|
requirements:
|
225
218
|
- - ">="
|
226
219
|
- !ruby/object:Gem::Version
|
227
|
-
version: '0'
|
220
|
+
version: '3.0'
|
228
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
229
222
|
requirements:
|
230
223
|
- - ">="
|
231
224
|
- !ruby/object:Gem::Version
|
232
225
|
version: '0'
|
233
226
|
requirements: []
|
234
|
-
rubygems_version: 3.
|
227
|
+
rubygems_version: 3.3.27
|
235
228
|
signing_key:
|
236
229
|
specification_version: 4
|
237
230
|
summary: Facilitate access to cookbooks changelog
|
238
231
|
test_files:
|
239
|
-
- spec/data/Berksfile
|
240
|
-
- spec/data/Berksfile.lock
|
241
232
|
- spec/data/Policyfile.lock.json
|
242
233
|
- spec/data/Policyfile.rb
|
243
234
|
- spec/data/Policyfile_git.lock.json
|
244
235
|
- spec/data/Policyfile_git.rb
|
245
236
|
- spec/data/updated/Policyfile.lock.json
|
246
237
|
- spec/spec_helper.rb
|
247
|
-
- spec/unit/changelog_spec.rb
|
248
238
|
- spec/unit/policyfile_spec.rb
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'changelog'
|
4
|
-
|
5
|
-
class KnifeChangelog
|
6
|
-
class Changelog
|
7
|
-
class Berksfile < Changelog
|
8
|
-
def initialize(berksfile, config)
|
9
|
-
require 'berkshelf'
|
10
|
-
@locked_versions = berksfile.lockfile.locks
|
11
|
-
@sources = berksfile.sources
|
12
|
-
@berksfile = berksfile
|
13
|
-
super(config)
|
14
|
-
end
|
15
|
-
|
16
|
-
def all_cookbooks
|
17
|
-
@locked_versions.keys
|
18
|
-
end
|
19
|
-
|
20
|
-
def new_cookbook?(name)
|
21
|
-
ck_dep(name).nil?
|
22
|
-
end
|
23
|
-
|
24
|
-
# return true if cookbook is downloaded from supermarket
|
25
|
-
def supermarket?(name)
|
26
|
-
# here is berkshelf "expressive" way to say cookbook
|
27
|
-
# comes from supermarket
|
28
|
-
ck_dep(name).location.is_a?(NilClass)
|
29
|
-
end
|
30
|
-
|
31
|
-
# return true if cookbook is downloaded from git
|
32
|
-
def git?(name)
|
33
|
-
ck_dep(name).location.is_a?(Berkshelf::GitLocation)
|
34
|
-
end
|
35
|
-
|
36
|
-
# return true if cookbook is downloaded from local path
|
37
|
-
def local?(name)
|
38
|
-
ck_dep(name).location.is_a?(Berkshelf::PathLocation)
|
39
|
-
end
|
40
|
-
|
41
|
-
# return a Changelog::Location for this cookbook
|
42
|
-
def git_location(name)
|
43
|
-
raise "#{name} has not a git location" unless git?(name)
|
44
|
-
Location.from_berk_git_location(ck_dep(name).location)
|
45
|
-
end
|
46
|
-
|
47
|
-
# return a list of supermarket uri for a given cookbook
|
48
|
-
# example: [ 'https://supermarket.chef.io' ]
|
49
|
-
def supermarkets_for(_name)
|
50
|
-
@sources.map(&:uri)
|
51
|
-
end
|
52
|
-
|
53
|
-
def guess_version_for(name)
|
54
|
-
@locked_versions[name].locked_version.to_s
|
55
|
-
end
|
56
|
-
|
57
|
-
def update(cookbooks)
|
58
|
-
@berksfile.update(*cookbooks)
|
59
|
-
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def ck_dep(name)
|
64
|
-
@locked_versions[name]
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,267 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
require 'chef/log'
|
3
|
-
require 'chef/knife'
|
4
|
-
require 'chef/version_class'
|
5
|
-
require 'rest-client'
|
6
|
-
require 'json'
|
7
|
-
require_relative 'git'
|
8
|
-
|
9
|
-
class KnifeChangelog
|
10
|
-
class Changelog
|
11
|
-
|
12
|
-
Location = Struct.new(:uri, :revision, :rev_parse) do
|
13
|
-
# todo move this method to Changelog::Berkshelf
|
14
|
-
def self.from_berk_git_location(location)
|
15
|
-
Location.new(location.uri,
|
16
|
-
location.revision.strip,
|
17
|
-
location.instance_variable_get(:@rev_parse))
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(config = {})
|
22
|
-
@tmp_prefix = 'knife-changelog'
|
23
|
-
@config = config
|
24
|
-
@tmp_dirs = []
|
25
|
-
end
|
26
|
-
|
27
|
-
# returns a list of all cookbooks names
|
28
|
-
def all_cookbooks
|
29
|
-
raise NotImplementedError
|
30
|
-
end
|
31
|
-
|
32
|
-
# return true if cookbook is not already listed as dependency
|
33
|
-
def new_cookbook?(name)
|
34
|
-
raise NotImplementedError
|
35
|
-
end
|
36
|
-
|
37
|
-
# return true if cookbook is downloaded from supermarket
|
38
|
-
def supermarket?(name)
|
39
|
-
raise NotImplementedError
|
40
|
-
end
|
41
|
-
|
42
|
-
# return true if cookbook is downloaded from git
|
43
|
-
def git?(name)
|
44
|
-
raise NotImplementedError
|
45
|
-
end
|
46
|
-
|
47
|
-
# return true if cookbook is downloaded from local path
|
48
|
-
def local?(name)
|
49
|
-
raise NotImplementedError
|
50
|
-
end
|
51
|
-
|
52
|
-
# return a Changelog::Location for a given cookbook
|
53
|
-
def git_location(name)
|
54
|
-
raise NotImplementedError
|
55
|
-
end
|
56
|
-
|
57
|
-
# return a list of supermarket uri for a given cookbook
|
58
|
-
# example: [ 'https://supermarket.chef.io' ]
|
59
|
-
def supermarkets_for(name)
|
60
|
-
raise NotImplementedError
|
61
|
-
end
|
62
|
-
|
63
|
-
# return current locked version for a given cookbook
|
64
|
-
def guess_version_for(name)
|
65
|
-
raise NotImplementedError
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
def run(cookbooks)
|
71
|
-
changelog = []
|
72
|
-
begin
|
73
|
-
if cookbooks.empty? and @config[:allow_update_all]
|
74
|
-
cks = all_cookbooks
|
75
|
-
else
|
76
|
-
cks = cookbooks
|
77
|
-
end
|
78
|
-
changelog += cks.map do |cookbook|
|
79
|
-
Chef::Log.debug "Checking changelog for #{cookbook} (cookbook)"
|
80
|
-
execute cookbook
|
81
|
-
end
|
82
|
-
subs = @config[:submodules] || []
|
83
|
-
subs = subs.split(',') if subs.is_a? String
|
84
|
-
changelog += subs.map do |submodule|
|
85
|
-
Chef::Log.debug "Checking changelog for #{submodule} (submodule)"
|
86
|
-
execute(submodule, true)
|
87
|
-
end
|
88
|
-
update(cks) if @config[:update]
|
89
|
-
ensure
|
90
|
-
clean
|
91
|
-
end
|
92
|
-
changelog.compact.join("\n")
|
93
|
-
end
|
94
|
-
|
95
|
-
def clean
|
96
|
-
@tmp_dirs.each do |dir|
|
97
|
-
FileUtils.rm_rf dir
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def handle_new_cookbook
|
102
|
-
stars = '**' if @config[:markdown]
|
103
|
-
["#{stars}Cookbook was not in the berksfile#{stars}"]
|
104
|
-
end
|
105
|
-
|
106
|
-
def execute(name, submodule = false)
|
107
|
-
version_change, changelog = if submodule
|
108
|
-
handle_submodule(name)
|
109
|
-
elsif new_cookbook?(name)
|
110
|
-
['', handle_new_cookbook]
|
111
|
-
else
|
112
|
-
case true
|
113
|
-
when supermarket?(name)
|
114
|
-
handle_source(name)
|
115
|
-
when git?(name)
|
116
|
-
handle_git(name, git_location(name))
|
117
|
-
when local?(name)
|
118
|
-
Chef::Log.debug "path location are always at the last version"
|
119
|
-
['', '']
|
120
|
-
else
|
121
|
-
raise "Cannot handle #{loc.class} yet"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
format_changelog(name, version_change, changelog)
|
125
|
-
end
|
126
|
-
|
127
|
-
def format_changelog(name, version_change, changelog)
|
128
|
-
if changelog.empty?
|
129
|
-
nil
|
130
|
-
else
|
131
|
-
full = ["Changelog for #{name}: #{version_change}"]
|
132
|
-
full << '=' * full.first.size
|
133
|
-
full << changelog
|
134
|
-
full << ''
|
135
|
-
full.compact.join("\n")
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def get_from_supermarket_sources(name)
|
140
|
-
supermarkets_for(name).map do |uri|
|
141
|
-
begin
|
142
|
-
# TODO: we could call /universe endpoint once
|
143
|
-
# instead of calling /api/v1/cookbooks/ for each cookbook
|
144
|
-
RestClient::Request.execute(
|
145
|
-
url: "#{uri}/api/v1/cookbooks/#{name}",
|
146
|
-
method: :get,
|
147
|
-
verify_ssl: false # TODO make this configurable
|
148
|
-
)
|
149
|
-
rescue => e
|
150
|
-
Chef::Log.debug "Error fetching package from supermarket #{e.class.name} #{e.message}"
|
151
|
-
nil
|
152
|
-
end
|
153
|
-
end
|
154
|
-
.compact
|
155
|
-
.map { |json| JSON.parse(json) }
|
156
|
-
.sort_by { |ck| cookbook_highest_version(ck) }
|
157
|
-
.map { |ck| ck['source_url'] || ck ['external_url'] }
|
158
|
-
.last
|
159
|
-
.tap do |source|
|
160
|
-
raise "Cannot find any changelog source for #{name}" unless source
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def cookbook_highest_version(json)
|
165
|
-
json['versions']
|
166
|
-
.map { |version_url| Chef::Version.new(version_url.gsub(/.*\//, '')) }
|
167
|
-
.sort
|
168
|
-
.last
|
169
|
-
end
|
170
|
-
|
171
|
-
def handle_source(name)
|
172
|
-
url = get_from_supermarket_sources(name)
|
173
|
-
raise "No source found in supermarket for cookbook '#{name}'" unless url
|
174
|
-
Chef::Log.debug("Using #{url} as source url")
|
175
|
-
# Workaround source_url not being written in a clonable way.
|
176
|
-
# github.com/blah/cookbook works but git clone requires github.com/blah/cookbook.git
|
177
|
-
if !url.end_with?('.git')
|
178
|
-
url = "#{url}.git"
|
179
|
-
end
|
180
|
-
location = Location.new(url, guess_version_for(name), 'HEAD')
|
181
|
-
handle_git(name, location)
|
182
|
-
end
|
183
|
-
|
184
|
-
def detect_cur_revision(name, rev, git)
|
185
|
-
unless git.revision_exists?(rev)
|
186
|
-
prefixed_rev = 'v' + rev
|
187
|
-
return prefixed_rev if git.revision_exists?(prefixed_rev)
|
188
|
-
fail "#{rev} is not an existing revision (#{name}), not a tag/commit/branch name."
|
189
|
-
end
|
190
|
-
rev
|
191
|
-
end
|
192
|
-
|
193
|
-
def handle_submodule(name)
|
194
|
-
subm_url = Mixlib::ShellOut.new("git config --list| grep ^submodule | grep ^submodule.#{name}.url")
|
195
|
-
subm_url.run_command
|
196
|
-
subm_url.error!
|
197
|
-
url = subm_url.stdout.lines.first.split('=')[1].chomp
|
198
|
-
subm_revision = Mixlib::ShellOut.new("git submodule status #{name}")
|
199
|
-
subm_revision.run_command
|
200
|
-
subm_revision.error!
|
201
|
-
revision = subm_revision.stdout.strip.split(' ').first
|
202
|
-
revision.gsub!(/^\+/, '')
|
203
|
-
loc = Location.new(url, revision, 'HEAD')
|
204
|
-
handle_git(name, loc)
|
205
|
-
end
|
206
|
-
|
207
|
-
# take cookbook name and Changelog::Location instance
|
208
|
-
def handle_git(name, location)
|
209
|
-
# todo: remove this compat check
|
210
|
-
raise "should be a location" unless location.is_a?(Changelog::Location)
|
211
|
-
git = Git.new(@tmp_prefix, location.uri)
|
212
|
-
@tmp_dirs << git.shallow_clone
|
213
|
-
|
214
|
-
rev_parse = location.rev_parse
|
215
|
-
cur_rev = detect_cur_revision(name, location.revision, git)
|
216
|
-
changelog_file = git.files(rev_parse).find { |line| line =~ /\s(changelog.*$)/i }
|
217
|
-
changelog = if changelog_file and !@config[:ignore_changelog_file]
|
218
|
-
Chef::Log.info "Found changelog file : " + $1
|
219
|
-
generate_from_changelog_file($1, cur_rev, rev_parse, git)
|
220
|
-
end
|
221
|
-
changelog ||= generate_from_git_history(git, location, cur_rev, rev_parse)
|
222
|
-
["#{cur_rev}->#{rev_parse}", changelog]
|
223
|
-
end
|
224
|
-
|
225
|
-
def generate_from_changelog_file(filename, current_rev, rev_parse, git)
|
226
|
-
ch = git.diff(filename, current_rev, rev_parse)
|
227
|
-
.collect { |line| $1.strip if line =~ /^{\+(.*)\+}$/ }.compact
|
228
|
-
.map { |line| line.gsub(/^#+(.*)$/, "\\1\n---")} # replace section by smaller header
|
229
|
-
.select { |line| !(line =~ /^===+/)}.compact # remove header lines
|
230
|
-
ch.empty? ? nil : ch
|
231
|
-
end
|
232
|
-
|
233
|
-
def generate_from_git_history(git, location, current_rev, rev_parse)
|
234
|
-
c = git.log(current_rev, rev_parse)
|
235
|
-
n = https_url(location)
|
236
|
-
c = linkify(n, c) if @config[:linkify] and n
|
237
|
-
c = c.map { |line| "* " + line } if @config[:markdown]
|
238
|
-
c = c.map { |line| line.strip } # clean end of line
|
239
|
-
c
|
240
|
-
end
|
241
|
-
|
242
|
-
GERRIT_REGEXP = %r{^(.*)/[^/]+/[^/]+(?:\.git)$}
|
243
|
-
def linkify(url, changelog)
|
244
|
-
format = case url
|
245
|
-
when /gitlab/, /github/
|
246
|
-
"\\2 (#{url.chomp('.git')}/commit/\\1)"
|
247
|
-
when GERRIT_REGEXP
|
248
|
-
"\\2 (#{::Regexp.last_match(1)}/#/q/\\1)"
|
249
|
-
end
|
250
|
-
format ? changelog.map { |line| line.sub(/^([a-f0-9]+) (.*)$/, format) } : changelog
|
251
|
-
end
|
252
|
-
|
253
|
-
def https_url(location)
|
254
|
-
if location.uri =~ /^\w+:\/\/(.*@)?(.*)(\.git)?/
|
255
|
-
"https://%s" % [ $2 ]
|
256
|
-
else
|
257
|
-
fail "Cannot guess http url from git remote url: #{location.uri}"
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
def short(location)
|
262
|
-
if location.uri =~ /([\w-]+)\/([\w-]+)(\.git)?$/
|
263
|
-
"%s/%s" % [$1,$2]
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
data/lib/knife/changelog/git.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
class KnifeChangelog
|
2
|
-
class Git
|
3
|
-
attr_accessor :tmp_prefix, :uri
|
4
|
-
|
5
|
-
def initialize(tmp_prefix, uri)
|
6
|
-
@tmp_prefix = tmp_prefix
|
7
|
-
@uri = uri
|
8
|
-
end
|
9
|
-
|
10
|
-
def shallow_clone
|
11
|
-
Chef::Log.debug "Cloning #{uri} in #{tmp_prefix}"
|
12
|
-
dir = Dir.mktmpdir(tmp_prefix)
|
13
|
-
clone = Mixlib::ShellOut.new("git clone --bare #{uri} bare-clone", cwd: dir)
|
14
|
-
clone.run_command
|
15
|
-
clone.error!
|
16
|
-
@clone_dir = ::File.join(dir, 'bare-clone')
|
17
|
-
@clone_dir
|
18
|
-
end
|
19
|
-
|
20
|
-
def files(rev_parse)
|
21
|
-
ls_tree = Mixlib::ShellOut.new("git ls-tree -r #{rev_parse}", cwd: @clone_dir)
|
22
|
-
ls_tree.run_command
|
23
|
-
ls_tree.error!
|
24
|
-
ls_tree.stdout.lines.map(&:strip)
|
25
|
-
end
|
26
|
-
|
27
|
-
def diff(filename, current_rev, rev_parse)
|
28
|
-
diff = Mixlib::ShellOut.new("git diff #{current_rev}..#{rev_parse} --word-diff -- #{filename}", cwd: @clone_dir)
|
29
|
-
diff.run_command
|
30
|
-
diff.stdout.lines
|
31
|
-
end
|
32
|
-
|
33
|
-
def log(current_rev, rev_parse)
|
34
|
-
log = Mixlib::ShellOut.new("git log --no-merges --abbrev-commit --pretty=oneline #{current_rev}..#{rev_parse}", cwd: @clone_dir)
|
35
|
-
log.run_command
|
36
|
-
log.stdout.lines
|
37
|
-
end
|
38
|
-
|
39
|
-
def revision_exists?(revision)
|
40
|
-
Chef::Log.debug "Testing existence of #{revision}"
|
41
|
-
revlist = Mixlib::ShellOut.new("git rev-list --quiet #{revision}", cwd: @clone_dir)
|
42
|
-
revlist.run_command
|
43
|
-
!revlist.error?
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
require 'chef/log'
|
3
|
-
require_relative 'changelog'
|
4
|
-
|
5
|
-
class KnifeChangelog
|
6
|
-
class GitSubmodule < Changelog
|
7
|
-
|
8
|
-
def run(submodules)
|
9
|
-
raise ::ArgumentError, "Submodules must be an Array instead of #{submodules.inspect}" unless submodules.is_a?(::Array)
|
10
|
-
submodules.map do |submodule|
|
11
|
-
Chef::Log.debug "Checking changelog for #{submodule} (submodule)"
|
12
|
-
format_changelog(submodule, *handle_submodule(submodule))
|
13
|
-
end.compact.join("\n")
|
14
|
-
ensure
|
15
|
-
clean
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/spec/data/Berksfile
DELETED
data/spec/data/Berksfile.lock
DELETED
data/spec/unit/changelog_spec.rb
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'berkshelf'
|
4
|
-
require 'spec_helper'
|
5
|
-
|
6
|
-
RSpec.shared_examples 'changelog generation' do
|
7
|
-
# this supposes that "changelog" is an instance of KnifeChangelog::Changelog
|
8
|
-
it 'detects basic changelog' do
|
9
|
-
mock_git('second_out_of_date', <<-EOH)
|
10
|
-
aaaaaa commit in second_out_of_date
|
11
|
-
bbbbbb bugfix in second_out_of_date
|
12
|
-
EOH
|
13
|
-
mock_git('outdated1', <<-EOH)
|
14
|
-
aaaaaa commit in outdated1
|
15
|
-
bbbbbb bugfix in outdated1
|
16
|
-
EOH
|
17
|
-
mock_git('uptodate', '')
|
18
|
-
|
19
|
-
changelog_txt = changelog.run(%w[new_cookbook uptodate outdated1 second_out_of_date])
|
20
|
-
expect(changelog_txt).to match(/commit in outdated1/)
|
21
|
-
expect(changelog_txt).to match(/commit in second_out_of_date/)
|
22
|
-
expect(changelog_txt).not_to match(/uptodate/)
|
23
|
-
expect(changelog_txt).to match(/new_cookbook: \n.*\nCookbook was not/)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe KnifeChangelog::Changelog do
|
28
|
-
before(:each) do
|
29
|
-
stub_request(:get, %r{https://mysupermarket.io/api/v1/cookbooks/})
|
30
|
-
.to_return(status: 404, body: '{}')
|
31
|
-
|
32
|
-
mock_supermarket('uptodate', %w[1.0.0])
|
33
|
-
mock_supermarket('outdated1', %w[1.0.0 1.1.0])
|
34
|
-
# TODO: we should make second_out_of_date a git location
|
35
|
-
mock_supermarket('second_out_of_date', %w[1.0.0 1.2.0])
|
36
|
-
|
37
|
-
mock_universe('https://mysupermarket2.io', uptodate: %w[1.0.0], outdated1: %w[1.0.0 1.1.0], second_out_of_date: %w[1.0.0 1.2.0])
|
38
|
-
mock_universe('https://mysupermarket.io', {})
|
39
|
-
end
|
40
|
-
|
41
|
-
def mock_git(name, changelog)
|
42
|
-
expect(KnifeChangelog::Git).to receive(:new)
|
43
|
-
.with(anything, /#{name}(.git|$)/)
|
44
|
-
.and_return(double(name,
|
45
|
-
shallow_clone: '/tmp/randomdir12345',
|
46
|
-
revision_exists?: true,
|
47
|
-
files: [],
|
48
|
-
log: changelog.split("\n")))
|
49
|
-
end
|
50
|
-
|
51
|
-
def mock_supermarket(name, versions)
|
52
|
-
stub_request(:get, %r{https://mysupermarket2.io/api/v1/cookbooks/#{name}})
|
53
|
-
.to_return(status: 200, body: supermarket_versions(name, versions))
|
54
|
-
end
|
55
|
-
|
56
|
-
def supermarket_versions(name, versions)
|
57
|
-
{
|
58
|
-
name: name,
|
59
|
-
maintainer: 'Linus',
|
60
|
-
description: 'small project on the side',
|
61
|
-
category: 'Operating System',
|
62
|
-
source_url: "https://github.com/chef-cookbooks/#{name}",
|
63
|
-
versions: []
|
64
|
-
}.tap do |json|
|
65
|
-
versions.each do |v|
|
66
|
-
json[:versions] << "https://source.io/#{name}/#{v}"
|
67
|
-
end
|
68
|
-
end.to_json
|
69
|
-
end
|
70
|
-
|
71
|
-
def mock_universe(supermarket_url, cookbooks)
|
72
|
-
universe = cookbooks.transform_values do |versions|
|
73
|
-
versions.map do |v|
|
74
|
-
[v, {
|
75
|
-
location_type: 'opscode',
|
76
|
-
location_path: "#{supermarket_url}/api/v1",
|
77
|
-
download_url: "#{supermarket_url}/api/v1/cookbooks/insertnamehere/versions/#{v}/download",
|
78
|
-
dependencies: {}
|
79
|
-
}]
|
80
|
-
end.to_h
|
81
|
-
end
|
82
|
-
stub_request(:get, "#{supermarket_url}/universe")
|
83
|
-
.to_return(status: 200, body: universe.to_json)
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'in Berksfile mode' do
|
87
|
-
let(:berksfile) do
|
88
|
-
Berkshelf::Berksfile.from_options(
|
89
|
-
berksfile: File.join(File.dirname(__FILE__), '../data/Berksfile')
|
90
|
-
)
|
91
|
-
end
|
92
|
-
|
93
|
-
let(:options) do
|
94
|
-
{}
|
95
|
-
end
|
96
|
-
|
97
|
-
let(:changelog) do
|
98
|
-
KnifeChangelog::Changelog::Berksfile.new(berksfile, options)
|
99
|
-
end
|
100
|
-
|
101
|
-
include_examples 'changelog generation'
|
102
|
-
|
103
|
-
context 'with --update' do
|
104
|
-
let(:options) do
|
105
|
-
{ update: true }
|
106
|
-
end
|
107
|
-
it 'updates Berksfile' do
|
108
|
-
mock_git('outdated1', <<-EOH)
|
109
|
-
aaaaaa commit in outdated1
|
110
|
-
bbbbbb bugfix in outdated1
|
111
|
-
EOH
|
112
|
-
expect(berksfile).to receive(:update).with('outdated1')
|
113
|
-
changelog.run(%w[outdated1])
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
class Hash
|
120
|
-
unless Chef::Version.new(RUBY_VERSION) >= Chef::Version.new('2.4')
|
121
|
-
def transform_values
|
122
|
-
map { |k, v| [k, (yield v)] }.to_h
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|