scan 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ module Scan
2
+ class Manager
3
+ def work(options)
4
+ Scan.config = options
5
+
6
+ FastlaneCore::PrintTable.print_values(config: options,
7
+ hide_keys: [:destination, :slack_url],
8
+ title: "Summary for scan #{Scan::VERSION}")
9
+
10
+ return Runner.new.run
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,115 @@
1
+ require "fastlane_core"
2
+ require "credentials_manager"
3
+
4
+ module Scan
5
+ class Options
6
+ def self.available_options
7
+ [
8
+ FastlaneCore::ConfigItem.new(key: :workspace,
9
+ short_option: "-w",
10
+ env_name: "SCAN_WORKSPACE",
11
+ optional: true,
12
+ description: "Path the workspace file",
13
+ verify_block: proc do |value|
14
+ v = File.expand_path(value.to_s)
15
+ raise "Workspace file not found at path '#{v}'".red unless File.exist?(v)
16
+ raise "Workspace file invalid".red unless File.directory?(v)
17
+ raise "Workspace file is not a workspace, must end with .xcworkspace".red unless v.include?(".xcworkspace")
18
+ end),
19
+ FastlaneCore::ConfigItem.new(key: :project,
20
+ short_option: "-p",
21
+ optional: true,
22
+ env_name: "SCAN_PROJECT",
23
+ description: "Path the project file",
24
+ verify_block: proc do |value|
25
+ v = File.expand_path(value.to_s)
26
+ raise "Project file not found at path '#{v}'".red unless File.exist?(v)
27
+ raise "Project file invalid".red unless File.directory?(v)
28
+ raise "Project file is not a project file, must end with .xcodeproj".red unless v.include?(".xcodeproj")
29
+ end),
30
+ FastlaneCore::ConfigItem.new(key: :device,
31
+ short_option: "-a",
32
+ optional: true,
33
+ is_string: false,
34
+ env_name: "SCAN_DEVICE",
35
+ description: "The name of the simulator type you want to run tests on",
36
+ verify_block: proc do |value|
37
+ end),
38
+ FastlaneCore::ConfigItem.new(key: :scheme,
39
+ short_option: "-s",
40
+ optional: true,
41
+ env_name: "SCAN_SCHEME",
42
+ description: "The project's scheme. Make sure it's marked as `Shared`"),
43
+ FastlaneCore::ConfigItem.new(key: :clean,
44
+ short_option: "-c",
45
+ env_name: "SCAN_CLEAN",
46
+ description: "Should the project be cleaned before building it?",
47
+ is_string: false,
48
+ default_value: false),
49
+ FastlaneCore::ConfigItem.new(key: :output_directory,
50
+ short_option: "-o",
51
+ env_name: "SCAN_OUTPUT_DIRECTORY",
52
+ description: "The directory in which all reports will be stored",
53
+ default_value: "./test_output"),
54
+ FastlaneCore::ConfigItem.new(key: :output_types,
55
+ short_option: "-f",
56
+ env_name: "SCAN_OUTPUT_TYPES",
57
+ description: "Comma seperated list of the output types (e.g. html, junit)",
58
+ default_value: "html,junit"),
59
+ FastlaneCore::ConfigItem.new(key: :buildlog_path,
60
+ short_option: "-l",
61
+ env_name: "SCAN_BUILDLOG_PATH",
62
+ description: "The directory were to store the raw log",
63
+ default_value: "~/Library/Logs/scan"),
64
+ FastlaneCore::ConfigItem.new(key: :sdk,
65
+ short_option: "-k",
66
+ env_name: "SCAN_SDK",
67
+ description: "The SDK that should be used for building the application",
68
+ optional: true),
69
+ FastlaneCore::ConfigItem.new(key: :skip_html_open,
70
+ short_option: "-g",
71
+ env_name: "SCAN_SKIP_HTML_OPEN",
72
+ description: "Don't open the HTML report when tests are completed",
73
+ is_string: false,
74
+ default_value: false),
75
+ FastlaneCore::ConfigItem.new(key: :configuration,
76
+ short_option: "-q",
77
+ env_name: "SCAN_CONFIGURATION",
78
+ description: "The configuration to use when building the app. Defaults to 'Release'",
79
+ optional: true),
80
+ FastlaneCore::ConfigItem.new(key: :destination,
81
+ short_option: "-d",
82
+ env_name: "SCAN_DESTINATION",
83
+ description: "Use only if you're a pro, use the other options instead",
84
+ optional: true),
85
+ FastlaneCore::ConfigItem.new(key: :xcargs,
86
+ short_option: "-x",
87
+ env_name: "SCAN_XCARGS",
88
+ description: "Pass additional arguments to xcodebuild. Be sure to quote the setting names and values e.g. OTHER_LDFLAGS=\"-ObjC -lstdc++\"",
89
+ optional: true),
90
+ FastlaneCore::ConfigItem.new(key: :xcconfig,
91
+ short_option: "-y",
92
+ env_name: "SCAN_XCCONFIG",
93
+ description: "Use an extra XCCONFIG file to build your app",
94
+ optional: true,
95
+ verify_block: proc do |value|
96
+ raise "File not found at path '#{File.expand_path(value)}'".red unless File.exist?(value)
97
+ end),
98
+ FastlaneCore::ConfigItem.new(key: :slack_url,
99
+ env_name: "SLACK_URL",
100
+ description: "Create an Incoming WebHook for your Slack group to post results there",
101
+ verify_block: proc do |value|
102
+ raise "Invalid URL, must start with https://" unless value.start_with? "https://"
103
+ end),
104
+ FastlaneCore::ConfigItem.new(key: :skip_slack,
105
+ description: "Don't publish to slack, even when an URL is given",
106
+ is_string: false,
107
+ default_value: false),
108
+ FastlaneCore::ConfigItem.new(key: :slack_only_on_failure,
109
+ description: "Only post on Slack if the tests fail",
110
+ is_string: false,
111
+ default_value: false)
112
+ ]
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,48 @@
1
+ module Scan
2
+ class ReportCollector
3
+ SUPPORTED = %w(html junit json-compilation-database)
4
+
5
+ def parse_raw_file(path)
6
+ raise "Couldn't find file at path '#{path}'".red unless File.exist?(path)
7
+
8
+ commands = generate_commands(path)
9
+ commands.each do |output_path, command|
10
+ system(command)
11
+ Helper.log.info("Successfully generated report at '#{output_path}'".green)
12
+
13
+ if !Scan.config[:skip_html_open] and output_path.end_with?(".html")
14
+ # Open the HTML file
15
+ `open --hide '#{output_path}'`
16
+ end
17
+ end
18
+ end
19
+
20
+ # Returns a hash containg the resulting path as key and the command as value
21
+ def generate_commands(path, types: nil, output_file_name: nil)
22
+ types ||= Scan.config[:output_types]
23
+ types = types.split(",") if types.kind_of?(String) # might already be an array when passed via fastlane
24
+ commands = {}
25
+
26
+ types.each do |raw|
27
+ type = raw.strip
28
+
29
+ unless SUPPORTED.include?(type)
30
+ Helper.log.error "Couldn't find reporter '#{type}', available #{SUPPORTED.join(', ')}"
31
+ next
32
+ end
33
+
34
+ file_name = "report.#{type}"
35
+ output_path = output_file_name || File.join(Scan.config[:output_directory], file_name)
36
+ parts = ["cat '#{path}' | "]
37
+ parts << "xcpretty"
38
+ parts << "--report #{type}"
39
+ parts << "--output '#{output_path}'"
40
+ parts << "&> /dev/null "
41
+
42
+ commands[output_path] = parts.join(" ")
43
+ end
44
+
45
+ return commands
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,72 @@
1
+ require 'pty'
2
+ require 'open3'
3
+ require 'fileutils'
4
+ require 'terminal-table'
5
+
6
+ module Scan
7
+ class Runner
8
+ def run
9
+ test_app
10
+ handle_results
11
+ end
12
+
13
+ def test_app
14
+ command = TestCommandGenerator.generate
15
+ prefix_hash = [
16
+ {
17
+ prefix: "Running Tests: ",
18
+ block: proc do |value|
19
+ value.include?("Touching")
20
+ end
21
+ }
22
+ ]
23
+ FastlaneCore::CommandExecutor.execute(command: command,
24
+ print_all: true,
25
+ print_command: true,
26
+ prefix: prefix_hash,
27
+ loading: "Loading...",
28
+ error: proc do |error_output|
29
+ begin
30
+ ErrorHandler.handle_build_error(error_output)
31
+ rescue => ex
32
+ SlackPoster.new.run({
33
+ build_errors: 1
34
+ })
35
+ raise ex
36
+ end
37
+ end)
38
+ end
39
+
40
+ def handle_results
41
+ # First, generate a JUnit report to get the number of tests
42
+ require 'tempfile'
43
+ output_file = Tempfile.new("junit_report")
44
+ cmd = ReportCollector.new.generate_commands(TestCommandGenerator.xcodebuild_log_path,
45
+ types: 'junit',
46
+ output_file_name: output_file.path).values.last
47
+ system(cmd)
48
+
49
+ result = TestResultParser.new.parse_result(output_file.read)
50
+ SlackPoster.new.run(result)
51
+
52
+ if result[:failures] > 0
53
+ failures_str = result[:failures].to_s.red
54
+ else
55
+ failures_str = result[:failures].to_s.green
56
+ end
57
+
58
+ puts Terminal::Table.new({
59
+ title: "Test Results",
60
+ rows: [
61
+ ["Number of tests", result[:tests]],
62
+ ["Number of failures", failures_str]
63
+ ]
64
+ })
65
+ puts ""
66
+
67
+ ReportCollector.new.parse_raw_file(TestCommandGenerator.xcodebuild_log_path)
68
+
69
+ raise "Tests failed" unless result[:failures] == 0
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,46 @@
1
+ module Scan
2
+ class SlackPoster
3
+ def run(results)
4
+ return if Scan.config[:skip_slack]
5
+ return if Scan.config[:slack_only_on_failure] && results[:failures] == 0
6
+
7
+ require 'slack-notifier'
8
+ notifier = Slack::Notifier.new(Scan.config[:slack_url])
9
+ notifier.username = 'fastlane'
10
+
11
+ attachments = []
12
+
13
+ attachments << {
14
+ text: "Build Errors: #{results[:build_errors] || 0}",
15
+ color: results[:build_errors].to_i > 0 ? "danger" : "good",
16
+ short: true
17
+ }
18
+
19
+ if results[:failures]
20
+ attachments << {
21
+ text: "Test Failures: #{results[:failures]}",
22
+ color: results[:failures].to_i > 0 ? "danger" : "good",
23
+ short: true
24
+ }
25
+ end
26
+
27
+ if results[:tests] and results[:failures]
28
+ attachments << {
29
+ text: "Successful Tests: #{results[:tests] - results[:failures]}",
30
+ color: "good",
31
+ short: true
32
+ }
33
+ end
34
+
35
+ result = notifier.ping "#{Scan.project.app_name} Tests:",
36
+ icon_url: 'https://s3-eu-west-1.amazonaws.com/fastlane.tools/fastlane.png',
37
+ attachments: attachments
38
+
39
+ if result.code.to_i == 200
40
+ Helper.log.info 'Successfully sent Slack notification'.green
41
+ else
42
+ Helper.log.error result.to_s.red
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,91 @@
1
+ module Scan
2
+ # Responsible for building the fully working xcodebuild command
3
+ class TestCommandGenerator
4
+ class << self
5
+ def generate
6
+ parts = prefix
7
+ parts << "xcodebuild"
8
+ parts += options
9
+ parts += actions
10
+ parts += suffix
11
+ parts += pipe
12
+
13
+ parts
14
+ end
15
+
16
+ def prefix
17
+ ["set -o pipefail &&"]
18
+ end
19
+
20
+ # Path to the project or workspace as parameter
21
+ # This will also include the scheme (if given)
22
+ # @return [Array] The array with all the components to join
23
+ def project_path_array
24
+ proj = Scan.project.xcodebuild_parameters
25
+ return proj if proj.count > 0
26
+ raise "No project/workspace found"
27
+ end
28
+
29
+ def options
30
+ config = Scan.config
31
+
32
+ options = []
33
+ options += project_path_array
34
+ options << "-configuration '#{config[:configuration]}'" if config[:configuration]
35
+ options << "-sdk '#{config[:sdk]}'" if config[:sdk]
36
+ options << "-destination '#{config[:destination]}'" # generated in `detect_values`
37
+ options << "-xcconfig '#{config[:xcconfig]}'" if config[:xcconfig]
38
+ options << config[:xcargs] if config[:xcargs]
39
+
40
+ options
41
+ end
42
+
43
+ def actions
44
+ config = Scan.config
45
+
46
+ actions = []
47
+ actions << :clean if config[:clean]
48
+ actions << :test
49
+
50
+ actions
51
+ end
52
+
53
+ def suffix
54
+ suffix = []
55
+ suffix
56
+ end
57
+
58
+ def pipe
59
+ # During building we just show the output in the terminal
60
+ # Check out the ReportCollector class for more xcpretty things
61
+ formatter = ""
62
+ if Helper.ci?
63
+ formatter = "-f `xcpretty-travis-formatter`"
64
+ Helper.log.info "Automatically switched to Travis formatter".green
65
+ end
66
+
67
+ ["| tee '#{xcodebuild_log_path}' | xcpretty #{formatter}"]
68
+ end
69
+
70
+ # Store the raw file
71
+ def xcodebuild_log_path
72
+ file_name = "#{Scan.project.app_name}-#{Scan.config[:scheme]}.log"
73
+ containing = File.expand_path(Scan.config[:buildlog_path])
74
+ FileUtils.mkdir_p(containing)
75
+
76
+ return File.join(containing, file_name)
77
+ end
78
+
79
+ # The path to set the Derived Data to
80
+ def build_path
81
+ unless Scan.cache[:build_path]
82
+ day = Time.now.strftime("%F") # e.g. 2015-08-07
83
+
84
+ Scan.cache[:build_path] = File.expand_path("~/Library/Developer/Xcode/Archives/#{day}/")
85
+ FileUtils.mkdir_p Scan.cache[:build_path]
86
+ end
87
+ Scan.cache[:build_path]
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,21 @@
1
+ module Scan
2
+ class TestResultParser
3
+ def parse_result(output)
4
+ # e.g. ...<testsuites tests='2' failures='1'>...
5
+ matched = output.match(/\<testsuites tests='(\d+)' failures='(\d+)'\>/)
6
+
7
+ if matched and matched.length == 3
8
+ tests = matched[1].to_i
9
+ failures = matched[2].to_i
10
+
11
+ return {
12
+ tests: tests,
13
+ failures: failures
14
+ }
15
+ else
16
+ Helper.log.error "Couldn't parse the number of tests from the output".red
17
+ return {}
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/scan/version.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  module Scan
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
+ DESCRIPTION = "Making sure no bad code gets on board"
3
4
  end
