cyclid-client 0.4.0 → 0.4.1

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
  SHA1:
3
- metadata.gz: 078b4e179f24bb0cd378bcd6993fd834bdcb4555
4
- data.tar.gz: 0abab651a16850f267229149a11ebd59e58b089e
3
+ metadata.gz: d4d1024367f882c7fafb1ae3080d8d324c4552c6
4
+ data.tar.gz: 2ff1efb950368d68163c345f81b2de8cf034b202
5
5
  SHA512:
6
- metadata.gz: 6635460d43ba93794cf903263d3b0f6341965b79cdd17ef5b1f5c06b5a42df653205c0c997039198a88f55c1ba143397c7f03f70037208e2db305cbf17108026
7
- data.tar.gz: 696dd68c6329ac1159616b6174445543ab0c9ee162e2b1f0c9404a3401cdea245b505eed71e76d5c4eecea013f77707f71d84316289ae801ada9b711a495672b
6
+ metadata.gz: ed3506d6b65119d0cf36d032e88768ca1ba7cb1ed514e98ecafdb1362aa13efd49c0c271dd989e8353bf6b20ebf501faf08772ea9a5a0428e0360b569347ec8c
7
+ data.tar.gz: d0fdf7cea01e01d6c0f077cb8a0bac01b7739f44d4211417c5df7a0c604fbe262ceeb3f14046baeb34e47182e782f0beb4f9e8634dde36ca63e6298a1a973b20
data/bin/cyclid CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
+
3
4
  # Copyright 2016 Liqwyd Ltd.
4
5
  #
5
6
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -31,6 +32,8 @@ module Cyclid
31
32
  Kernel.puts t + args.join
32
33
  end
33
34
  alias colorize puts
35
+ alias warning puts
36
+ alias error puts
34
37
 
35
38
  def ask(question)
36
39
  print "#{question}: "
@@ -42,16 +45,30 @@ module Cyclid
42
45
  class Terminal < Base
43
46
  class << self
44
47
  def colorize(title, *args)
48
+ puts_with_color(:cyan, title, args)
49
+ end
50
+
51
+ def warning(title, *args)
52
+ puts_with_color(:yellow, title, args)
53
+ end
54
+
55
+ def error(title, *args)
56
+ puts_with_color(:red, title, args)
57
+ end
58
+
59
+ def ask(question)
60
+ print "#{question}: ".colorize(:red)
61
+ end
62
+
63
+ private
64
+
65
+ def puts_with_color(color, title, *args)
45
66
  t = if args.empty?
46
67
  title
47
68
  else
48
69
  "#{title}: "
49
70
  end
50
- Kernel.puts t.colorize(:cyan) + args.join
51
- end
52
-
53
- def ask(question)
54
- print "#{question}: ".colorize(:red)
71
+ Kernel.puts t.colorize(color) + args.join
55
72
  end
56
73
  end
57
74
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,6 +18,8 @@ require 'yaml'
17
18
  require 'json'
18
19
  require 'cyclid/constants'
19
20
 
21
+ require_relative 'linter'
22
+
20
23
  module Cyclid
21
24
  module Cli
22
25
  # 'job' sub-command
@@ -33,36 +36,12 @@ module Cyclid
33
36
 
34
37
  The --json option causes the job file to be parsed as JSON.
35
38
  LONGDESC
36
- option :yaml, aliases: '-y'
37
- option :json, aliases: '-j'
39
+ option :yaml, type: :boolean, aliases: '-y', desc: 'Force the input file type to YAML'
40
+ option :json, type: :boolean, aliases: '-j', desc: 'Force the input file type to JSON'
38
41
  def submit(filename)
39
- job_file = File.expand_path(filename)
40
- raise 'Cannot open file' unless File.exist?(job_file)
41
-
42
- job_type = if options[:yaml]
43
- 'yaml'
44
- elsif options[:json]
45
- 'json'
46
- else
47
- # Detect format
48
- match = job_file.match(/\A.*\.(json|yml|yaml)\z/)
49
- match[1]
50
- end
51
- job_type = 'yaml' if job_type == 'yml'
42
+ job_data, job_type = load_job_file(filename)
52
43
 
