knife-changelog 1.2.5 → 1.5.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: afbea7c14cdeabf23ea4f20db0af330eff3cad96f1239ded017e125182fb1ffb
4
- data.tar.gz: 7cb891e33b24d3d99c0822d509af3f2c50ae9fb40cb6dde74bf83c1b21fc5075
3
+ metadata.gz: ac82fb7552ead5bf08e8d7340883adab40185d5098c60ab3944472b3d51555b8
4
+ data.tar.gz: 22f9713b7df19b7a332a1a275e3a69db6dfa0d9d59abd815d7728c22b6d7c006
5
5
  SHA512:
6
- metadata.gz: 56b42d01d1246064e7d74812cbccb51be231aea9603a0364046a1dde153127d6ee0eb24bede748c6af660dc0131f4bd1b20858b3fc2b0057ac6e86206918c75f
7
- data.tar.gz: 1840e41083d1167cb803590b9151b543ed6df478d89e12a8ca81e921359eb6383ac340a847d87f99d91a91e17e2eefc5fd0bca338e970cd86a45cf6834045d1a
6
+ metadata.gz: 64bed7f1436c1d8536d479673d92d7749e7a8e9d16c271f81bbeac380c24b1f305300ff77bd4e17f7698746b2545b7773897923c7cb27dd68f6266f50ae5888a
7
+ data.tar.gz: e7939f44aefd0b409a9e5d2a12f7bdf1cd4ad9671c6ec906b1a650f51aaddb3cd72985ec3f220a5b8f96f532ddd1735d3bf7c9948927ac3905fc2f6dfb8e97c3
@@ -0,0 +1,15 @@
1
+ name: Tests
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ ruby-version: ['2.5', '2.7']
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: ${{ matrix.ruby-version }}
14
+ bundler-cache: true
15
+ - run: bundle exec rake
@@ -0,0 +1,18 @@
1
+ name: Release
2
+ on:
3
+ push:
4
+ tags: [ '*' ]
5
+ jobs:
6
+ release:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - uses: ruby/setup-ruby@v1
11
+ with:
12
+ ruby-version: 2.7
13
+ - run: |
14
+ install -D -m 600 <(echo -e "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}") $HOME/.gem/credentials
15
+ gem build *.gemspec
16
+ gem push *.gem
17
+ env:
18
+ RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
data/Rakefile CHANGED
@@ -1,9 +1,6 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
2
3
 
3
- begin
4
- require 'rspec/core/rake_task'
5
- RSpec::Core::RakeTask.new(:spec)
4
+ RSpec::Core::RakeTask.new(:spec)
6
5
 
7
- task :default => :spec
8
- rescue LoadError
9
- end
6
+ task default: :spec
@@ -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 = '1.2.5'
8
+ spec.version = '1.5.0'
9
9
  spec.authors = ['Gregoire Seux']
10
10
  spec.email = ['kamaradclimber@gmail.com']
11
11
  spec.summary = 'Facilitate access to cookbooks changelog'
@@ -18,7 +18,6 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.6'
22
21
  spec.add_development_dependency 'pry'
23
22
  spec.add_development_dependency 'rake'
24
23
  spec.add_development_dependency 'rspec'
@@ -42,6 +42,12 @@ class Chef
42
42
  long: '--submodules SUBMODULE[,SUBMODULE]',
43
43
  description: 'Submoduless to check for changes as well (comma separated)'
44
44
 
45
+ option :prevent_downgrade,
46
+ long: '--prevent-downgrade',
47
+ description: 'Fail if knife-changelog detect a cookbook downgrade',
48
+ boolean: true,
49
+ default: false
50
+
45
51
  option :policyfile,
46
52
  long: '--policyfile PATH',
47
53
  description: 'Link to policyfile, defaults to "Policyfile.rb"',
@@ -58,7 +64,7 @@ class Chef
58
64
  description: 'Update Berksfile'
59
65
 
60
66
  def run
61
- Log.info config
67
+ Log.info config.to_s
62
68
  if config[:policyfile] && File.exist?(config[:policyfile])