metadata CHANGED
@@ -1,62 +1,241 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-13 00:00:00.000000000 Z
11
+ date: 2015-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fastlane_core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.21.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 1.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.21.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: xcpretty
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.1.12
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.1.12
47
+ - !ruby/object:Gem::Dependency
48
+ name: xcpretty-travis-formatter
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 0.0.3
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.0.3
61
+ - !ruby/object:Gem::Dependency
62
+ name: slack-notifier
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.3'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.3'
75
+ - !ruby/object:Gem::Dependency
76
+ name: terminal-table
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
13
89
  - !ruby/object:Gem::Dependency
14
90
  name: bundler
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: fastlane
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 1.25.0
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 1.25.0
117
+ - !ruby/object:Gem::Dependency
118
+ name: rake
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rubocop
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: rspec
15
147
  requirement: !ruby/object:Gem::Requirement
16
148
  requirements:
17
149
  - - "~>"
18
150
  - !ruby/object:Gem::Version
19
- version: '1.10'
151
+ version: 3.1.0
20
152
  type: :development
21
153
  prerelease: false
22
154
  version_requirements: !ruby/object:Gem::Requirement
23
155
  requirements:
24
156
  - - "~>"
25
157
  - !ruby/object:Gem::Version
26
- version: '1.10'
158
+ version: 3.1.0
27
159
  - !ruby/object:Gem::Dependency