53
- # Do a client-side sanity check by attempting to parse the file; we
54
- # don't do anything with the data but it fails-fast if the file has a
55
- # syntax error
56
- job = File.read(job_file)
57
- if job_type == 'yaml'
58
- YAML.load(job)
59
- elsif job_type == 'json'
60
- JSON.parse(job)
61
- else
62
- raise 'Unknown or unsupported file type'
63
- end
64
-
65
- job_info = client.job_submit(client.config.organization, job, job_type)
44
+ job_info = client.job_submit(client.config.organization, job_data, job_type)
66
45
  Formatter.colorize 'Job', job_info['job_id'].to_s
67
46
  rescue StandardError => ex
68
47
  abort "Failed to submit job: #{ex}"
@@ -138,6 +117,126 @@ module Cyclid
138
117
  rescue StandardError => ex
139
118
  abort "Failed to get job list: #{ex}"
140
119
  end
120
+
121
+ desc 'lint FILENAME', 'Check your job file for errors'
122
+ long_desc <<-LONGDESC
123
+ Lint a Cyclid job file for errors and potential problems. FILENAME should be the path to a
124
+ valid Cyclid job file, in either YAML or JSON format.
125
+
126
+ Cyclid will attempt to detect the format of the job file automatically. You can force the
127
+ parsing format using either the --yaml or --json options.
128
+
129
+ The --yaml option causes the job file to be parsed as YAML.
130
+
131
+ The --json option causes the job file to be parsed as JSON.
132
+ LONGDESC
133
+ option :yaml, type: :boolean, aliases: '-y', desc: 'Force the input file type to YAML'
134
+ option :json, type: :boolean, aliases: '-j', desc: 'Force the input file type to JSON'
135
+ def lint(filename)
136
+ job = parse_job_file(filename)
137
+
138
+ # Now run the job through the Verifier to find problems
139
+ verifier = RemoteVerifier.new(client: client)
140
+ verifier.verify(job)
141
+
142
+ # Display the result summary
143
+ verifier.status.messages.each do |message|
144
+ case message[:type]
145
+ when Cyclid::Linter::StatusLogger::MessageTypes::WARNING
146
+ Formatter.warning 'Warning', message[:text]
147
+ when Cyclid::Linter::StatusLogger::MessageTypes::ERROR
148
+ Formatter.error 'Error', message[:text]
149
+ end
150
+ end
151
+
152
+ Formatter.puts ''
153
+ Formatter.error 'Errors', verifier.status.errors \
154
+ unless verifier.status.errors.zero?
155
+ Formatter.warning 'Warnings', verifier.status.warnings \
156
+ unless verifier.status.warnings.zero?
157
+
158
+ # Finish with an exit code of 1 if there were problems
159
+ exit 1 unless verifier.status.errors.zero? && verifier.status.warnings.zero?
160
+ end
161
+
162
+ desc 'format FILENAME', 'Re-format or convert your job file'
163
+ long_desc <<-LONGDESC
164
+ Pretty-format a Cyclid job file. FILENAME should be the path to a valid Cyclid job file,
165
+ in either YAML or JSON format. The output format can be YAML or JSON, regardless of the
166
+ input format.
167
+
168
+ Cyclid will attempt to detect the format of the job file automatically. You can force the
169
+ parsing format using either the --yaml or --json options.
170
+
171
+ The --yaml option causes the job file to be parsed as YAML.
172
+
173
+ The --json option causes the job file to be parsed as JSON.
174
+
175
+ The --yamlout option sets the output format the YAML.
176
+
177
+ The --jsonout option sets the output format the JSON.
178
+ LONGDESC
179
+
180
+ option :yaml, type: :boolean, aliases: '-y', desc: 'Force the input file type to YAML'
181
+ option :json, type: :boolean, aliases: '-j', desc: 'Force the input file type to JSON'
182
+ option :yamlout, type: :boolean, aliases: '-Y', desc: 'Set the output format to YAML'
183
+ option :jsonout, type: :boolean,
184
+ aliases: '-J',
185
+ desc: 'Set the input format to JSON',
186
+ default: true
187
+ def format(filename)
188
+ job = parse_job_file(filename)
189
+
190
+ # Re-emit; Oj & YAML are nice and trustworthy in that they wont re-order objects. This
191
+ # means that we can nicely indent, or convert, without worrying that things like the
192
+ # Sequence is going to get re-ordered.
193
+ #
194
+ # The downside is that we can't force things like ordering of top-level elements,
195
+ # although users may consider that an advantage.
196
+ if options[:yamlout]
197
+ puts YAML.dump(job)
198
+ else
199
+ puts Oj.dump(job, indent: 2)
200
+ end
201
+ end
202
+
203
+ private
204
+
205
+ # Load a Cyclid job file, including format detection
206
+ def load_job_file(filename)
207
+ job_file = File.expand_path(filename)
208
+ raise 'Cannot open file' unless File.exist?(job_file)
209
+
210
+ job_type = if options[:yaml]
211
+ 'yaml'
212
+ elsif options[:json]
213
+ 'json'
214
+ else
215
+ # Detect format
216
+ match = job_file.match(/\A.*\.(json|yml|yaml)\z/)
217
+ match[1]
218
+ end
219
+ job_type = 'yaml' if job_type == 'yml'
220
+
221
+ # Attempt to load & parse the job file; any JSON or YAML syntax errors
222
+ # will be caught here
223
+ job_data = File.read(job_file)
224
+
225
+ [job_data, job_type]
226
+ end
227
+
228
+ # Load and parse a Cyclid job file
229
+ def parse_job_file(filename)
230
+ job_data, job_type = load_job_file(filename)
231
+
232
+ if job_type == 'yaml'
233
+ YAML.safe_load(job_data)
234
+ elsif job_type == 'json'
235
+ JSON.parse(job_data)
236
+ else
237
+ raise 'Unknown or unsupported file type'
238
+ end
239
+ end
141
240
  end
