ci-queue 0.8.0 → 0.9.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 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