28
- name: rake
160
+ name: pry
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: yard
29
175
  requirement: !ruby/object:Gem::Requirement
30
176
  requirements:
31
177
  - - "~>"
32
178
  - !ruby/object:Gem::Version
33
- version: '10.0'
179
+ version: 0.8.7.4
34
180
  type: :development
35
181
  prerelease: false
36
182
  version_requirements: !ruby/object:Gem::Requirement
37
183
  requirements:
38
184
  - - "~>"
39
185
  - !ruby/object:Gem::Version
40
- version: '10.0'
41
- description: To be announced
186
+ version: 0.8.7.4
187
+ - !ruby/object:Gem::Dependency
188
+ name: webmock
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: 1.19.0
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "~>"
199
+ - !ruby/object:Gem::Version
200
+ version: 1.19.0
201
+ - !ruby/object:Gem::Dependency
202
+ name: coveralls
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ type: :development
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ description: Making sure no bad code gets on board
42
216
  email:
43
- - krausefx@gmail.com
44
- executables: []
217
+ - scan@krausefx.com
218
+ executables:
219
+ - scan
45
220
  extensions: []
46
221
  extra_rdoc_files: []
47
222
  files:
48
- - ".gitignore"
49
- - ".travis.yml"
50
- - CODE_OF_CONDUCT.md
51
- - Gemfile
52
- - LICENSE.txt
223
+ - LICENSE
53
224
  - README.md
