knife-changelog 1.2.5 → 1.5.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: 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