cookbook-release 1.4.3 → 1.7.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: d48e42c04f5d4ac5f465c53eebb18921398ba5212f39cf0fa6207e6377e3b162
4
- data.tar.gz: 684da15c491938a19b473ddcd997d428830631c11a0a174b70dcf02bf1dbba9d
3
+ metadata.gz: 59ea3c1e5d1d222c334a409f63333f4a7339cebc36655043656fd1c26c78ec2f
4
+ data.tar.gz: 59d2e2dfb5db2d3bd9e28fc341b0839c0fdb63a0d8483764528cb2bede290320
5
5
  SHA512:
6
- metadata.gz: 2a2455d339262c0e83172ee37af3ff81f224139915022a97dcbbbac2ea8d8b45e754af7dcf7a913c612418d63614848ce7c0fc6d957bddddb77cb01515f66eef
7
- data.tar.gz: 4fd577bd939752c1ddf96d003f9c521b2c186b2e3ce9333046cfb1a0d5c2c3c8b0e2415d26aa4183955ed1ab0625559755e1b13cc783099224985cb3b4a2d528
6
+ metadata.gz: 5b292dadbf789958681065228a9732c0614008e9cca74a8e3bcf478cbbf42da2c0bef73f8a6ad2ae52309b0ac47573a6038ddd62480fb4c73afdab76616be4f1
7
+ data.tar.gz: 5f856842d4d1588c21d3961d29f9346b8b41000e3054933dcfbdba830a3811703b5894b6ac41cdd530e9bb6d2e6a8911eb65874cfd423dfc0b98c2dc82f2f58f
@@ -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 ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -6,7 +6,7 @@ require 'English'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
8
  spec.name = 'cookbook-release'
9
- spec.version = '1.4.3'
9
+ spec.version = '1.7.0'
10
10
  spec.authors = ['Grégoire Seux']
11
11
  spec.email = 'g.seux@criteo.com'
12
12
  spec.summary = 'Provide primitives (and rake tasks) to release a cookbook'
@@ -22,8 +22,10 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency 'semantic'
23
23
  spec.add_dependency 'highline'
24
24
  spec.add_dependency 'mixlib-shellout'
25
- spec.add_dependency 'chef', '>= 12.18.31'
25
+ # TODO: support Chef 17 and leverage knife gem at some point
26
+ spec.add_dependency 'chef', '>= 12.18.31', '< 17.0' # knife code has been moved to dedicated gem starting with Chef 17
26
27
  spec.add_dependency 'git-ng' # see https://github.com/schacon/ruby-git/issues/307
28
+ spec.add_dependency 'unicode-emoji'
27
29
 
28
30
 
29
31
  spec.add_development_dependency 'rspec'
@@ -11,6 +11,7 @@ module CookbookRelease
11
11
  RISKY = 'RISKY/BREAKING (details below):'
12
12
  NO_RISKY = 'NO RISKY/BREAKING COMMITS. READ FULL CHANGELOG.'
13
13
  NON_NODES_ONLY = 'Non-risky/major, Non-node-only commits'
14
+ NODES_ONLY = 'Commits impacting only nodes'
14
15
  FULL = 'Full changelog:'
15
16
  DETAILS = 'Details of risky commits:'
16
17
 
@@ -109,28 +110,53 @@ module CookbookRelease
109
110
  end
110
111
 
111
112
  def markdown_priority_nodes
112
- cl = changelog
113
- risky_commits = cl.select { |c| c.risky? || c.major? }
114
- not_nodes_only_commits = cl.reject { |c| c.nodes_only? || c.risky? || c.major? }
115
113
  result = []
116
- if risky_commits.any?
117
- result << "*#{RISKY}*\n" << risky_commits.map { |c| c.to_s_markdown(false) }.join("\n") << "\n"
118
- else
119
- result << "*#{NO_RISKY}*\n\n"
120
- end
114
+ result << append_risky(changelog)
115
+ result << append_by_impact(changelog)
116
+ result << append_risky_details(changelog)
117
+ result
118
+ end
119
+
120
+ private
121
+
122
+ # @param changelog [Array<Commit>]
123
+ # @return [String] a string describing the changelog
124
+ def append_by_impact(changelog)
125
+ not_nodes_only_commits = changelog.reject { |c| c.nodes_only? || c.risky? || c.major? }
126
+ nodes_only_commits = changelog.select(&:nodes_only?)
127
+ output = []
121
128
  if not_nodes_only_commits.any?