54
- - Rakefile
55
- - bin/console
56
- - bin/setup
225
+ - bin/scan
226
+ - lib/assets/ScanfileTemplate
57
227
  - lib/scan.rb
228
+ - lib/scan/commands_generator.rb
229
+ - lib/scan/detect_values.rb
230
+ - lib/scan/error_handler.rb
231
+ - lib/scan/manager.rb
232
+ - lib/scan/options.rb
233
+ - lib/scan/report_collector.rb
234
+ - lib/scan/runner.rb
235
+ - lib/scan/slack_poster.rb
236
+ - lib/scan/test_command_generator.rb
237
+ - lib/scan/test_result_parser.rb
58
238
  - lib/scan/version.rb
59
- - scan.gemspec
60
239
  homepage: https://fastlane.tools
61
240
  licenses:
62
241
  - MIT
@@ -69,7 +248,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
248
  requirements:
70
249
  - - ">="
71
250
  - !ruby/object:Gem::Version
72
- version: '0'
251
+ version: 2.0.0
73
252
  required_rubygems_version: !ruby/object:Gem::Requirement
74
253
  requirements:
75
254
  - - ">="
@@ -77,9 +256,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
256
  version: '0'
78
257
  requirements: []
79
258
  rubyforge_project:
80
- rubygems_version: 2.4.5
259
+ rubygems_version: 2.4.8
81
260
  signing_key:
82
261
  specification_version: 4
83
- summary: To be announced
262
+ summary: Making sure no bad code gets on board
84
263
  test_files: []
85
264
  has_rdoc: