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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33f9c5c8b0d5cec6a862af4f16c6ba10ad50d0ec63d52c66ae6f78ad57e5edf5
4
- data.tar.gz: 9122a7dc32a956d2301799efddbabe6f90f581c3d03b7bf4e9baea94aca7a3ec
3
+ metadata.gz: 411909df80e256eb6bd9e979757fec2380c12af929364ab6c5dc950e0ae1ad4c
4
+ data.tar.gz: acd53e149eed37830e7a8f1ab43f6ce43f457bce96ec0a721797a08626365dcd
5
5
  SHA512:
6
- metadata.gz: bbe30f69038cacfc6da33eb097122daea229c01532a579100c47a21e3f97bd20c449f070164457f82433df42f3bd6bbdfdd76f8425375e9336145d7d64941801
7
- data.tar.gz: b568f75c320ba3e6016d1e2cfa72d8d81489e2764c8e8d763c8833aa3681f73bf7085bd3c6d93c14ec3c503f54164c0e62646093e34a8a5961ed2e7f98bace7b
6
+ metadata.gz: 83f46649c2d333d411f6d0f6207fabd62c6c591253288df58473cd1e70f16d96f280b6693c70bc512f77d5aa1971a942cb961c9d4721b6dafefd61829ac67d7e
7
+ data.tar.gz: e5f843bfd021fd395c882f306caf9f716a9f1c11b95375a85fc399fb6f6a48114a2b7e75c22a6a7ca5080b2ffd9d76cf04a2ef863553f96e8fe8cced18e9c147
@@ -5,7 +5,7 @@ jobs:
5
5
  runs-on: ubuntu-latest
6
6
  strategy:
7
7
  matrix:
8
- ruby-version: ['2.5', '2.7']
8
+ ruby-version: ['3.1']
9
9
  steps:
10
10
  - uses: actions/checkout@v2
11
11
  - uses: ruby/setup-ruby@v1
@@ -9,7 +9,7 @@ jobs:
9
9
  - uses: actions/checkout@v2
10
10
  - uses: ruby/setup-ruby@v1
11
11
  with:
12
- ruby-version: 2.7
12
+ ruby-version: 3.1
13
13
  - name: Build
14
14
  run: gem build *.gemspec
15
15
  - name: Push on Rubygems
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
-
5
- gem 'chef', '14.7.17' # Pin for now as recent Chef version does not provide knife
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 or classical repositories with a Berksfile
18
+ This plugin works in policyfile style repositories
19
19
 
20
20
  ## Todos
21
21
 
@@ -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 = '2.0.0'
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
@@ -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
- if config[:policyfile] && File.exist?(config[:policyfile])
69
- puts PolicyChangelog.new(
70
- @name_args,
71
- config[:policyfile],
72
- config[:with_dependencies]
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
@@ -147,7 +147,7 @@ class PolicyChangelog
147
147
  existing_ref = possible_refs.find do |ref|
148
148
  begin
149
149
  repo.checkout(ref)
150
- rescue ::Git::GitExecuteError
150
+ rescue ::Git::Error
151
151
  false
152
152
  end
153
153
  end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'knife/changelog/changelog'
4
- require 'knife/changelog/berksfile'
5
3
  require 'knife/changelog/policyfile'
6
4
 
5
+ require 'rexml/document'
7
6
  require 'webmock/rspec'
8
7
 
9
8
  WebMock.disable_net_connect!(allow_localhost: true)
@@ -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::GitExecuteError)
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::GitExecuteError)
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::GitExecuteError)
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::GitExecuteError)
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: 2.0.0
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: 2022-09-06 00:00:00.000000000 Z
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: berkshelf
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: chef-cli
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: deep_merge
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: git
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.1.6
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
@@ -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
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://mysupermarket.io'
4
- source 'https://mysupermarket2.io'
5
-
6
- cookbook 'uptodate'
7
- cookbook 'outdated1'
8
- cookbook 'second_out_of_date'
9
- cookbook 'othercookbook'
@@ -1,11 +0,0 @@
1
- DEPENDENCIES
2
- othercookbook
3
- outdated1
4
- second_out_of_date
5
- uptodate
6
-
7
- GRAPH
8
- othercookbook (1.0.0)
9
- outdated1 (1.0.0)
10
- second_out_of_date (1.0.0)
11
- uptodate (1.0.0)
@@ -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