milestoner 10.4.0 → 11.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: 27d5b0fb8d1d2b22dd34a890fca4e1c9e5457517522c19345f60c2fe626805ed
4
- data.tar.gz: bafe01b14f43e42e2521359b3767aded738c3bc5e937337884ee99fd6fd3f989
3
+ metadata.gz: 5152a1a412828716c3e01a280e473011f66335cb0cb007d18603a7fe973fa298
4
+ data.tar.gz: 325015f1de0b136f8d817c3f24ec96f7b429b8c5bf1847551fdb5cc0cdde420d
5
5
  SHA512:
6
- metadata.gz: e7c0cf919317aac53ebbabc7b6e709258ae4d850c385d1fde6a62ed8114a1205fc59386edd8f3534f0253197898dc594c913e8ae95b6e8b519fff0fa84499cc5
7
- data.tar.gz: b2538300101f1e0661a4b4ef1c2677ed1a4adf4599467bb6fdfeaa86dd02f88a27182cb7a49c3bb61e1aced9863a0a0c48bc5ea0288922d80a36d76c0db05e56
6
+ metadata.gz: dc1808ca74a11de0ed5e751faa47832e2c2cbebfcd544c99a045886b004f00bb29c9d80c078fe0b043a802f492e2afddbef289f5c028ac60072a940f14d3d978
7
+ data.tar.gz: 444fce8423e259ec58ea353464c204a2d94eb4d3de51f04d2ab3bb7cf71f358962ff670c979c2bef354848a6944f75d58e966262d17b304cf518001643b24cd3
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -30,11 +30,8 @@ toc::[]
30
30
  ** Updated
31
31
  ** Removed
32
32
  ** Refactored
33
- * Ensures Git commit merge messages are excluded.
34
33
  * Ensures Git commit messages are alphabetically sorted.
35
34
  * Ensures duplicate Git commit messages are removed (if any).
36
- * Ensures Git commit messages are sanitized by removing extra spaces and `+[ci skip]+` text within
37
- each Git tag message.
38
35
  * Provides optional security for signing Git tags with https://www.gnupg.org[GnuPG] signing key.
39
36
 
40
37
  == Screencasts
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "git_plus"
3
4
  require "milestoner/identity"
4
5
  require "milestoner/errors/base"
5
6
  require "milestoner/errors/duplicate_tag"
6
7
  require "milestoner/errors/git"
7
- require "milestoner/git/config"
8
- require "milestoner/git/kit"
8
+ require "milestoner/commit"
9
9
  require "milestoner/tagger"
10
10
  require "milestoner/pusher"
11
11
  require "milestoner/publisher"
@@ -46,7 +46,7 @@ module Milestoner
46
46
  default: false
47
47
  def tag version
48
48
  tagger.create version, sign: sign_tag?(options[:sign])
49
- say "Repository tagged: #{tagger.version}."
49
+ say "Repository tagged: #{version}."
50
50
  rescue StandardError => error
51
51
  say_status :error, error.message, :red
52
52
  end
@@ -69,7 +69,7 @@ module Milestoner
69
69
  default: false
70
70
  def publish version
71
71
  publisher.publish version, sign: sign_tag?(options[:sign])
72
- say_status :info, "Repository tagged and pushed: #{tagger.version}.", :green
72
+ say_status :info, "Repository tagged and pushed: #{version}.", :green
73
73
  say_status :info, "Milestone published!", :green
74
74
  rescue StandardError => error
75
75
  say_status :error, error.message, :red
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module Milestoner
6
+ # Wraps the Git Kit Commit for presentation purposes.
7
+ class Commit
8
+ extend Forwardable
9
+
10
+ delegate [*GitPlus::Commit.members, :fixup?, :squash?] => :source
11
+
12
+ def initialize source
13
+ @source = source
14
+ end
15
+
16
+ def subject_author delimiter: " - "
17
+ "#{subject}#{delimiter}#{author_name}"
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :source
23
+ end
24
+ end
@@ -5,7 +5,7 @@ module Milestoner
5
5
  module Identity