63
69
  puts PolicyChangelog.new(
64
70
  @name_args,
@@ -239,10 +239,15 @@ class KnifeChangelog
239
239
  c
240
240
  end
241
241
 
242
+ GERRIT_REGEXP = %r{^(.*)/[^/]+/[^/]+(?:\.git)$}
242
243
  def linkify(url, changelog)
243
- changelog.map do |line|
244
- line.gsub(/^([a-f0-9]+) (.*)$/, '\2 (%s/commit/\1) ' % [url.chomp('.git')])
245
- end
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
246
251
  end
247
252
 
248
253
  def https_url(location)
@@ -11,6 +11,9 @@ require 'rest-client'
11
11
 
12
12
  class PolicyChangelog
13
13
  TMP_PREFIX = 'knife-changelog'
14
+ # Regex matching Chef cookbook version syntax
15
+ # See https://docs.chef.io/cookbook_versioning.html#syntax
16
+ VERSION_REGEX = /^[1-9]*[0-9](\.[0-9]+){1,2}$/
14
17
 
15
18
  # Initialzes Helper class
16
19
  #
@@ -104,14 +107,30 @@ class PolicyChangelog
104
107
  # @param current [String] current cookbook version tag
105
108
  # @param target [String] target cookbook version tag
106
109
  # @return [String] changelog between tags for one cookbook
107
- def git_changelog(source_url, current, target)
110
+ def git_changelog(source_url, current, target, cookbook = nil)
108
111
  dir = Dir.mktmpdir(TMP_PREFIX)
109
112
  repo = Git.clone(source_url, dir)
110
- repo.log.between(git_ref(current, repo), git_ref(target, repo)).map do |commit|
113
+ cookbook_path = cookbook ? git_cookbook_path(repo, cookbook) : '.'
114
+ repo.log.path(cookbook_path).between(git_ref(current, repo, cookbook), git_ref(target, repo, cookbook)).map do |commit|
111
115
  "#{commit.sha[0, 7]} #{commit.message.lines.first.strip}"
112
116
  end.join("\n")
113
117
  end
114
118
 
119
+ # Tries to find the location of a specific cookbook in the given repo
120
+ #
121
+ # @param repo [Git::Base] Git repository object
122
+ # @param cookbook [String] name of the cookbook to search the location
123
+ # @return [String] reative location of the cookbook in the repo
124
+ def git_cookbook_path(repo, cookbook)
125
+ metadata_files = ['metadata.rb', '*/metadata.rb'].flat_map { |location| repo.ls_files(location).keys }
126
+ metadata_path = metadata_files.find do |path|
127
+ path = ::File.join(repo.dir.to_s, path)
128
+ ::Chef::Cookbook::Metadata.new.tap { |m| m.from_file(path) }.name == cookbook
129
+ end
130
+ raise "Impossible to find matching metadata for #{cookbook} in #{repo.remote.url}" unless metadata_path
131
+ ::File.dirname(metadata_path)
132
+ end
133
+
115
134
  # Tries to convert a supermarket tag to a git reference
116
135
  # if there is a difference in formatting between the two.
117
136
  # This is issue is present for the 'java' cookbook.
@@ -119,9 +138,11 @@ class PolicyChangelog
119
138
  #
120
139
  # @param ref [String] version reference
121
140
  # @param repo [Git::Base] Git repository object
141
+ # @param cookbook [String] name of the cookbook to ref against
122
142
  # @return [String]
123
- def git_ref(myref, repo)
143
+ def git_ref(myref, repo, cookbook_name = nil)
124
144
  possible_refs = ['v' + myref, myref]
145
+ possible_refs += possible_refs.map { |ref| "#{cookbook_name}-#{ref}" } if cookbook_name
125
146
  possible_refs += possible_refs.map { |ref| ref.chomp('.0') } if myref[/\.0$/]
126
147
  existing_ref = possible_refs.find do |ref|
127
148
  begin
@@ -159,7 +180,7 @@ class PolicyChangelog
159
180
  output = ["\nChangelog for #{name}: #{data['current_version']}->#{data['target_version']}"]
160
181
  output << '=' * output.first.size
161
182
  output << if data['current_version']
162
- git_changelog(data['source_url'], data['current_version'], data['target_version'])
183
+ git_changelog(data['source_url'], data['current_version'], data['target_version'], name)
163
184
  else
164
185
  'Cookbook was not in the Policyfile.lock.json'
165
186
  end
@@ -176,10 +197,24 @@ class PolicyChangelog
176
197
  data['current_version'] == data['target_version'] || data['target_version'].nil?
177
198
  end
178
199
 
200
+ # Search for cookbook downgrade and raise an error if any
201
+ def validate_downgrade!(data)
202
+ downgrade = data.select do |_, ck|
203
+ # Do not try to validate downgrade on non-sementic versions (e.g. git revision)
204
+ ck['target_version'] =~ VERSION_REGEX && ck['current_version'] =~ VERSION_REGEX &&
205
+ ::Gem::Version.new(ck['target_version']) < ::Gem::Version.new(ck['current_version'])
206
+ end
207
+
208
+ return if downgrade.empty?
209
+
210
+ details = downgrade.map { |name, data| "#{name} (#{data['current_version']} -> #{data['target_version']})" }
211
+ raise "Trying to downgrade following cookbooks: #{details.join(', ')}"
212
+ end
213
+
179
214
  # Generates Policyfile changelog
180
215
  #
181
216
  # @return [String] formatted version changelog
182
- def generate_changelog
217
+ def generate_changelog(prevent_downgrade: false)
183
218
  lock_current = read_policyfile_lock(@policyfile_dir)
184
219
  current = versions(lock_current['cookbook_locks'], 'current')
185
220
 
@@ -192,6 +227,9 @@ class PolicyChangelog
192
227
  else
193
228
  updated_cookbooks.select { |name, _data| @cookbooks_to_update.include?(name) }
194
229
  end
230
+
231
+ validate_downgrade!(updated_cookbooks) if prevent_downgrade
232
+
195
233
  generate_changelog_from_versions(changelog_cookbooks)
196
234
  end
197
235
 
@@ -92,6 +92,35 @@ 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
+
95
124
  describe '#versions' do
96
125
  context 'when type is current' do
97
126
  it 'returns correct current versions' do
@@ -185,7 +214,7 @@ RSpec.describe PolicyChangelog do
185
214
  allow(changelog).to receive(:git_ref).with('1.0.0', any_args).and_return('v1.0.0')
186
215
  allow(changelog).to receive(:git_ref).with('1.0.1', any_args).and_return('v1.0.1')
187
216
  allow(changelog).to receive(:correct_tags)
188
- allow(git_repo).to receive_message_chain(:log, :between)
217
+ allow(git_repo).to receive_message_chain(:log, :path, :between)
189
218
  .with('v1.0.0', 'v1.0.1')
190
219
  .and_return([git_commit])
191
220
 
@@ -209,11 +238,16 @@ RSpec.describe PolicyChangelog do
209
238
 
210
239
  context 'when tag invalid and able to correct' do
211
240
  it 'returns correct git tag' do
212
- allow(repo).to receive(:checkout).with(/v1.0/).and_raise(::Git::GitExecuteError)
213
241
  allow(repo).to receive(:checkout).with('1.0.0').and_raise(::Git::GitExecuteError)
214
- allow(repo).to receive(:checkout).with('1.0').and_return(true)
215
242
 
216
- expect(changelog.git_ref('1.0.0', repo)).to eq('1.0')
243
+ 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
+ tags.each do |valid_result|
245
+ allow(repo).to receive(:checkout).with(valid_result).and_return(true)
246
+ tags.reject { |v| v == valid_result }.each do |invalid_result|
247
+ allow(repo).to receive(:checkout).with(invalid_result).and_raise(::Git::GitExecuteError)
248
+ end
249
+ expect(changelog.git_ref('1.0.0', repo, 'cookbook_name')).to eq valid_result
250
+ end
217
251
  end
218
252
  end
219
253
 
@@ -279,7 +313,7 @@ RSpec.describe PolicyChangelog do
279
313
  }
