ci-queue 0.8.0 → 0.9.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
  SHA1:
3
- metadata.gz: d71f2dd528eeda6758bc37bb9142cac9814150ea
4
- data.tar.gz: 3042fc3632751cc3ef1834dd749978dff2c628a6
3
+ metadata.gz: 98b80ab169a69259f71c570b707f087c3b81de3c
4
+ data.tar.gz: c2fdd8f99b8462fde12ba800f4e5060263705bc2
5
5
  SHA512:
6
- metadata.gz: bc012267f7470bc5527ae5081ebfe2e268acf6d777db6c8c50d218e9aa21fa7a3dba46e2f1af467a9f7fcbf5ca98512322128dea0115ce4a047cd6a09aa09253
7
- data.tar.gz: 80445ac4bb1f43a2a930269708c7f97178921d5da60b198af42ffdeecf07e0e0c3242cb4c065c6b220ee4ef19b6a7935716330875df1aa1b62b665f891641ae9
6
+ metadata.gz: 670223dbcfc6d462c25086fa449ef07063bb2b325d4e977489e7b78afd9e02bf07de55b240e92e9b95bb6a695500154dcce8c993e5ba81bfe1faafa5771d2fa9
7
+ data.tar.gz: 0c4a98d593e3088ea58b097785b002ac78bc51990545719f630144fdf72c59dfbe76c8ade54c157864163a3445811b29b452947bfbfdeae75545c0c356470275
data/README.md CHANGED
@@ -51,4 +51,19 @@ minitest-queue --queue path/to/test_order.log --failing-test 'SomeTest#test_some
51
51
 
52
52
  ### RSpec
53
53
 
54
- The RSpec integration is not implemented yet.
54
+ The RSpec integration is still missing some features, but is already usable:
55
+
56
+ ```bash
57
+ rspec-queue --queue redis://example.com --build XXX --worker XXX
58
+ ```
59
+
60
+ #### Missing features
61
+
62
+ To be implemented:
63
+
64
+ - Requeueing
65
+ - Centralized reporting
66
+
67
+ #### Limitations
68
+
69
+ Because of how `ci-queue` execute the examples, `before(:all)` and `after(:all)` hooks are not supported. `rspec-queue` will explicitly reject them.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'ci/queue/version'
5
5
  Rake::TestTask.new(:test) do |t|
6
6
  t.libs << 'test'
7
7
  t.libs << 'lib'
8
- t.test_files = FileList['test/**/*_test.rb'] - FileList['test/fixtures/*_test.rb']
8
+ t.test_files = FileList['test/**/*_test.rb'] - FileList['test/fixtures/**/*_test.rb']
9
9
  end
10
10
 
11
11
  task :default => :test
data/ci-queue.gemspec CHANGED
@@ -26,9 +26,12 @@ Gem::Specification.new do |spec|
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ['lib']
28
28
 
29
+ spec.add_dependency 'ansi'
30
+
29
31
  spec.add_development_dependency 'bundler', '~> 1.13'
30
32
  spec.add_development_dependency 'rake', "~> 10.0"
31
33
  spec.add_development_dependency 'minitest', '~> 5.9.1'
34
+ spec.add_development_dependency 'rspec', '~> 3.7.0'
32
35
  spec.add_development_dependency 'redis', '~> 3.3'
33
36
  spec.add_development_dependency 'simplecov', '~> 0.12'
34
37
  spec.add_development_dependency 'minitest-reporters', '~> 1.1'
data/exe/rspec-queue ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rspec/queue'
4
+ RSpec::Queue::Runner.invoke
@@ -149,7 +149,7 @@ module CI
149
149
 
150
150
  if @master = redis.setnx(key('master-status'), 'setup')
151
151
  redis.multi do
152
- redis.lpush(key('queue'), tests)
152
+ redis.lpush(key('queue'), tests) unless tests.empty?
153
153
  redis.set(key('total'), @total)
154
154
  redis.set(key('master-status'), 'ready')
155
155
  end
@@ -1,6 +1,6 @@
1
1
  module CI
2
2
  module Queue
3
- VERSION = '0.8.0'
3
+ VERSION = '0.9.0'
4
4
  DEV_SCRIPTS_ROOT = ::File.expand_path('../../../../../redis', __FILE__)
5
5
  RELEASE_SCRIPTS_ROOT = ::File.expand_path('../redis', __FILE__)
