ballantine 0.1.3 → 0.1.4.pre.beta
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 +4 -4
- data/lib/ballantine/author.rb +12 -10
- data/lib/ballantine/cli.rb +111 -88
- data/lib/ballantine/config.rb +9 -7
- data/lib/ballantine/version.rb +1 -1
- data/lib/ballantine.rb +6 -5
- data/lib/string.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36f79167ee934830b2a9d8a59273ffb68970b81a2a48ba21b28f11779227722b
|
4
|
+
data.tar.gz: 37c6726d842dc7dd153c6b8545200ab31fd97586ee1c07e1270bd318a745dd92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acb862515fde0497f8b7c592c29610c79368063594d8f0f3daa38ed252beabdad2c1ce8fbb2970ee7f30d81e88c2a8d6b95f4158ca67d878ccea0a10bf290f9d
|
7
|
+
data.tar.gz: 0a3b6021c754125ba74bba213df06e860e0a793b3b0027640ae3ae559adce7544c61e4e2ef70832f0fcadc07207cd51428223f4083aa85fe40db8e1b725ca5e5
|
data/lib/ballantine/author.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Ballantine
|
4
4
|
class Author
|
@@ -8,15 +8,17 @@ module Ballantine
|
|
8
8
|
# @param [String] name
|
9
9
|
# @return [Author] author
|
10
10
|
def find_or_create_by(name)
|
11
|
-
|
12
|
-
return
|
13
|
-
|
11
|
+
@_collections = {} unless defined?(@_collections)
|
12
|
+
return @_collections[name] unless @_collections[name].nil?
|
13
|
+
|
14
|
+
@_collections[name] = new(name)
|
14
15
|
end
|
15
16
|
|
16
17
|
# @return [Array<Author>] authors
|
17
18
|
def all
|
18
|
-
return [] unless defined?(
|
19
|
-
|
19
|
+
return [] unless defined?(@_collections)
|
20
|
+
|
21
|
+
@_collections.sort.map(&:last) # sort and take values
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
@@ -46,9 +48,9 @@ module Ballantine
|
|
46
48
|
"*#{repo}*: #{count} new #{word}\n#{lists.join("\n")}"
|
47
49
|
end.join("\n")
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
51
|
+
{
|
52
|
+
"text" => "- <@#{name}>\n#{message}",
|
53
|
+
"color" => "#00B86A", # green
|
52
54
|
}
|
53
55
|
end
|
54
56
|
|
@@ -58,7 +60,7 @@ module Ballantine
|
|
58
60
|
# @param [Array(Integer, String)] count, word
|
59
61
|
def retrieve_count_and_word(lists)
|
60
62
|
count = lists.size
|
61
|
-
word = count == 1 ?
|
63
|
+
word = count == 1 ? "commit" : "commits"
|
62
64
|
[count, word]
|
63
65
|
end
|
64
66
|
end
|
data/lib/ballantine/cli.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Ballantine
|
4
4
|
class CLI < Thor
|
@@ -13,115 +13,110 @@ module Ballantine
|
|
13
13
|
'^ssh://git@(.+)/(.+)/(.+)\.git$', # protocol: ssh -> ssh://git@github.com/oohyun15/ballantine.git
|
14
14
|
].freeze
|
15
15
|
|
16
|
-
FILE_GITMODULES =
|
16
|
+
FILE_GITMODULES = ".gitmodules"
|
17
17
|
|
18
|
-
TYPE_TERMINAL =
|
19
|
-
TYPE_SLACK =
|
18
|
+
TYPE_TERMINAL = "terminal"
|
19
|
+
TYPE_SLACK = "slack"
|
20
20
|
|
21
21
|
DEFAULT_LJUST = 80
|
22
22
|
|
23
23
|
attr_reader :app_name, :main_path, :sub_path, :send_type
|
24
24
|
|
25
|
-
|
25
|
+
class << self
|
26
|
+
def exit_on_failure?; exit(1) end
|
27
|
+
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
package_name "Ballantine"
|
30
|
+
option "force", type: :boolean, aliases: "-f", default: false, desc: "Initialize forcely if already initialized."
|
31
|
+
desc "init", "Initialize ballantine"
|
29
32
|
def init
|
30
|
-
conf.init_file(force: options[
|
33
|
+
conf.init_file(force: options["force"])
|
31
34
|
|
32
35
|
puts "🥃 Initialized ballantine."
|
36
|
+
|
37
|
+
true
|
33
38
|
end
|
34
39
|
|
35
|
-
Config::AVAILABLE_ENVIRONMENTS.each{ |env| option env, type: :boolean, default: false, desc: "Set envirment to `#{env}'." }
|
36
|
-
desc
|
40
|
+
Config::AVAILABLE_ENVIRONMENTS.each { |env| option env, type: :boolean, default: false, desc: "Set envirment to `#{env}'." }
|
41
|
+
desc "config [--env] [KEY] [VALUE]", "Set ballantine's configuration"
|
37
42
|
def config(key = nil, value = nil)
|
38
43
|
# check environment value
|
39
|
-
if Config::AVAILABLE_ENVIRONMENTS.map{ |key| !options[key] }.reduce(:&)
|
40
|
-
raise NotAllowed, "Set environment value (#{Config::AVAILABLE_ENVIRONMENTS.map{ |key| "`--#{key}'" }.join(", ")})"
|
41
|
-
elsif Config::AVAILABLE_ENVIRONMENTS.map{ |key| !!options[key] }.reduce(:&)
|
44
|
+
if Config::AVAILABLE_ENVIRONMENTS.map { |key| !options[key] }.reduce(:&)
|
45
|
+
raise NotAllowed, "Set environment value (#{Config::AVAILABLE_ENVIRONMENTS.map { |key| "`--#{key}'" }.join(", ")})"
|
46
|
+
elsif Config::AVAILABLE_ENVIRONMENTS.map { |key| !!options[key] }.reduce(:&)
|
42
47
|
raise NotAllowed, "Environment value must be unique."
|
43
48
|
end
|
44
|
-
|
49
|
+
|
50
|
+
@env = Config::AVAILABLE_ENVIRONMENTS.find { |key| options[key] }
|
45
51
|
raise AssertionFailed, "Environment value must exist: #{@env}" if @env.nil?
|
46
52
|
|
47
53
|
value ? conf.set_data(key, value) : conf.print_data(key)
|
48
54
|
end
|
49
55
|
|
50
|
-
desc
|
51
|
-
option TYPE_SLACK, type: :boolean, aliases:
|
52
|
-
def diff(
|
53
|
-
|
54
|
-
|
55
|
-
# check argument is tag
|
56
|
-
from = check_tag(from)
|
57
|
-
to = check_tag(to)
|
56
|
+
desc "diff [TARGET] [SOURCE]", "Diff commits between TARGET and SOURCE"
|
57
|
+
option TYPE_SLACK, type: :boolean, aliases: "-s", default: false, desc: "Send to slack using slack webhook URL."
|
58
|
+
def diff(target, source = %x(git rev-parse --abbrev-ref HEAD).chomp)
|
59
|
+
# validate arguments
|
60
|
+
validate(target, source, **options)
|
58
61
|
|
59
62
|
# check commits are newest
|
60
|
-
system
|
63
|
+
system("git pull -f &> /dev/null")
|
61
64
|
|
62
|
-
#
|
63
|
-
|
64
|
-
@app_name = File.basename(`git config --get remote.origin.url`.chomp, '.git')
|
65
|
-
@main_path = Dir.pwd
|
66
|
-
@sub_path = if Dir[FILE_GITMODULES].any?
|
67
|
-
file = File.open(FILE_GITMODULES)
|
68
|
-
lines = file.readlines.map(&:chomp)
|
69
|
-
file.close
|
70
|
-
lines.grep(/path =/).map{ |line| line[/(?<=path \=).*/, 0].strip }.sort
|
71
|
-
else
|
72
|
-
[]
|
73
|
-
end
|
65
|
+
# init instance variables
|
66
|
+
init_variables(**options)
|
74
67
|
|
75
68
|
# find github url, branch
|
76
|
-
|
77
|
-
|
69
|
+
url = github_url(%x(git config --get remote.origin.url).chomp)
|
70
|
+
current_revision = %x(git rev-parse --abbrev-ref HEAD).chomp
|
78
71
|
|
79
72
|
# get commit hash
|
80
|
-
|
81
|
-
|
82
|
-
system
|
73
|
+
from, sub_from = commit_hash(target)
|
74
|
+
to, sub_to = commit_hash(source)
|
75
|
+
system("git checkout #{current_revision} -f &> /dev/null")
|
83
76
|
|
84
77
|
# check commits
|
85
|
-
check_commits(
|
86
|
-
|
78
|
+
check_commits(from, to, url)
|
79
|
+
sub_path.each_with_index do |path, idx|
|
87
80
|
next if sub_from[idx] == sub_to[idx]
|
81
|
+
|
88
82
|
Dir.chdir(path)
|
89
|
-
sub_url = github_url(
|
83
|
+
sub_url = github_url(%x(git config --get remote.origin.url).chomp)
|
90
84
|
check_commits(sub_from[idx], sub_to[idx], sub_url)
|
91
|
-
Dir.chdir(
|
85
|
+
Dir.chdir(main_path)
|
92
86
|
end
|
93
87
|
|
94
|
-
|
88
|
+
# send commits
|
89
|
+
send_commits(target, source, from, to, url)
|
95
90
|
|
96
|
-
exit
|
91
|
+
exit(0)
|
97
92
|
end
|
98
93
|
|
99
|
-
desc
|
94
|
+
desc "version", "Display version information about ballntine"
|
100
95
|
def version
|
101
96
|
puts "ballantine version #{Ballantine::VERSION}"
|
97
|
+
|
98
|
+
Ballantine::VERSION
|
102
99
|
end
|
103
100
|
|
104
101
|
private
|
105
102
|
|
106
|
-
def self.exit_on_failure?; exit 1 end
|
107
|
-
|
108
103
|
def conf; @conf ||= Config.new(@env) end
|
109
104
|
|
110
|
-
# @param [String]
|
111
|
-
# @param [String]
|
105
|
+
# @param [String] target
|
106
|
+
# @param [String] source
|
112
107
|
# @param [Hash] options
|
113
108
|
# @return [NilClass] nil
|
114
|
-
def
|
115
|
-
if Dir[
|
109
|
+
def validate(target, source, **options)
|
110
|
+
if Dir[".git"].empty?
|
116
111
|
raise NotAllowed, "ERROR: There is no \".git\" in #{Dir.pwd}."
|
117
112
|
end
|
118
113
|
|
119
|
-
if (uncommitted =
|
114
|
+
if (uncommitted = %x(git diff HEAD --name-only).split("\n")).any?
|
120
115
|
raise NotAllowed, "ERROR: Uncommitted file exists. stash or commit uncommitted files.\n#{uncommitted.join("\n")}"
|
121
116
|
end
|
122
117
|
|
123
|
-
if
|
124
|
-
raise NotAllowed, "ERROR: target(#{
|
118
|
+
if target == source
|
119
|
+
raise NotAllowed, "ERROR: target(#{target}) and source(#{source}) can't be equal."
|
125
120
|
end
|
126
121
|
|
127
122
|
if options[TYPE_SLACK] && !conf.get_data(Config::KEY_SLACK_WEBHOOK)
|
@@ -131,14 +126,32 @@ module Ballantine
|
|
131
126
|
nil
|
132
127
|
end
|
133
128
|
|
129
|
+
# @param [Hash] options
|
130
|
+
# @return [Boolean]
|
131
|
+
def init_variables(**options)
|
132
|
+
@send_type = options[TYPE_SLACK] ? TYPE_SLACK : TYPE_TERMINAL
|
133
|
+
@app_name = File.basename(%x(git config --get remote.origin.url).chomp, ".git")
|
134
|
+
@main_path = Dir.pwd
|
135
|
+
@sub_path =
|
136
|
+
if Dir[FILE_GITMODULES].any?
|
137
|
+
file = File.open(FILE_GITMODULES)
|
138
|
+
lines = file.readlines.map(&:chomp)
|
139
|
+
file.close
|
140
|
+
lines.grep(/path =/).map { |line| line[/(?<=path \=).*/, 0].strip }.sort
|
141
|
+
else
|
142
|
+
[]
|
143
|
+
end
|
144
|
+
true
|
145
|
+
end
|
146
|
+
|
134
147
|
# @param [String] name
|
135
148
|
# @return [String] hash
|
136
149
|
def check_tag(name)
|
137
|
-
list =
|
150
|
+
list = %x(git tag -l).split("\n")
|
138
151
|
return name unless list.grep(name).any?
|
139
152
|
|
140
|
-
system
|
141
|
-
|
153
|
+
system("git fetch origin tag #{name} -f &> /dev/null")
|
154
|
+
%x(git rev-list -n 1 #{name}).chomp[0...7]
|
142
155
|
end
|
143
156
|
|
144
157
|
# @param [String] from
|
@@ -146,13 +159,17 @@ module Ballantine
|
|
146
159
|
# @param [String] url
|
147
160
|
# @return [NilClass] nil
|
148
161
|
def check_commits(from, to, url)
|
149
|
-
repo = File.basename(
|
150
|
-
names =
|
151
|
-
authors = names.map{ |name| Author.find_or_create_by(name) }
|
162
|
+
repo = File.basename(%x(git config --get remote.origin.url).chomp, ".git")
|
163
|
+
names = %x(git --no-pager log --pretty=format:"%an" #{from}..#{to}).split("\n").uniq.sort
|
164
|
+
authors = names.map { |name| Author.find_or_create_by(name) }
|
152
165
|
authors.each do |author|
|
153
166
|
format = commit_format(url, ljust: DEFAULT_LJUST - 10)
|
154
|
-
commits =
|
167
|
+
commits =
|
168
|
+
%x(git --no-pager log --reverse --no-merges --author="#{author.name}" --format="#{format}" --abbrev=7 #{from}..#{to})
|
169
|
+
.gsub('"', '\"')
|
170
|
+
.gsub(/[\u0080-\u00ff]/, "")
|
155
171
|
next if commits.empty?
|
172
|
+
|
156
173
|
author.commits[repo] = commits.split("\n")
|
157
174
|
end
|
158
175
|
nil
|
@@ -171,17 +188,20 @@ module Ballantine
|
|
171
188
|
end
|
172
189
|
|
173
190
|
# @param [String] hash
|
174
|
-
# @param [Array<String>] sub_path
|
175
191
|
# @return [Array(String, Array<String>)] main, sub's hash
|
176
192
|
def commit_hash(hash)
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
193
|
+
# check argument is tag
|
194
|
+
hash = check_tag(hash)
|
195
|
+
|
196
|
+
system("git checkout #{hash} -f &> /dev/null")
|
197
|
+
system("git pull &> /dev/null")
|
198
|
+
main_hash = %x(git --no-pager log -1 --format='%h').chomp
|
199
|
+
sub_hash =
|
200
|
+
if sub_path.any?
|
201
|
+
%x(git ls-tree HEAD #{@sub_path.join(" ")}).split("\n").map { |line| line.split(" ")[2] }
|
202
|
+
else
|
203
|
+
[]
|
204
|
+
end
|
185
205
|
|
186
206
|
[main_hash, sub_hash]
|
187
207
|
end
|
@@ -190,55 +210,58 @@ module Ballantine
|
|
190
210
|
# @param [String] format
|
191
211
|
# @param [Integer] ljust
|
192
212
|
def commit_format(url, ljust: DEFAULT_LJUST)
|
193
|
-
case
|
213
|
+
case send_type
|
194
214
|
when TYPE_TERMINAL
|
195
|
-
" - "+ "%h".yellow + " %<(#{ljust})%s " + "#{url}/commit/%H".gray
|
215
|
+
" - " + "%h".yellow + " %<(#{ljust})%s " + "#{url}/commit/%H".gray
|
196
216
|
when TYPE_SLACK
|
197
217
|
"\\\`<#{url}/commit/%H|%h>\\\` %s - %an"
|
198
|
-
else raise AssertionFailed, "Unknown send type: #{
|
218
|
+
else raise AssertionFailed, "Unknown send type: #{send_type}"
|
199
219
|
end
|
200
220
|
end
|
201
221
|
|
222
|
+
# @param [String] target
|
223
|
+
# @param [String] source
|
202
224
|
# @param [String] from
|
203
225
|
# @param [String] to
|
204
226
|
# @param [String] url
|
205
227
|
# @return [NilClass] nil
|
206
|
-
def send_commits(from, to, url)
|
228
|
+
def send_commits(target, source, from, to, url)
|
207
229
|
authors = Author.all
|
208
230
|
if authors.empty?
|
209
|
-
raise ArgumentError, "ERROR: There is no commits between \"#{
|
231
|
+
raise ArgumentError, "ERROR: There is no commits between \"#{target}\" and \"#{source}\""
|
210
232
|
end
|
233
|
+
|
211
234
|
number = authors.size
|
212
|
-
last_commit =
|
235
|
+
last_commit = %x(git --no-pager log --reverse --format="#{commit_format(url, ljust: DEFAULT_LJUST - 22)}" --abbrev=7 #{from}..#{to} -1).strip
|
213
236
|
|
214
|
-
case
|
237
|
+
case send_type
|
215
238
|
when TYPE_TERMINAL
|
216
|
-
puts "Check commits before #{
|
239
|
+
puts "Check commits before #{app_name.red} deployment. (#{target.cyan} <- #{source.cyan})".ljust(DEFAULT_LJUST + 34) + " #{url}/compare/#{from}...#{to}".gray
|
217
240
|
puts "Author".yellow + ": #{number}"
|
218
241
|
puts "Last commit".blue + ": #{last_commit}"
|
219
242
|
authors.map(&:print_commits)
|
220
243
|
when TYPE_SLACK
|
221
244
|
# set message for each author
|
222
245
|
messages = authors.map(&:serialize_commits)
|
223
|
-
actor =
|
246
|
+
actor = %x(git config user.name).chomp
|
224
247
|
|
225
248
|
# send message to slack
|
226
|
-
require
|
227
|
-
require
|
249
|
+
require "net/http"
|
250
|
+
require "uri"
|
228
251
|
uri = URI.parse(conf.get_data(Config::KEY_SLACK_WEBHOOK))
|
229
252
|
request = Net::HTTP::Post.new(uri)
|
230
|
-
request.content_type =
|
253
|
+
request.content_type = "application/json"
|
231
254
|
request.body = JSON.dump({
|
232
|
-
|
233
|
-
|
255
|
+
"text" => ":white_check_mark: *#{app_name}* deployment request by <@#{actor}> (\`<#{url}/tree/#{from}|#{target}>\` <- \`<#{url}/tree/#{to}|#{source}>\` <#{url}/compare/#{from}...#{to}|compare>)\n:technologist: Author: #{number}\nLast commit: #{last_commit}",
|
256
|
+
"attachments" => messages,
|
234
257
|
})
|
235
|
-
req_options = { use_ssl: uri.scheme ==
|
258
|
+
req_options = { use_ssl: uri.scheme == "https" }
|
236
259
|
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
237
260
|
http.request(request)
|
238
261
|
end
|
239
262
|
puts response.message
|
240
263
|
else
|
241
|
-
raise AssertionFailed, "Unknown send type: #{
|
264
|
+
raise AssertionFailed, "Unknown send type: #{send_type}"
|
242
265
|
end
|
243
266
|
end
|
244
267
|
end
|
data/lib/ballantine/config.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Ballantine
|
4
4
|
class Config
|
5
|
-
ENV_LOCAL =
|
6
|
-
ENV_GLOBAL =
|
5
|
+
ENV_LOCAL = "local"
|
6
|
+
ENV_GLOBAL = "global"
|
7
7
|
AVAILABLE_ENVIRONMENTS = [
|
8
8
|
ENV_LOCAL,
|
9
|
-
ENV_GLOBAL
|
9
|
+
ENV_GLOBAL,
|
10
10
|
].freeze
|
11
11
|
|
12
|
-
KEY_SLACK_WEBHOOK =
|
12
|
+
KEY_SLACK_WEBHOOK = "slack_webhook"
|
13
13
|
AVAILABLE_KEYS = [
|
14
|
-
KEY_SLACK_WEBHOOK
|
14
|
+
KEY_SLACK_WEBHOOK,
|
15
15
|
].freeze
|
16
16
|
|
17
|
-
FILE_BALLANTINE_CONFIG =
|
17
|
+
FILE_BALLANTINE_CONFIG = ".ballantine.json"
|
18
18
|
|
19
19
|
attr_reader :env, :data, :loaded
|
20
20
|
|
@@ -41,6 +41,7 @@ module Ballantine
|
|
41
41
|
|
42
42
|
JSON.parse(File.read(file_path)).each do |key, value|
|
43
43
|
next unless AVAILABLE_KEYS.include?(key)
|
44
|
+
|
44
45
|
@data[key] = value
|
45
46
|
end
|
46
47
|
|
@@ -55,6 +56,7 @@ module Ballantine
|
|
55
56
|
|
56
57
|
if key
|
57
58
|
raise InvalidParameter, "Key must be within #{AVAILABLE_KEYS}" unless AVAILABLE_KEYS.include?(key)
|
59
|
+
|
58
60
|
puts @data[key]
|
59
61
|
else
|
60
62
|
@data.each do |key, value|
|
data/lib/ballantine/version.rb
CHANGED
data/lib/ballantine.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require "json"
|
5
|
+
require_relative "string"
|
5
6
|
require_relative "ballantine/version"
|
6
|
-
require_relative
|
7
|
-
require_relative
|
7
|
+
require_relative "ballantine/config"
|
8
|
+
require_relative "ballantine/author"
|
8
9
|
require_relative "ballantine/cli"
|
9
10
|
|
10
11
|
module Ballantine
|
data/lib/string.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ballantine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4.pre.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- oohyun15
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -58,7 +58,7 @@ homepage: https://github.com/oohyun15/ballantine
|
|
58
58
|
licenses:
|
59
59
|
- MIT
|
60
60
|
metadata: {}
|
61
|
-
post_install_message:
|
61
|
+
post_install_message:
|
62
62
|
rdoc_options: []
|
63
63
|
require_paths:
|
64
64
|
- lib
|
@@ -66,15 +66,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
66
|
requirements:
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: '3.1'
|
70
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- - "
|
72
|
+
- - ">"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
74
|
+
version: 1.3.1
|
75
75
|
requirements: []
|
76
|
-
rubygems_version: 3.3.
|
77
|
-
signing_key:
|
76
|
+
rubygems_version: 3.3.26
|
77
|
+
signing_key:
|
78
78
|
specification_version: 4
|
79
79
|
summary: Describe your commits.
|
80
80
|
test_files: []
|