6
6
  NAME = "milestoner"
7
7
  LABEL = "Milestoner"
8
- VERSION = "10.4.0"
8
+ VERSION = "11.0.0"
9
9
  VERSION_LABEL = "#{LABEL} #{VERSION}"
10
10
  end
11
11
  end
@@ -3,26 +3,32 @@
3
3
  module Milestoner
4
4
  # Handles publishing of Git tags to remote repository.
5
5
  class Pusher
6
- def initialize git: Git::Kit.new
7
- @git = git
6
+ def initialize repository: GitPlus::Repository.new
7
+ @repository = repository
8
8
  end
9
9
 
10
10
  def push version
11
11
  version = Versionaire::Version version
12
12
 
13
- fail Errors::Git, "Remote repository not configured." unless git.remote?
13
+ fail Errors::Git, "Remote repository not configured." unless repository.config_remote?
14
14
  fail Errors::Git, "Remote tag exists: #{version}." if tag_exists? version
15
- return if git.push_tags.empty?
15
+ return if push_tags
16
16
 
17
17
  fail Errors::Git, "Tags could not be pushed to remote repository."
18
18
  end
19
19
 
20
20
  private
21
21
 
22
- attr_reader :git, :version
22
+ attr_reader :repository, :version
23
23
 
24
24
  def tag_exists? version
25
- git.tag_remote? version
25
+ repository.tag_remote? version
26
+ end
27
+
28
+ def push_tags
29
+ repository.tag_push.then do |_stdout, stderr, status|
30
+ status.success? && stderr.match?(/[new tag]/)
31
+ end
26
32
  end
27
33
  end
28
34
  end
@@ -1,115 +1,88 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open3"
4
3
  require "thor"
5
4
  require "versionaire"
6
- require "tempfile"
7
5
 
8
6
  module Milestoner
9
7
  # Handles the tagging of a project repository.
10
- # :reek:TooManyMethods
11
- # :reek:InstanceVariableAssumption
8
+ # :reek:TooManyInstanceVariables
12
9
  class Tagger
13
- attr_reader :version, :commit_prefixes
10
+ attr_reader :commit_prefixes
14
11
 
15
- def initialize commit_prefixes: [], git: Git::Kit.new
12
+ def initialize commit_prefixes: [], repository: GitPlus::Repository.new, presenter: Commit
16
13
  @commit_prefixes = commit_prefixes
17
- @git = git
14
+ @repository = repository
15
+ @presenter = presenter
18
16
  @shell = Thor::Shell::Color.new
19
17
  end
20
18
 
21
19
  def commit_prefix_regex
22
- return Regexp.new "" if commit_prefixes.empty?
23
-
24
- Regexp.union commit_prefixes
20
+ commit_prefixes.empty? ? Regexp.new("") : Regexp.union(commit_prefixes)
25
21
  end
26
22
 
27
23
  def commits
28
24
  groups = build_commit_prefix_groups
29
25
  group_by_commit_prefix groups
30
- groups.each_value(&:sort!)
31
- groups.values.flatten.uniq
26
+ groups.each_value { |commits| commits.sort_by!(&:subject) }
27
+ groups.values.flatten.uniq(&:subject)
32
28
  end
33
29
 
34
30
  def commit_list
35
- commits.map { |commit| "- #{commit}" }
31
+ commits.map { |source| presenter.new source }
32
+ .map { |commit| "- #{commit.subject_author}" }
36
33
  end
37
34
 
38
35
  # :reek:BooleanParameter
36
+ # :reek:ControlParameter
37
+ # :reek:TooManyStatements
39
38
  def create version, sign: false
40
- @version = Versionaire::Version version
41
- fail Errors::Git, "Unable to tag without commits." unless git.commits?
42
- return if existing_tag?
39
+ version = Versionaire::Version version
40
+ fail Errors::Git, "Unable to tag without commits." if repository.commits.empty?
41
+ return if exists? version
43
42
 