280
314
 
281
315
  allow(changelog).to receive(:git_changelog)
282
- .with(instance_of(String), '4.0.0', '5.0.0')
316
+ .with(instance_of(String), '4.0.0', '5.0.0', 'users')
283
317
  .and_return('e1b971a Add test commit message')
284
318
 
285
319
  output = <<~COMMIT.chomp
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-changelog
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.5.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: 2018-05-24 00:00:00.000000000 Z
11
+ date: 2021-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.6'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.6'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: pry
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -199,9 +185,10 @@ executables: []
199
185
  extensions: []
200
186
  extra_rdoc_files: []
201
187
  files:
188
+ - ".github/workflows/ci.yml"
189
+ - ".github/workflows/release.yml"
202
190
  - ".gitignore"
203
191
  - ".rubocop.yml"
204
- - ".travis.yml"
205
192
  - Gemfile
206
193
  - LICENSE.txt
207
194
  - README.md
@@ -243,8 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
243
230
  - !ruby/object:Gem::Version
244
231
  version: '0'
245
232
  requirements: []
246
- rubyforge_project:
247
- rubygems_version: 2.7.7
233
+ rubygems_version: 3.1.6
248
234
  signing_key:
249
235
  specification_version: 4
250
236
  summary: Facilitate access to cookbooks changelog
data/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.4
4
- deploy:
5
- provider: rubygems
6
- api_key:
7
- secure: LAM8qxTQa6oxzKiQpWrqRlcE1czmGFj16NSj1FVgZYJLZIfXKdvSpth+DfuCk8mxG1tvDXa3ckfERrzexG3lYGNPGyZH2sjnyt900Evd3Bn8vhv0LXE7cEZb3x/uJ3RHRvKpEDnMsy4gqoVByDLWXWnI9Q/8B4AtzFeTVsTr48g=
8
- gem: knife-changelog
9
- on:
10
- tags: true
11
- repo: criteo/knife-changelog
12
- sudo: false # use docker based infra