122
- result << "*#{NON_NODES_ONLY}*\n" << not_nodes_only_commits.map { |c| c.to_s_markdown(false) }.join("\n") << "\n"
129
+ txt = not_nodes_only_commits.map { |c| c.to_s_markdown(false) }.join("\n")
130
+ output << "*#{NON_NODES_ONLY}*\n#{txt}\n"
123
131
  end
124
- result << "*#{FULL}*\n"
125
- result << cl.map { |c| c.to_s_markdown(false) }.join("\n")
132
+ if nodes_only_commits.any?
133
+ txt = nodes_only_commits.map { |c| c.to_s_markdown(false) }.join("\n")
134
+ output << "*#{NODES_ONLY}*\n#{txt}\n"
135
+ end
136
+ output.join
137
+ end
138
+
139
+ # @param changelog [Array<Commit>]
140
+ # @return [String] a string describing the changelog
141
+ def append_risky_details(changelog)
142
+ risky_commits = changelog.select { |c| c.risky? || c.major? }
126
143
  if risky_commits.any?
127
- result << "\n#{DETAILS}\n"
128
- result << risky_commits.map { |c| c.to_s_markdown(true) }.join("\n")
144
+ "\n#{DETAILS}\n" + risky_commits.map { |c| c.to_s_markdown(true) }.join("\n")
145
+ else
146
+ ''
129
147
  end
130
- result
131
148
  end
132
149
 
133
- private
150
+ # @param changelog [Array<Commit>]
151
+ # @return [String] a string describing the changelog
152
+ def append_risky(changelog)
153
+ risky_commits = changelog.select { |c| c.risky? || c.major? }
154
+ if risky_commits.any?
155
+ "*#{RISKY}*\n" << risky_commits.map { |c| c.to_s_markdown(false) }.join("\n") << "\n"
156
+ else
157
+ "*#{NO_RISKY}*\n\n"
158
+ end
159
+ end
134
160
 
135
161
  def changelog
136
162
  ref = ENV['RELEASE_BRANCH'] || 'origin/master'
@@ -1,3 +1,6 @@
1
+ require 'forwardable'
2
+ require 'unicode/emoji'
3
+
1
4
  module CookbookRelease
2
5
  class Commit
3
6
  extend Forwardable
@@ -79,11 +82,20 @@ module CookbookRelease
79
82
  else
80
83
  result << "_#{self[:author]} <#{self[:email]}>_"
81
84
  end
82
- result << " `#{self[:subject]}`"
85
+ result << ' '
86
+ result << backtick_string(self[:subject])
83
87
  result << "\n```\n#{strip_change_id(self[:body])}```" if full && self[:body]
84
88
  result
85
89
  end
86
90
 