44
- git_tag sign: sign
43
+ content = message version
44
+ sign ? repository.tag_sign(version, content) : repository.tag_unsign(version, content)
45
45
  end
46
46
 
47
47
  private
48
48
 
49
- attr_reader :git, :shell
50
-
51
- def git_log_command
52
- "git log --oneline --no-merges --format='%s'"
53
- end
49
+ attr_reader :repository, :presenter, :shell
54
50
 
55
- def git_tag_command
56
- "$(git describe --abbrev=0 --tags --always)..HEAD"
51
+ def saved_commits
52
+ repository.commits
57
53
  end
58
54
 
59
- def git_commits_command
60
- return "#{git_log_command} #{git_tag_command}" if git.tagged?
61
-
62
- git_log_command
55
+ def tagged_commits
56
+ repository.commits "#{repository.tag_last}..HEAD"
63
57
  end
64
58
 
65
- def raw_commits
66
- `#{git_commits_command}`.split "\n"
59
+ def computed_commits
60
+ (repository.tagged? ? tagged_commits : saved_commits)
67
61
  end
68
62
 
69
63
  def build_commit_prefix_groups
70
- groups = commit_prefixes.map.with_object({}) { |prefix, group| group.merge! prefix => [] }
71
- groups.merge! "Other" => []
64
+ commit_prefixes.map
65
+ .with_object({}) { |prefix, group| group.merge! prefix => [] }
66
+ .merge! "Other" => []
72
67
  end
73
68
 
74
69
  def group_by_commit_prefix groups = {}
75
- raw_commits.each do |commit|
76
- prefix = commit[commit_prefix_regex]
70
+ computed_commits.each do |commit|
71
+ prefix = commit.subject[commit_prefix_regex]
77
72
  key = groups.key?(prefix) ? prefix : "Other"
78
- groups[key] << commit.gsub(/\[ci\sskip\]/, "").squeeze(" ").strip
73
+ groups[key] << commit
79
74
  end
80
75
  end
81
76
 