6
6
  end
@@ -248,7 +248,7 @@ module Minitest
248
248
  Defaults to 0.
249
249
  EOS
250
250
  opts.separator ""
251
- opts.on('--max-requeues MAX') do |max|
251
+ opts.on('--max-requeues MAX', *help) do |max|
252
252
  queue_config.max_requeues = Integer(max)
253
253
  end
254
254
 
@@ -0,0 +1,202 @@
1
+ require 'rspec/core'
2
+ require 'ci/queue'
3
+
4
+ module RSpec
5
+ module Queue
6
+ class << self
7
+ def config
8
+ @config ||= CI::Queue::Configuration.from_env(ENV)
9
+ end
10
+ end
11
+
12
+ module ConfigurationExtension
13
+ private
14
+
15
+ def command
16
+ 'rspec' # trick rspec into enabling it's default behavior
17
+ end
18
+ end
19
+
20
+ Core::Configuration.add_setting(:queue_url)
21
+ Core::Configuration.prepend(ConfigurationExtension)
22
+
23
+ module ConfigurationOptionsExtension
24
+ attr_accessor :queue_url
25
+ end
26
+ Core::ConfigurationOptions.prepend(ConfigurationOptionsExtension)
27
+
28
+
29
+ module ParserExtension
30
+ private
31
+
32
+ def parser(options)
33
+ parser = super
34
+
35
+ parser.separator("\n **** Queue options ****\n\n")
36
+
37
+ help = split_heredoc(<<-EOS)
38
+ URL of the queue, e.g. redis://example.com.
39
+ Defaults to $CI_QUEUE_URL if set.
40
+ EOS
41
+ parser.separator ""
42
+ parser.on('--queue URL', *help) do |url|
43
+ options[:queue_url] = url
44
+ end
45
+
46
+ help = split_heredoc(<<-EOS)
47
+ Unique identifier for the workload. All workers working on the same suite of tests must have the same build identifier.
48
+ If the build is tried again, or another revision is built, this value must be different.
49
+ It's automatically inferred on Buildkite, CircleCI and Travis.
50
+ EOS
51
+ parser.separator ""
52
+ parser.on('--build BUILD_ID', *help) do |build_id|
53
+ queue_config.build_id = build_id
54
+ end
55
+
56
+ help = split_heredoc(<<-EOS)
57
+ Optional. Sets a prefix for the build id in case a single CI build runs multiple independent test suites.
58
+ Example: --namespace integration
59
+ EOS
60
+ parser.separator ""
61
+ parser.on('--namespace NAMESPACE', *help) do |namespace|
62
+ queue_config.namespace = namespace
63
+ end
64
+
65
+ help = split_heredoc(<<-EOS)
66
+ Specify a timeout after which if a test haven't completed, it will be picked up by another worker.
67
+ It is very important to set this vlaue higher than the slowest test in the suite, otherwise performance will be impacted.
68
+ Defaults to 30 seconds.
69
+ EOS
70
+ parser.separator ""
71
+ parser.on('--timeout TIMEOUT', *help) do |timeout|
72
+ queue_config.timeout = Float(timeout)
73
+ end
74
+
75
+ help = split_heredoc(<<-EOS)
76
+ A unique identifier for this worker, It must be consistent to allow retries.
77
+ If not specified, retries won't be available.
78
+ It's automatically inferred on Buildkite and CircleCI.
79
+ EOS
80
+ parser.separator ""
81
+ parser.on('--worker WORKER_ID', *help) do |worker_id|
82
+ queue_config.worker_id = worker_id
83
+ end
84
+
85
+ help = split_heredoc(<<-EOS)
86
+ Defines how many time a single test can be requeued.
87
+ Defaults to 0.
88
+ EOS
89
+ parser.separator ""
90
+ parser.on('--max-requeues MAX', *help) do |max|
91
+ queue_config.max_requeues = Integer(max)
92
+ end
93
+
94
+ help = split_heredoc(<<-EOS)
95
+ Defines how many requeues can happen overall, based on the test suite size. e.g 0.05 for 5%.
96
+ Defaults to 0.
97
+ EOS
98
+ parser.separator ""
99
+ parser.on('--requeue-tolerance RATIO', *help) do |ratio|
100
+ queue_config.requeue_tolerance = Float(ratio)
101
+ end
102
+
103
+ parser
104
+ end
105
+
106
+ def split_heredoc(string)
107
+ string.lines.map(&:strip)
108
+ end
109
+
110
+ def queue_config
111
+ ::RSpec::Queue.config
112
+ end
113
+ end
114
+
115
+ RSpec::Core::Parser.prepend(ParserExtension)
116
+
117
+ class SingleExample
118
+ attr_reader :example_group, :example
119
+
120
+ def initialize(example_group, example)
121
+ @example_group = example_group
122
+ @example = example
123
+ end
124
+
125
+ def id
126
+ example.id
127
+ end
128
+
129
+ def run(reporter)
130
+ return if RSpec.world.wants_to_quit
131
+ instance = example_group.new(example.inspect_output)
132
+ example_group.set_ivars(instance, example_group.before_context_ivars)
133
+ succeeded = example.run(instance, reporter)
134
+ if !succeeded && reporter.fail_fast_limit_met?
135
+ RSpec.world.wants_to_quit = true
136
+ end
137
+ succeeded
138
+ end
139
+ end
140
+
141
+ class Runner < ::RSpec::Core::Runner
142
+ include CI::Queue::OutputHelpers
143
+
144
+ def setup(err, out)
145
+ super
146
+ invalid_usage!('Missing --queue parameter') unless queue_url
147
+ invalid_usage!('Missing --build parameter') unless RSpec::Queue.config.build_id
148
+ invalid_usage!('Missing --worker parameter') unless RSpec::Queue.config.worker_id
149
+ end
150
+
151
+ def run_specs(example_groups)
152
+ examples = example_groups.flat_map do |example_group|
153
+ example_group.filtered_examples.map do |example|
154
+ SingleExample.new(example_group, example)
155
+ end
156
+ end
157
+
158
+ queue = CI::Queue.from_uri(queue_url, RSpec::Queue.config)
159
+ queue.populate(examples, &:id)
160
+ examples_count = examples.size # TODO: figure out which stub value would be best
161
+ success = true
162
+ @configuration.reporter.report(examples_count) do |reporter|
163
+ @configuration.with_suite_hooks do
164
+ queue.poll do |example|
165
+ success &= example.run(reporter)
166
+ queue.acknowledge(example)
167
+ end
168
+ end
169
+ end
170
+
171
+ success &= !@world.non_example_failure
172
+ success ? 0 : @configuration.failure_exit_code
173
+ end
174
+
175
+ private
176
+
177
+ def queue_url
178
+ configuration.queue_url || ENV['CI_QUEUE_URL']
179
+ end
180
+
181
+ def invalid_usage!(message)
182
+ reopen_previous_step
183
+ puts red(message)
184
+ puts
185
+ puts 'Please use --help for a listing of valid options'
186
+ exit! 1 # exit! is required to avoid minitest at_exit callback
187
+ end
188
+
189
+ def exit!(*)
190
+ STDOUT.flush
191
+ STDERR.flush
192
+ super
193
+ end
194
+
195
+ def abort!(message)
196
+ reopen_previous_step
197
+ puts red(message)
198
+ exit! 1 # exit! is required to avoid minitest at_exit callback
199
+ end
200
+ end
201
+ end
202
+ end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ci-queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-28 00:00:00.000000000 Z
11
+ date: 2017-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ansi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: 5.9.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.7.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.7.0
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: redis
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -99,6 +127,7 @@ email:
99
127
  - jean.boussier@shopify.com
100
128
  executables:
101
129
  - minitest-queue
130
+ - rspec-queue
102
131
  extensions: []
103
132
  extra_rdoc_files: []
104
133
  files:
@@ -113,6 +142,7 @@ files:
113
142
  - ci-queue.gemspec
114
143
  - dev.yml
115
144
  - exe/minitest-queue
145
+ - exe/rspec-queue
116
146
  - lib/ci/queue.rb
117
147
  - lib/ci/queue/bisect.rb
118
148
  - lib/ci/queue/configuration.rb
@@ -136,6 +166,7 @@ files:
136
166
  - lib/minitest/reporters/order_reporter.rb
137
167
  - lib/minitest/reporters/queue_reporter.rb
138
168
  - lib/minitest/reporters/redis_reporter.rb
169
+ - lib/rspec/queue.rb
139
170
  homepage: https://github.com/Shopify/ci-queue
140
171
  licenses:
141
172
  - MIT