trollolo 0.1.1 → 0.2.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 +4 -4
- data/.rubocop.yml +21 -2
- data/.rubocop_todo.yml +105 -270
- data/CHANGELOG.md +10 -0
- data/CONTRIBUTING.md +6 -4
- data/Gemfile +1 -1
- data/README.md +10 -1
- data/Rakefile +4 -4
- data/bin/trollolo +2 -2
- data/lib/backup.rb +21 -23
- data/lib/burndown_chart.rb +46 -49
- data/lib/burndown_data.rb +21 -21
- data/lib/card.rb +23 -32
- data/lib/checklist.rb +13 -1
- data/lib/cli.rb +105 -110
- data/lib/column.rb +11 -10
- data/lib/empty_column.rb +2 -2
- data/lib/scrum/backlog_mover.rb +3 -3
- data/lib/scrum/card_type_detection.rb +1 -1
- data/lib/scrum/creator.rb +7 -7
- data/lib/scrum/prioritizer.rb +1 -1
- data/lib/scrum/sprint_board.rb +4 -4
- data/lib/scrum/sprint_cleaner.rb +3 -3
- data/lib/scrum/sprint_planning_board.rb +2 -4
- data/lib/scrum_board.rb +3 -3
- data/lib/settings.rb +29 -27
- data/lib/trello_service.rb +1 -1
- data/lib/trello_wrapper.rb +9 -9
- data/lib/version.rb +1 -1
- data/spec/data/card.json +19 -0
- data/spec/data/trollolorc +3 -0
- data/spec/integration/command_line_spec.rb +14 -14
- data/spec/integration/create_burndown_spec.rb +25 -25
- data/spec/integration/integration_spec_helper.rb +1 -1
- data/spec/integration/wrapper/credentials_input_wrapper +7 -11
- data/spec/integration/wrapper/empty_config_trollolo_wrapper +2 -2
- data/spec/integration/wrapper/trollolo_wrapper +2 -2
- data/spec/unit/backup_spec.rb +14 -14
- data/spec/unit/burndown_chart_spec.rb +176 -184
- data/spec/unit/burndown_data_spec.rb +21 -23
- data/spec/unit/card_spec.rb +38 -24
- data/spec/unit/cli_spec.rb +57 -57
- data/spec/unit/empty_column_spec.rb +1 -1
- data/spec/unit/retrieve_data_spec.rb +13 -13
- data/spec/unit/scrum/backlog_mover_spec.rb +8 -8
- data/spec/unit/scrum/card_type_detection_spec.rb +12 -12
- data/spec/unit/scrum/creator_spec.rb +8 -8
- data/spec/unit/scrum/prioritizer_spec.rb +19 -19
- data/spec/unit/scrum/priority_name_spec.rb +16 -16
- data/spec/unit/scrum/sprint_board_spec.rb +3 -3
- data/spec/unit/scrum/sprint_cleaner_spec.rb +15 -15
- data/spec/unit/scrum/sprint_planning_board_spec.rb +2 -2
- data/spec/unit/scrum_board_spec.rb +56 -56
- data/spec/unit/settings_spec.rb +23 -23
- data/spec/unit/spec_helper.rb +3 -3
- data/spec/unit/support/test_data_operations.rb +4 -0
- data/spec/unit/support/update_webmock_data +9 -11
- data/spec/unit/support/vcr.rb +3 -3
- data/spec/unit/support/webmocks.rb +21 -12
- data/spec/unit/trello_wrapper_spec.rb +40 -29
- data/trollolo.gemspec +3 -3
- metadata +8 -5
data/spec/unit/settings_spec.rb
CHANGED
@@ -4,58 +4,58 @@ describe Settings do
|
|
4
4
|
|
5
5
|
include GivenFilesystemSpecHelpers
|
6
6
|
|
7
|
-
context
|
7
|
+
context 'given config file' do
|
8
8
|
before(:each) do
|
9
9
|
@settings = Settings.new( File.expand_path('../../data/trollolorc', __FILE__) )
|
10
10
|
end
|
11
11
|
|
12
|
-
it
|
12
|
+
it 'is not verbose by default' do
|
13
13
|
expect(@settings.verbose).to be false
|
14
14
|
end
|
15
15
|
|
16
|
-
it
|
17
|
-
expect(@settings.developer_public_key).to eq
|
18
|
-
expect(@settings.member_token).to eq
|
16
|
+
it 'reads config file' do
|
17
|
+
expect(@settings.developer_public_key).to eq 'mykey'
|
18
|
+
expect(@settings.member_token).to eq 'mytoken'
|
19
19
|
end
|
20
20
|
|
21
|
-
context
|
22
|
-
context
|
21
|
+
context '#scrum' do
|
22
|
+
context 'when setting is missing' do
|
23
23
|
before do
|
24
24
|
@settings = Settings.new( File.expand_path('../../data/trollolorc_with_board_aliases', __FILE__) )
|
25
25
|
end
|
26
|
-
it
|
27
|
-
expect(@settings.scrum[
|
26
|
+
it 'returns default settings' do
|
27
|
+
expect(@settings.scrum['board_names']).to eq('planning' => 'Planning Board', 'sprint' => 'Sprint Board')
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
context
|
32
|
-
it
|
33
|
-
expect(@settings.scrum[
|
34
|
-
expect(@settings.scrum.board_names[
|
31
|
+
context 'when setting does exist' do
|
32
|
+
it 'returns name' do
|
33
|
+
expect(@settings.scrum['board_names']['sprint']).to eq('Sprint Board')
|
34
|
+
expect(@settings.scrum.board_names['planning']).to eq('Planning Board')
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
context
|
40
|
-
context
|
41
|
-
it
|
39
|
+
context '#board_aliases' do
|
40
|
+
context 'when aliases do not exist' do
|
41
|
+
it 'returns an empty Hash' do
|
42
42
|
expect(@settings.board_aliases).to eq({})
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
context
|
46
|
+
context 'when mapping exists' do
|
47
47
|
before do
|
48
48
|
@settings = Settings.new( File.expand_path('../../data/trollolorc_with_board_aliases', __FILE__) )
|
49
49
|
end
|
50
50
|
|
51
|
-
it
|
52
|
-
expect(@settings.board_aliases).to eq(
|
51
|
+
it 'returns the mapping' do
|
52
|
+
expect(@settings.board_aliases).to eq('MyTrelloBoard' => '53186e8391ef8671265eba9d')
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
context
|
58
|
+
context 'non-existent config file' do
|
59
59
|
use_given_filesystem
|
60
60
|
|
61
61
|
before(:each) do
|
@@ -63,9 +63,9 @@ describe Settings do
|
|
63
63
|
@settings = Settings.new(@config_file)
|
64
64
|
end
|
65
65
|
|
66
|
-
it
|
67
|
-
@settings.developer_public_key =
|
68
|
-
@settings.member_token =
|
66
|
+
it 'saves config file' do
|
67
|
+
@settings.developer_public_key = 'mypublickey'
|
68
|
+
@settings.member_token = 'mymembertoken'
|
69
69
|
@settings.save_config
|
70
70
|
|
71
71
|
expect(File.read(@config_file)).to eq "---\ndeveloper_public_key: mypublickey\nmember_token: mymembertoken\n"
|
data/spec/unit/spec_helper.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
require
|
1
|
+
require 'simplecov'
|
2
2
|
SimpleCov.start
|
3
3
|
require_relative '../../lib/trollolo'
|
4
4
|
require 'given_filesystem/spec_helpers'
|
5
5
|
require 'webmock/rspec'
|
6
6
|
require 'byebug'
|
7
7
|
require 'pry'
|
8
|
-
WebMock.disable_net_connect!(:
|
8
|
+
WebMock.disable_net_connect!(allow: 'codeclimate.com')
|
9
9
|
|
10
|
-
bin_path = File.expand_path(
|
10
|
+
bin_path = File.expand_path( '../../../bin/', __FILE__ )
|
11
11
|
|
12
12
|
if ENV['PATH'] !~ /#{bin_path}/
|
13
13
|
ENV['PATH'] = bin_path + File::PATH_SEPARATOR + ENV['PATH']
|
@@ -1,24 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'json'
|
4
4
|
|
5
|
-
require_relative
|
5
|
+
require_relative 'webmocks'
|
6
6
|
|
7
|
-
trollolo_bin = File.expand_path(
|
8
|
-
spec_data_dir = File.expand_path(
|
7
|
+
trollolo_bin = File.expand_path('../../../../bin/trollolo', __FILE__)
|
8
|
+
spec_data_dir = File.expand_path('../../../data', __FILE__)
|
9
9
|
|
10
|
-
STDERR.puts
|
10
|
+
STDERR.puts 'Updating web mock data'
|
11
11
|
|
12
12
|
def scrub_file(file)
|
13
13
|
json = JSON.parse(File.read(file))
|
14
|
-
if json.is_a?(Hash) && json.
|
15
|
-
json[
|
16
|
-
if card.
|
17
|
-
card["email"] = "trello@example.com"
|
18
|
-
end
|
14
|
+
if json.is_a?(Hash) && json.key?('cards')
|
15
|
+
json['cards'].each do |card|
|
16
|
+
card['email'] = 'trello@example.com' if card.key?('email')
|
19
17
|
end
|
20
18
|
end
|
21
|
-
File.open(file,
|
19
|
+
File.open(file, 'w') do |f|
|
22
20
|
f.write(JSON.pretty_generate(json))
|
23
21
|
end
|
24
22
|
end
|
data/spec/unit/support/vcr.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'vcr'
|
2
2
|
VCR.configure do |config|
|
3
|
-
config.cassette_library_dir =
|
3
|
+
config.cassette_library_dir = 'spec/data/vcr'
|
4
4
|
config.hook_into :webmock
|
5
5
|
end
|
6
6
|
|
7
7
|
# example needs to use real_settings if vcr_record: true is used
|
8
8
|
def real_settings
|
9
|
-
config_path = ENV[
|
9
|
+
config_path = ENV['TROLLOLO_CONFIG_PATH'] || File.expand_path('~/.trollolorc')
|
10
10
|
Settings.new(config_path)
|
11
11
|
end
|
12
12
|
|
@@ -40,7 +40,7 @@ end
|
|
40
40
|
RSpec.configure do |c|
|
41
41
|
c.around do |example|
|
42
42
|
if (cassette = example.metadata[:vcr])
|
43
|
-
|
43
|
+
raise 'you need to use real_settings to re-record vcr data' if real_settings_needed?(example)
|
44
44
|
VCR.use_cassette(cassette, record: vcr_record_mode(example)) do
|
45
45
|
example.run
|
46
46
|
end
|
@@ -7,27 +7,36 @@ def webmock_mapping
|
|
7
7
|
{
|
8
8
|
path: 'boards/53186e8391ef8671265eba9d/lists',
|
9
9
|
parameters: {
|
10
|
-
|
10
|
+
'filter' => 'open'
|
11
11
|
},
|
12
12
|
file: 'lists.json'
|
13
13
|
},
|
14
14
|
{
|
15
15
|
path: 'boards/53186e8391ef8671265eba9d',
|
16
16
|
parameters: {
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
'cards' => 'open',
|
18
|
+
'lists' => 'open',
|
19
|
+
'card_checklists' => 'all'
|
20
20
|
},
|
21
21
|
file: 'full-board.json'
|
22
22
|
},
|
23
23
|
{
|
24
24
|
path: 'boards/P4kJA4bE',
|
25
25
|
parameters: {
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
'cards' => 'open',
|
27
|
+
'lists' => 'open',
|
28
|
+
'card_checklists' => 'all'
|
29
29
|
},
|
30
30
|
file: 'full-board-with-accepted.json'
|
31
|
+
},
|
32
|
+
{
|
33
|
+
path: 'boards/7Zar7bNm',
|
34
|
+
parameters: {
|
35
|
+
'cards' => 'open',
|
36
|
+
'lists' => 'open',
|
37
|
+
'card_checklists' => 'all'
|
38
|
+
},
|
39
|
+
file: 'full-board.json'
|
31
40
|
}
|
32
41
|
]
|
33
42
|
end
|
@@ -40,22 +49,22 @@ def parameters_as_string(mapping, parameters = nil)
|
|
40
49
|
end
|
41
50
|
end
|
42
51
|
if !parameters.empty?
|
43
|
-
parameters_string =
|
52
|
+
parameters_string = '?' + parameters.join('&')
|
44
53
|
else
|
45
|
-
parameters_string =
|
54
|
+
parameters_string = ''
|
46
55
|
end
|
47
56
|
parameters_string
|
48
57
|
end
|
49
58
|
|
50
59
|
def mapping_url(mapping, parameters = nil)
|
51
|
-
url =
|
60
|
+
url = 'https://api.trello.com/1/' + mapping[:path]
|
52
61
|
url += parameters_as_string(mapping, parameters)
|
53
62
|
end
|
54
63
|
|
55
64
|
def full_board_mock
|
56
65
|
webmock_mapping.each do |mapping|
|
57
|
-
url = mapping_url(mapping, [
|
66
|
+
url = mapping_url(mapping, [ 'key=mykey', 'token=mytoken' ])
|
58
67
|
stub_request(:get, url)
|
59
|
-
.to_return(:
|
68
|
+
.to_return(status: 200, body: load_test_file(mapping[:file]))
|
60
69
|
end
|
61
70
|
end
|
@@ -4,12 +4,12 @@ include GivenFilesystemSpecHelpers
|
|
4
4
|
|
5
5
|
describe TrelloWrapper do
|
6
6
|
|
7
|
-
let!(:settings){ double('settings', developer_public_key:
|
7
|
+
let!(:settings){ double('settings', developer_public_key: 'mykey', member_token: 'mytoken') }
|
8
8
|
subject { described_class.new(settings) }
|
9
9
|
|
10
10
|
before do
|
11
|
-
stub_request(:get,
|
12
|
-
to_return(:
|
11
|
+
stub_request(:get, 'https://api.trello.com/1/boards/myboard?cards=open&key=mykey&lists=open&token=mytoken').
|
12
|
+
to_return(status: 200, body: load_test_file('board.json'), headers: {})
|
13
13
|
full_board_mock
|
14
14
|
end
|
15
15
|
|
@@ -30,26 +30,26 @@ describe TrelloWrapper do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'finds board via Trello' do
|
33
|
-
subject.board(
|
33
|
+
subject.board('myboard')
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'instantiate ScrumBoard with trello board and settings' do
|
37
37
|
expect(ScrumBoard).to receive(:new).with(:board, subject.instance_variable_get(:@settings))
|
38
|
-
subject.board(
|
38
|
+
subject.board('myboard')
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'returns instance of a ScrumBoard' do
|
42
|
-
expect(subject.board(
|
42
|
+
expect(subject.board('myboard')).to be_instance_of(ScrumBoard)
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'memoize board object' do
|
46
|
-
expect(subject.board(
|
46
|
+
expect(subject.board('myboard')).to be subject.board('myboard')
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
describe '#backup' do
|
51
51
|
it 'raises an error for empty board id' do
|
52
|
-
expect { subject.backup(
|
52
|
+
expect { subject.backup('') }.to raise_error(TrolloloError)
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'raises an error for nil board id' do
|
@@ -70,7 +70,7 @@ describe TrelloWrapper do
|
|
70
70
|
describe '#add_attachment' do
|
71
71
|
use_given_filesystem
|
72
72
|
|
73
|
-
it
|
73
|
+
it 'uploads attachment' do
|
74
74
|
srand(1) # Make sure multipart boundary is always the same
|
75
75
|
|
76
76
|
card_body = <<EOT
|
@@ -80,26 +80,31 @@ describe TrelloWrapper do
|
|
80
80
|
}
|
81
81
|
EOT
|
82
82
|
|
83
|
-
stub_request(:get,
|
84
|
-
with(:
|
85
|
-
to_return(:
|
83
|
+
stub_request(:get, 'https://api.trello.com/1/cards/123?key=mykey&token=mytoken').
|
84
|
+
with(headers: {'Accept' => '*/*; q=0.5, application/xml', 'Accept-Encoding' => 'gzip, deflate', 'User-Agent' => 'Ruby'}).
|
85
|
+
to_return(status: 200, body: card_body, headers: {})
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
headers = {'Accept' => '*/*; q=0.5, application/xml',
|
88
|
+
'Accept-Encoding' => 'gzip, deflate',
|
89
|
+
'Content-Length' => '188',
|
90
|
+
'Content-Type' => 'multipart/form-data; boundary=470924',
|
91
|
+
'User-Agent' => 'Ruby'}
|
90
92
|
|
91
|
-
|
93
|
+
stub_request(:post, 'https://api.trello.com/1/cards/123/attachments?key=mykey&token=mytoken').
|
94
|
+
with(headers: headers).to_return(status: 200, body: '', headers: {})
|
92
95
|
|
93
|
-
|
96
|
+
path = given_file('attachment-data')
|
97
|
+
|
98
|
+
subject.add_attachment('123', path)
|
94
99
|
end
|
95
100
|
end
|
96
101
|
|
97
|
-
describe
|
98
|
-
let(:card_id) {
|
99
|
-
let(:image_id) {
|
100
|
-
let(:image_name) {
|
102
|
+
describe '#make_cover' do
|
103
|
+
let(:card_id) { 'c133a484cff21c7a33ff031f' }
|
104
|
+
let(:image_id) { '484cff21c7a33ff031f997a' }
|
105
|
+
let(:image_name) { 'passed.jpg' }
|
101
106
|
let(:client) { double }
|
102
|
-
let(:card_attachments_body)
|
107
|
+
let(:card_attachments_body) do <<-EOF
|
103
108
|
[
|
104
109
|
{
|
105
110
|
"id":"78d86ae7f25c748559b37ca",
|
@@ -111,23 +116,29 @@ EOT
|
|
111
116
|
}
|
112
117
|
]
|
113
118
|
EOF
|
114
|
-
|
119
|
+
end
|
115
120
|
|
116
121
|
before(:each) do
|
117
122
|
stub_request(:get, "https://api.trello.com/1/cards/#{card_id}/attachments?fields=name&key=mykey&token=mytoken").
|
118
|
-
with(:
|
119
|
-
to_return(:
|
123
|
+
with(headers: {'Accept' => '*/*; q=0.5, application/xml', 'Accept-Encoding' => 'gzip, deflate', 'User-Agent' => 'Ruby'}).
|
124
|
+
to_return(status: 200, body: card_attachments_body, headers: {})
|
125
|
+
headers = {'Accept' => '*/*; q=0.5, application/xml',
|
126
|
+
'Accept-Encoding' => 'gzip, deflate',
|
127
|
+
'Content-Length' => '0',
|
128
|
+
'Content-Type' => 'application/x-www-form-urlencoded',
|
129
|
+
'User-Agent' => 'Ruby'}
|
130
|
+
|
120
131
|
stub_request(:put, "https://api.trello.com/1/cards/#{card_id}/idAttachmentCover?key=mykey&token=mytoken&value=#{image_id}").
|
121
|
-
with(:headers
|
132
|
+
with(headers: headers)
|
122
133
|
end
|
123
134
|
|
124
|
-
it
|
135
|
+
it 'make the attachment with the file name passed.jpg the cover' do
|
125
136
|
subject.make_cover(card_id, image_name)
|
126
137
|
expect(WebMock).to have_requested(:put, "https://api.trello.com/1/cards/#{card_id}/idAttachmentCover?key=mykey&token=mytoken&value=#{image_id}")
|
127
138
|
end
|
128
139
|
|
129
|
-
it
|
130
|
-
expect { subject.make_cover(card_id,
|
140
|
+
it 'shows an error if the file was not found in the attachment list' do
|
141
|
+
expect { subject.make_cover(card_id, 'non_existing_file.jpg') }.to raise_error(/non_existing_file.jpg/)
|
131
142
|
end
|
132
143
|
end
|
133
144
|
end
|
data/trollolo.gemspec
CHANGED
@@ -4,7 +4,7 @@ require File.expand_path('../lib/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'trollolo'
|
6
6
|
s.version = Trollolo::VERSION
|
7
|
-
s.license = 'GPL-3'
|
7
|
+
s.license = 'GPL-3.0'
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ['Cornelius Schumacher']
|
10
10
|
s.email = ['cschum@suse.de']
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = 'Trello command line client'
|
13
13
|
s.description = 'Trollolo is a command line tool to access Trello and support tasks like generation of burndown charts.'
|
14
14
|
|
15
|
-
s.required_ruby_version = '>= 2.2'
|
15
|
+
s.required_ruby_version = ['>= 2.2.0', '< 2.4.2']
|
16
16
|
s.required_rubygems_version = '>= 1.3.6'
|
17
17
|
s.rubyforge_project = 'trollolo'
|
18
18
|
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.add_dependency 'ruby-trello', '~> 1.5.0'
|
21
21
|
|
22
22
|
s.files = `git ls-files`.split("\n")
|
23
|
-
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ?
|
23
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? Regexp.last_match(1) : nil}.compact
|
24
24
|
s.require_path = 'lib'
|
25
25
|
|
26
26
|
s.files += Dir['man/*.?'] # UNIX man pages
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trollolo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cornelius Schumacher
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -171,7 +171,7 @@ files:
|
|
171
171
|
- yes_ship_it.conf
|
172
172
|
homepage: https://github.com/openSUSE/trollolo
|
173
173
|
licenses:
|
174
|
-
- GPL-3
|
174
|
+
- GPL-3.0
|
175
175
|
metadata: {}
|
176
176
|
post_install_message:
|
177
177
|
rdoc_options: []
|
@@ -181,7 +181,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
181
|
requirements:
|
182
182
|
- - ">="
|
183
183
|
- !ruby/object:Gem::Version
|
184
|
-
version:
|
184
|
+
version: 2.2.0
|
185
|
+
- - "<"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: 2.4.2
|
185
188
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
189
|
requirements:
|
187
190
|
- - ">="
|
@@ -189,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
189
192
|
version: 1.3.6
|
190
193
|
requirements: []
|
191
194
|
rubyforge_project: trollolo
|
192
|
-
rubygems_version: 2.
|
195
|
+
rubygems_version: 2.5.2.1
|
193
196
|
signing_key:
|
194
197
|
specification_version: 4
|
195
198
|
summary: Trello command line client
|