82
- def git_message
83
- %(Version #{@version}\n\n#{commit_list.join "\n"}\n\n)
77
+ def message version
78
+ %(Version #{version}\n\n#{commit_list.join "\n"}\n\n)
84
79
  end
85
80
 
86
- # :reek:BooleanParameter
87
- # :reek:ControlParameter
88
- def git_options message_file, sign: false
89
- options = %(--sign --annotate "#{@version}" ) +
90
- %(--cleanup verbatim --file "#{message_file.path}")
91
- return options.gsub "--sign ", "" unless sign
81
+ def exists? version
82
+ return false unless repository.tag_local? version
92
83
 
93
- options
94
- end
95
-
96
- def existing_tag?
97
- return false unless git.tag_local? @version
98
-
99
- shell.say_status :warn, "Local tag exists: #{@version}. Skipped.", :yellow
84
+ shell.say_status :warn, "Local tag exists: #{version}. Skipped.", :yellow
100
85
  true
101
86
  end
102
-
103
- # :reek:BooleanParameter
104
- # :reek:TooManyStatements
105
- def git_tag sign: false
106
- message_file = Tempfile.new Identity::NAME
107
- File.open(message_file, "w") { |file| file.write git_message }
108
- status = system "git tag #{git_options message_file, sign: sign}"
109
- fail Errors::Git, "Unable to create tag: #{@version}." unless status
110
- ensure
111
- message_file.close
112
- message_file.unlink
113
- end
114
87
  end
115
88
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: milestoner
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.4.0
4
+ version: 11.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -28,246 +28,78 @@ cert_chain:
28
28
  2XV8FRa7/JimI07sPLC13eLY3xd/aYTi85Z782KIA4j0G8XEEWAX0ouBhlXPocZv
29
29
  QWc=
30
30
  -----END CERTIFICATE-----
31
- date: 2020-11-14 00:00:00.000000000 Z
31
+ date: 2020-12-30 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
- name: runcom
34
+ name: git_plus
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '6.4'
39
+ version: '0.1'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '6.4'
46
+ version: '0.1'
47
47
  - !ruby/object:Gem::Dependency
48
- name: thor
48
+ name: refinements
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '0.20'
53
+ version: '8.0'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '0.20'
60
+ version: '8.0'
61
61
  - !ruby/object:Gem::Dependency
62
- name: versionaire
62
+ name: runcom
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '8.4'
67
+ version: '7.0'
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: '8.4'
75
- - !ruby/object:Gem::Dependency
76
- name: bundler-audit
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.7'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.7'
89
- - !ruby/object:Gem::Dependency
90
- name: bundler-leak
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '0.2'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '0.2'
103
- - !ruby/object:Gem::Dependency
104
- name: climate_control
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '0.1'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: '0.1'
117
- - !ruby/object:Gem::Dependency
118
- name: guard-rspec
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '4.7'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '4.7'
131
- - !ruby/object:Gem::Dependency
132
- name: pry
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '0.13'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '0.13'
145
- - !ruby/object:Gem::Dependency
146
- name: pry-byebug
147
- requirement: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - "~>"
150
- - !ruby/object:Gem::Version
151
- version: '3.9'
152
- type: :development
153
- prerelease: false
154
- version_requirements: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '3.9'
159
- - !ruby/object:Gem::Dependency
160
- name: rake
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
164
- - !ruby/object:Gem::Version
165
- version: '13.0'
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
171
- - !ruby/object:Gem::Version
172
- version: '13.0'
173
- - !ruby/object:Gem::Dependency
174
- name: reek
175
- requirement: !ruby/object:Gem::Requirement
176
- requirements:
177
- - - "~>"
178
- - !ruby/object:Gem::Version
179
- version: '6.0'
180
- type: :development
181
- prerelease: false
182
- version_requirements: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - "~>"
185
- - !ruby/object:Gem::Version
186
- version: '6.0'
187
- - !ruby/object:Gem::Dependency
188
- name: rspec
189
- requirement: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - "~>"
192
- - !ruby/object:Gem::Version
193
- version: '3.10'
194
- type: :development
195
- prerelease: false
196
- version_requirements: !ruby/object:Gem::Requirement
197
- requirements:
198
- - - "~>"
199
- - !ruby/object:Gem::Version
200
- version: '3.10'
201
- - !ruby/object:Gem::Dependency
202
- name: rubocop
203
- requirement: !ruby/object:Gem::Requirement
204
- requirements:
205
- - - "~>"
206
- - !ruby/object:Gem::Version
207
- version: '1.3'
208
- type: :development
209
- prerelease: false
210
- version_requirements: !ruby/object:Gem::Requirement
211
- requirements:
212
- - - "~>"
213
- - !ruby/object:Gem::Version
214
- version: '1.3'
215
- - !ruby/object:Gem::Dependency
216
- name: rubocop-performance
217
- requirement: !ruby/object:Gem::Requirement
218
- requirements:
219
- - - "~>"
220
- - !ruby/object:Gem::Version
221
- version: '1.8'
222
- type: :development
223
- prerelease: false
224
- version_requirements: !ruby/object:Gem::Requirement
225
- requirements:
226
- - - "~>"
227
- - !ruby/object:Gem::Version
228
- version: '1.8'
74
+ version: '7.0'
229
75
  - !ruby/object:Gem::Dependency
230
- name: rubocop-rake
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - "~>"
234
- - !ruby/object:Gem::Version
235
- version: '0.5'
236
- type: :development
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - "~>"
241
- - !ruby/object:Gem::Version
242
- version: '0.5'
243
- - !ruby/object:Gem::Dependency
244
- name: rubocop-rspec
76
+ name: thor
245
77
  requirement: !ruby/object:Gem::Requirement
246
78
  requirements:
247
79
  - - "~>"
248
80
  - !ruby/object:Gem::Version
249
- version: '2.0'
250
- type: :development
81
+ version: '0.20'
82
+ type: :runtime
251
83
  prerelease: false
252
84
  version_requirements: !ruby/object:Gem::Requirement
253
85
  requirements:
254
86
  - - "~>"
255
87
  - !ruby/object:Gem::Version
256
- version: '2.0'
88
+ version: '0.20'
257
89
  - !ruby/object:Gem::Dependency
258
- name: simplecov
90
+ name: versionaire
259
91
  requirement: !ruby/object:Gem::Requirement
260
92
  requirements:
261
93
  - - "~>"
262
94
  - !ruby/object:Gem::Version
263
- version: '0.19'
264
- type: :development
95
+ version: '9.0'
96
+ type: :runtime
265
97
  prerelease: false
266
98
  version_requirements: !ruby/object:Gem::Requirement
267
99
  requirements:
268
100
  - - "~>"
269
101
  - !ruby/object:Gem::Version
270
- version: '0.19'
102
+ version: '9.0'
271
103
  description:
272
104
  email:
273
105
  - brooke@alchemists.io
@@ -283,11 +115,10 @@ files:
283
115
  - bin/milestoner
284
116
  - lib/milestoner.rb
285
117
  - lib/milestoner/cli.rb
118
+ - lib/milestoner/commit.rb
286
119
  - lib/milestoner/errors/base.rb
287
120
  - lib/milestoner/errors/duplicate_tag.rb
288
121
  - lib/milestoner/errors/git.rb
289
- - lib/milestoner/git/config.rb
290
- - lib/milestoner/git/kit.rb
291
122
  - lib/milestoner/identity.rb
292
123
  - lib/milestoner/publisher.rb
293
124
  - lib/milestoner/pusher.rb
@@ -308,14 +139,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
308
139
  requirements:
309
140
  - - "~>"
310
141
  - !ruby/object:Gem::Version
311
- version: '2.7'
142
+ version: '3.0'
312
143
  required_rubygems_version: !ruby/object:Gem::Requirement
313
144
  requirements:
314
145
  - - ">="
315
146
  - !ruby/object:Gem::Version
316
147
  version: '0'
317
148
  requirements: []
318
- rubygems_version: 3.1.4
149
+ rubygems_version: 3.2.3
319
150
  signing_key:
320
151
  specification_version: 4
321
152
  summary: A command line interface for crafting Git repository milestones.
metadata.gz.sig CHANGED
Binary file
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "open3"
4
-
5
- module Milestoner
6
- module Git
7
- # A lightweight Git Config wrapper.
8
- class Config
9
- def initialize shell: Open3
10
- @shell = shell
11
- end
12
-
13
- def get key
14
- shell.capture3 "git config --get #{key}"
15
- end
16
-
17
- def set key, value
18
- shell.capture3 %(git config --add #{key} "#{value}")
19
- end
20
-
21
- def value key
22
- get(key).first.chomp
23
- end
24
-
25
- private
26
-
27
- attr_reader :shell
28
- end
29
- end
30
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Milestoner
4
- module Git
5
- # A lightweight Git wrapper.
6
- class Kit
7
- def initialize
8
- @git_dir = File.join Dir.pwd, ".git"
9
- end
10
-
11
- def supported?
12
- File.exist? git_dir
13
- end
14
-
15
- def commits?
16
- !shell("git log").empty?
17
- end
18
-
19
- def push_tags
20
- shell "git push --tags"
21
- end
22
-
23
- def tagged?
24
- !shell("git tag").empty?
25
- end
26
-
27
- def tag_local? tag
28
- shell("git tag --list #{tag}").match?(/\A#{tag}\Z/)
29
- end
30
-
31
- def tag_remote? tag
32
- shell("git ls-remote --tags origin #{tag}").match?(%r(.+tags/#{tag}\Z))
33
- end
34
-
35
- def remote?
36
- !shell("git config remote.origin.url").empty?
37
- end
38
-
39
- private
40
-
41
- attr_reader :git_dir
42
-
43
- def shell command
44
- String `#{command}`
45
- end
46
- end
47
- end
48
- end