142
241
  end
143
242
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2017 Liqwyd Ltd.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'yaml'
18
+ require 'json'
19
+ require 'cyclid/linter'
20
+
21
+ module Cyclid
22
+ module Cli
23
+ # Verify by fetching Stages from a remote server
24
+ class RemoteVerifier < Cyclid::Linter::Verifier
25
+ def initialize(args)
26
+ @client = args[:client]
27
+
28
+ super
29
+ end
30
+
31
+ # Find a Stage by it's name on a remote server
32
+ def stage_exists?(name)
33
+ @client.stage_get(@client.config.organization, name)
34
+
35
+ Bertrand::EXIST
36
+ rescue StandardError => ex
37
+ if ex.to_s == 'stage does not exist'
38
+ Bertrand::NOT_EXIST
39
+ else
40
+ Bertrand::UNKNOWN
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -63,8 +64,8 @@ module Cyclid
63
64
 
64
65
  The --json option causes the file to be parsed as JSON.
65
66
  LONGDESC
66
- option :yaml, aliases: '-y'
67
- option :json, aliases: '-j'
67
+ option :yaml, type: :boolean, aliases: '-y', desc: 'Force the input file type to YAML'
68
+ option :json, type: :boolean, aliases: '-j', desc: 'Force the input file type to JSON'
68
69
  option :version, aliases: '-v'
69
70
  def create(filename)
70
71
  stage_file = File.expand_path(filename)
@@ -85,7 +86,7 @@ module Cyclid
85
86
  # will fail-fast if the file has a syntax error
86
87
  stage = File.read(stage_file)
87
88
  stage_data = if stage_type == 'yaml'
88
- YAML.load(stage)
89
+ YAML.safe_load(stage)
89
90
  elsif stage_type == 'json'
90
91
  JSON.parse(stage)
91
92
  else
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -80,6 +81,7 @@ module Cyclid
80
81
  def api_request(uri, req)
81
82
  http = Net::HTTP.new(uri.hostname, uri.port)
82
83
  http.use_ssl = uri.scheme == 'https'
84
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @config.ssl_verify_none
83
85
 
84
86
  res = http.request(req)
85
87
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -42,7 +43,7 @@ module Cyclid
42
43
  nonce = SecureRandom.hex
43
44
  headers = signer.sign_request(uri.path,
44
45
  @config.secret,
45
- auth_header_format: '%{auth_scheme} %{username}:%{signature}', # rubocop:disable Metrics/LineLength
46
+ auth_header_format: '%<auth_scheme>s %<username>s:%<signature>s', # rubocop:disable Metrics/LineLength
46
47
  username: @config.username,
47
48
  nonce: nonce,
48
49
  method: method)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -66,13 +67,15 @@ module Cyclid
66
67
  user['secret'] = secret unless secret.nil?
67
68
 
68
69
  # Add the password if one was supplied
