cookbook-release 1.4.3 → 1.7.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: 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