91
+ def backtick_string(input)
92
+ s = input.gsub(/( )?(#{Unicode::Emoji::REGEX})( )?/, '` \2 `')
93
+ .gsub(/( )?``( )?/, '')
94
+ s += '`' unless s =~ /`$/
95
+ s = '`' + s unless s =~ /^`/
96
+ s
97
+ end
98
+
87
99
  private
88
100
 
89
101
  def strip_change_id(body)
@@ -8,6 +8,7 @@ module CookbookRelease
8
8
  class GitUtilities
9
9
 
10
10
  attr_accessor :no_prompt
11
+ attr_reader :sub_dir
11
12
 
12
13
  def initialize(options={})
13
14
  @tag_prefix = options[:tag_prefix] || ''
@@ -23,6 +24,15 @@ module CookbookRelease
23
24
  File.directory?(::File.join(dir, '.git'))
24
25
  end
25
26
 
27
+ def self.find_root(dir = Dir.pwd)
28
+ # Do not consider given dir as part of the git repo if not in git hierarchy or dir is not tracked
29
+ return if ::Mixlib::ShellOut.new('git ls-files --error-unmatch .', cwd: dir).run_command.error?
30
+
31
+ cmd = Mixlib::ShellOut.new("git rev-parse --show-toplevel", cwd: dir)
32
+ cmd.run_command
33
+ cmd.error? ? nil : cmd.stdout.chomp
34
+ end
35
+
26
36
  def reset_command(new_version)
27
37
  remote = choose_remote
28
38
  "git tag -d #{new_version} ; git push #{remote} :#{new_version}"
@@ -43,11 +53,13 @@ module CookbookRelease
43
53
  def _compute_last_release
44
54
  tag = Mixlib::ShellOut.new([
45
55
  'git describe',
56
+ "--abbrev=0",
46
57
  "--tags",
47
58
  "--match \"#{@tag_prefix}[0-9]*\.[0-9]*\.[0-9]*\""
48
59
  ].join(" "), @shellout_opts)
49
60
  tag.run_command
50
- tag.stdout.split('-').first
61
+ rel = tag.stdout.sub(/^#{@tag_prefix}/, '').chomp
62
+ rel.empty? ? nil : rel
51
63
  end
52
64
 
53
65
  def has_any_release?
@@ -64,7 +76,8 @@ module CookbookRelease
64
76
  end
65
77
 
66
78
  def compute_changelog(since, short_sha = true)
67
- @g.log(500).object(@sub_dir).between(since, 'HEAD').map do |commit|
79
+ ref = "#{@tag_prefix}#{since}"
80
+ @g.log(500).object(@sub_dir).between(ref, 'HEAD').map do |commit|
68
81
  message = commit.message.lines.map(&:chomp).compact.delete_if(&:empty?)
69
82
  Commit.new(
70
83
  author: commit.author.name,
@@ -5,13 +5,20 @@ module CookbookRelease
5
5
  def self.current_version(file)
6
6
  dir = File.dirname(file)
7
7
  version_file = File.join(dir, '.cookbook_version')
8
+ git_root = GitUtilities.find_root(dir)
8
9
 
9
- if !GitUtilities.git?(dir)
10
+ if !GitUtilities.git?(dir) && git_root.nil?
10
11
  return File.read(version_file) if File.exist?(version_file)
11
12
  raise "Can't determine version in a non-git environment without #{version_file}"
12
13
  end
13
14
 
14
- r = Release.new(GitUtilities.new(cwd: dir))
15
+ git = if git_root == dir
16
+ GitUtilities.new(cwd: dir)
17
+ else
18
+ GitUtilities.new(cwd: git_root, tag_prefix: "#{File.basename(dir)}-", sub_dir: dir)
19
+ end
20
+
21
+ r = Release.new(git)
15
22
  begin
16
23
  r.new_version.first
17
24
  rescue ExistingRelease
@@ -101,7 +108,7 @@ module CookbookRelease
101
108
  exit 1 unless agreed
102
109
  git.push_tag(new_version)
103
110
  supermarket = Supermarket.new
104
- supermarket.publish_ck(@category)
111
+ supermarket.publish_ck(@category, git.sub_dir)
105
112
  rescue
106
113
  puts HighLine.color("Release aborted, you have to reset to previous state manually", :red)
107
114
  puts ":use with care: #{git.reset_command(new_version)}"
@@ -8,7 +8,7 @@ require 'json'
8
8
  module CookbookRelease
9
9
  class Supermarket
10
10
 
11
- # This code is adapted from "knife cookbook share" and travis dpl provider
11
+ # This code is adapted from "knife cookbook share" and travis dpl provider
12
12
  # for supermarket.
13
13
 
14
14
  def initialize(opts={})
@@ -20,11 +20,11 @@ module CookbookRelease
20
20
 
21
21
  include ::Chef::Mixin::ShellOut
22
22
 
23
- def publish_ck(category)
24
- ck = ::Chef::Cookbook::CookbookVersionLoader.new('.')
23
+ def publish_ck(category, path = nil)
24
+ ck = ::Chef::Cookbook::CookbookVersionLoader.new(path || '.')
25
25
  ck.load!
26
26
  cookbook = ck.cookbook_version
27
- # we have to provide a rest option otherwise it will try to load a
27
+ # we have to provide a rest option otherwise it will try to load a
28
28
  # client.pem key
29
29
  ::Chef::CookbookUploader.new(cookbook, rest: 'fake_rest').validate_cookbooks
30
30
 
@@ -83,10 +83,10 @@ describe CookbookRelease::Changelog do
83
83
  end
84
84
 
85
85
  it 'expands the body with non-risky+non-nodes' do
86
- expect(git).to receive(:compute_changelog).and_return(commits)
86
+ expect(git).to receive(:compute_changelog).and_return(commits).at_least(:once)
87
87
  changelog = CookbookRelease::Changelog.new(git, expand_risky: true, nodes_only: true)
88
88
  expect(changelog.markdown_priority_nodes.join('')).to include(
89
- "\n*Non-risky/major, Non-node-only commits*\n*654321* _John Doe <j.doe@nobody.com>_ `hello`\n*Full"
89
+ "\n*Non-risky/major, Non-node-only commits*\n*654321* _John Doe <j.doe@nobody.com>_ `hello`\n*Commits impacting only nodes"
90
90
  )
91
91
  end
92
92
  end
data/spec/commit_spec.rb CHANGED
@@ -23,4 +23,16 @@ describe CookbookRelease::Commit do
23
23
  expect(minor_change) .not_to be_patch
24
24
  end
25
25
  end
26
+
27
+ describe '.to_s_markdown' do
28
+ it 'surrounds subject with backticks' do
29
+ commit = CookbookRelease::Commit.new(subject: 'This is a fix', hash: 'abcdef', author: 'Linus', email: 'linus@linux.org')
30
+ expect(commit.to_s_markdown(false)).to match(/`#{commit[:subject]}`/)
31
+ end
32
+
33
+ it 'properly handle emojis' do
34
+ commit = CookbookRelease::Commit.new(subject: 'This is a fix 🔧 and I love 🪐🚀', hash: 'abcdef', author: 'Linus', email: 'linus@linux.org')
35
+ expect(commit.to_s_markdown(false)).to match(/`This is a fix` 🔧 `and I love` 🪐🚀/)
36
+ end
37
+ end
26
38
  end
data/spec/git_spec.rb CHANGED
@@ -44,6 +44,21 @@ describe CookbookRelease::GitUtilities do
44
44
  expect(CookbookRelease::GitUtilities.git?(tmp)).to be(true)
45
45
  FileUtils.rm_rf(tmp)
46
46
  end
47
+
48
+ it 'do not finds repo\'s root from untracked subdir' do
49
+ subdir = 'cookbooks/mycookbook'
50
+ FileUtils.mkdir_p(subdir)
51
+ expect(CookbookRelease::GitUtilities.find_root(subdir)).to be nil
52
+ end
53
+
54
+ it 'finds repo\'s root from tracked subdir' do
55
+ subdir = 'cookbooks/mycookbook'
56
+ tracked_file = ::File.join(subdir, 'tracked_file')
57
+ FileUtils.mkdir_p(subdir)
58
+ FileUtils.touch(tracked_file)
59
+ ::Mixlib::ShellOut.new("git add '#{tracked_file}'").run_command
60
+ expect(CookbookRelease::GitUtilities.find_root(subdir)).to eq(Dir.pwd)
61
+ end
47
62
  end
48
63
 
49
64
  describe '.clean_index(?|!)' do
@@ -150,8 +165,8 @@ git tag 12.34.56
150
165
 
151
166
  it 'parse correctly commits' do
152
167
  cmds = <<-EOH
153
- git commit --allow-empty -m "subject" -m "body" -m "line2"
154
- git commit --allow-empty -m "without body"
168
+ git commit --allow-empty --no-verify -m "subject" -m "body" -m "line2"
169
+ git commit --allow-empty --no-verify -m "without body"
155
170
  EOH
156
171
  cmds.split("\n").each do |cmd|
157
172
  cmd = Mixlib::ShellOut.new(cmd)
data/spec/release_spec.rb CHANGED
@@ -36,12 +36,13 @@ describe Release do
36
36
  :push_tag => true,
37
37
  )
38
38
  allow(git).to receive(:no_prompt=)
39
+ allow(git).to receive(:sub_dir).and_return(nil)
39
40
  release = Release.new(git, no_prompt: true)
40
41
 
41
42
  supermarket = double('supermarket')
42
43
  expect(CookbookRelease::Supermarket).to receive(:new).and_return(supermarket)
43
44
 
44
- expect(supermarket).to receive(:publish_ck).with('Other')
45
+ expect(supermarket).to receive(:publish_ck).with('Other', nil)
45
46
  release.release!
46
47
  end
47
48
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cookbook-release
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grégoire Seux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-03 00:00:00.000000000 Z
11
+ date: 2021-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: semantic
@@ -59,6 +59,9 @@ dependencies:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: 12.18.31
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '17.0'
62
65
  type: :runtime
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
@@ -66,6 +69,9 @@ dependencies:
66
69
  - - ">="
67
70
  - !ruby/object:Gem::Version
68
71
  version: 12.18.31
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '17.0'
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: git-ng
71
77
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +86,20 @@ dependencies:
80
86
  - - ">="
81
87
  - !ruby/object:Gem::Version
82
88
  version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: unicode-emoji
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
83
103
  - !ruby/object:Gem::Dependency
84
104
  name: rspec
85
105
  requirement: !ruby/object:Gem::Requirement
@@ -142,12 +162,13 @@ executables: []
142
162
  extensions: []
143
163
  extra_rdoc_files: []
144
164
  files:
165
+ - ".github/workflows/ci.yml"
166
+ - ".github/workflows/release.yml"
145
167
  - ".gitignore"
146
- - ".travis.yml"
147
168
  - Gemfile
148
169
  - LICENSE.txt
149
170
  - README.md
150
- - Rakefile.rb
171
+ - Rakefile
151
172
  - cookbook-release.gemspec
152
173
  - lib/cookbook-release.rb
153
174
  - lib/cookbook-release/changelog.rb
@@ -180,8 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
201
  - !ruby/object:Gem::Version
181
202
  version: '0'
182
203
  requirements: []
183
- rubyforge_project:
184
- rubygems_version: 2.7.6
204
+ rubygems_version: 3.1.6
185
205
  signing_key:
186
206
  specification_version: 4
187
207
  summary: Provide primitives (and rake tasks) to release a cookbook
data/.travis.yml DELETED
@@ -1,11 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.4
4
- deploy:
5
- provider: rubygems
6
- api_key:
7
- secure: nrEzm2dqWjyaa5ewApSonF+2D+y3PYwt9xaQC04d1NtbhQYyzX6wti3oatpMJI2gkcuuLjKrNHH/aLbKOGv7+Jj5BUJGOLixxhRdJyLWde/6cKCYVgIYPxeUtSJrRgyHAS2o8TDPjhWCT5oRwSkmhd+5D2JKjVqAycetbIzKWWvqScO09z0bF66bbKSfO1s44JwKjnUUW7W9tzrPvMPouBBoFtQ+dQVgxYLajgmjprVvIwzlHxgq/zP8YwL8i7vyRJFiQXyveSxZfBagN2qrUM72HWBPLLW4AeAdLDHYWon88GDU0p+cy2mVeSe67fBPVDopAEGij7MNJCBWV1/SRRKQcEb2U823+1GSB13OvaOGTn9rYsJP5zLKu77ATbHPi22nMfWOAzdEJJ+uFu9XW4nwUO/j79zPC1mEsRZDJlDrmTc4XZQJRKkCUjSl/J53vbdy4JQfos8B2V15tzx1baswQVPZuNiwuP4dOupI34FohJSVXQrsOoWVWVEX5Tfod6s3kpivW6lzwM68I2qXFa/4H8RPU2m0eVpfQslOO8TaGnbodudbQ1LSi/d5W6XWrMVqWGH910JG3jlJgHn5J7yQlI4VqnOpCjGsx/5xincuJZ7hBhcu5q5zcAGem7TrYSNkrx6neBYKmpZBHOWalIGw8wI9uViEsGQ6fayFee8=
8
- gem: cookbook-release
9
- on:
10
- tags: true
11
- repo: criteo/cookbook-release
data/Rakefile.rb DELETED
@@ -1,7 +0,0 @@
1
- begin
2
- require 'rspec/core/rake_task'
3
- RSpec::Core::RakeTask.new(:spec)
4
- rescue LoadError
5
- end
6
-
7
- task :default => :spec