69
- user['password'] = if password =~ /\A\$2a\$.+\z/
70
- # Password is already encrypted
71
- password
72
- else
73
- # Encrypt the plaintext password
74
- BCrypt::Password.create(password).to_s
75
- end unless password.nil?
70
+ unless password.nil?
71
+ user['password'] = if password =~ /\A\$2a\$.+\z/
72
+ # Password is already encrypted
73
+ password
74
+ else
75
+ # Encrypt the plaintext password
76
+ BCrypt::Password.create(password).to_s
77
+ end
78
+ end
76
79
 
77
80
  @logger.debug user
78
81
 
@@ -114,13 +117,15 @@ module Cyclid
114
117
  user['secret'] = args[:secret] if args.key? :secret and args[:secret]
115
118
 
116
119
  # Add the password if one was supplied
117
- user['password'] = if args[:password] =~ /\A\$2a\$.+\z/
118
- # Password is already encrypted
119
- args[:password]
120
- else
121
- # Encrypt the plaintext password
122
- BCrypt::Password.create(args[:password]).to_s
123
- end if args.key? :password and args[:password]
120
+ if args.key? :password and args[:password]
121
+ user['password'] = if args[:password] =~ /\A\$2a\$.+\z/
122
+ # Password is already encrypted
123
+ args[:password]
124
+ else
125
+ # Encrypt the plaintext password
126
+ BCrypt::Password.create(args[:password]).to_s
127
+ end
128
+ end
124
129
 
125
130
  @logger.debug user
126
131
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright 2016 Liqwyd Ltd.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,6 +26,7 @@ module Cyclid
25
26
  :server,
26
27
  :port,
27
28
  :tls,
29
+ :ssl_verify_none,
28
30
  :organization,
29
31
  :username,
30
32
  :secret,
@@ -65,6 +67,10 @@ module Cyclid
65
67
  def initialize(options = {})
66
68
  # Load the config if a path was provided
67
69
  @path = options[:path] || nil
70
+ unless File.file?(@path)
71
+ raise "no config found at #{@path} - Have you selected an organisation with " \
72
+ '`cyclid organization use <name>`?'
73
+ end
68
74
  @config = @path.nil? ? nil : YAML.load_file(@path)
69
75
 
70
76
  # Select the authentication type & associated authentication data.
@@ -72,6 +78,7 @@ module Cyclid
72
78
  case @auth
73
79
  when AUTH_NONE
74
80
  # Nothing
81
+ nil
75
82
  when AUTH_HMAC
76
83
  @secret = options[:secret] || @config['secret']
77
84
  when AUTH_BASIC
@@ -85,6 +92,7 @@ module Cyclid
85
92
  @server = options[:server] || nil
86
93
  @port = options[:port] || nil
87
94
  @tls = options[:tls] || nil
95
+ @ssl_verify_none = options[:ssl_verify_none] || nil
88
96
  @organization = options[:organization] || nil
89
97
  @username = options[:username] || nil
90
98
 
@@ -94,6 +102,7 @@ module Cyclid
94
102
  @server ||= @config['server']
95
103
  @port ||= @config['port'] || 8361
96
104
  @tls ||= @config['tls'] || false
105
+ @ssl_verify_none ||= @config['ssl_verify_none'] || false
97
106
  @organization ||= @config['organization']
98
107
  @username ||= @config['username']
99
108
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Cyclid
3
4
  module Client
4
- VERSION = '0.4.0'
5
+ VERSION = '0.4.1'.freeze
5
6
  end
6
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cyclid-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kristian Van Der Vliet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-28 00:00:00.000000000 Z
11
+ date: 2017-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -113,6 +113,7 @@ files:
113
113
  - lib/cyclid/cli/admin/user.rb
114
114
  - lib/cyclid/cli/formatter.rb
115
115
  - lib/cyclid/cli/job.rb
116
+ - lib/cyclid/cli/linter.rb
116
117
  - lib/cyclid/cli/organization.rb
117
118
  - lib/cyclid/cli/organization/config.rb
118
119
  - lib/cyclid/cli/organization/member.rb
@@ -153,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
154
  version: '0'
154
155
  requirements: []
155
156
  rubyforge_project:
156
- rubygems_version: 2.5.1
157
+ rubygems_version: 2.2.0
157
158
  signing_key:
158
159
  specification_version: 4
159
160
  summary: Cyclid command line client & library