knife-changelog 2.0.0 → 4.0.0

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