roxanne 0.1.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.
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roxanne::Configuration::YAML do
4
+
5
+ def spec_file(variation)
6
+ File.expand_path(File.join(File.dirname(__FILE__), '../../yaml', "#{variation}.yml"))
7
+ end
8
+
9
+ it 'uses activation default settings' do
10
+ subject.new(spec_file('defaults')).tap do |config|
11
+ config.active_days.must_equal 1..5
12
+ config.timerange.must_equal 8..19
13
+ end
14
+ end
15
+
16
+ it 'overrides activation settings' do
17
+ subject.new(spec_file('full_blown')).tap do |config|
18
+ config.active_days.must_equal 1..3
19
+ config.timerange.must_equal 9..18
20
+ end
21
+ end
22
+
23
+ module Roxanne::Spec
24
+ class Consumer
25
+ attr_accessor :consumer_opt
26
+ end
27
+
28
+ class Publisher
29
+ attr_accessor :publisher_opt
30
+ end
31
+ end
32
+
33
+ it 'create consumers' do
34
+ subject.new(spec_file('defaults')).tap do |config|
35
+ config.consumers.size.must_equal 1
36
+ config.consumers.first.must_be_instance_of Roxanne::Spec::Consumer
37
+ config.consumers.first.consumer_opt.must_equal "some-value"
38
+ end
39
+ end
40
+
41
+ it 'create publisher' do
42
+ subject.new(spec_file('defaults')).tap do |config|
43
+ config.publisher.must_be_instance_of Roxanne::Spec::Publisher
44
+ config.publisher.publisher_opt.must_equal "another-value"
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roxanne::Configuration::Base do
4
+
5
+ after do
6
+ Timecop.return
7
+ end
8
+
9
+ it 'initializes settings' do
10
+ subject.new.tap do |config|
11
+ config.publisher.must_be_nil
12
+ config.consumers.must_equal []
13
+ end
14
+ end
15
+
16
+ it 'is active when in specified days and time range' do
17
+ Timecop.travel(Time.local(2014, 3, 7, 19, 59, 59))
18
+ subject.new.activated.must_equal true
19
+
20
+ Timecop.travel(Time.local(2014, 3, 3, 8, 0, 0))
21
+ subject.new.activated.must_equal true
22
+ end
23
+
24
+ it 'is not active when out of specified days' do
25
+ Timecop.travel(Time.local(2014, 3, 8, 8, 0, 0))
26
+ subject.new.activated.must_equal false
27
+ end
28
+
29
+ it 'is not active when out of time range' do
30
+ Timecop.travel(Time.local(2014, 3, 7, 20, 0, 0))
31
+ subject.new.activated.must_equal false
32
+
33
+ Timecop.travel(Time.local(2014, 3, 3, 7, 59, 59))
34
+ subject.new.activated.must_equal false
35
+ end
36
+
37
+ end
@@ -0,0 +1,54 @@
1
+ describe Roxanne::GPIO::Publisher do
2
+
3
+ before do
4
+ @publisher = subject.new
5
+ @publisher.green_pin = 17
6
+ @publisher.orange_pin = 25
7
+ @publisher.red_pin = 22
8
+ end
9
+
10
+ it 'disable gpio pins' do
11
+ expects_all_off
12
+ @publisher.disable
13
+ end
14
+
15
+ it 'sets all pins to zero on nil status' do
16
+ expects_all_off
17
+ @publisher.push nil, nil
18
+ end
19
+
20
+ it 'switch green pin to 1 on green status' do
21
+ expects_pin(@publisher.green_pin).expects(:value).with 1
22
+ expects_pin(@publisher.orange_pin).expects(:value).with 0
23
+ expects_pin(@publisher.red_pin).expects(:value).with 0
24
+ @publisher.push nil, :green
25
+ end
26
+
27
+ it 'switch red pin to 1 on red status' do
28
+ expects_pin(@publisher.green_pin).expects(:value).with 0
29
+ expects_pin(@publisher.orange_pin).expects(:value).with 0
30
+ expects_pin(@publisher.red_pin).expects(:value).with 1
31
+ @publisher.push nil, :red
32
+ end
33
+
34
+ it 'switch orange pin to 1 on orange status' do
35
+ expects_pin(@publisher.green_pin).expects(:value).with 0
36
+ expects_pin(@publisher.orange_pin).expects(:value).with 1
37
+ expects_pin(@publisher.red_pin).expects(:value).with 0
38
+ @publisher.push nil, :orange
39
+ end
40
+
41
+ def expects_pin(num)
42
+ mock.tap do |pin|
43
+ Taopaipai.gpio.expects(:pin).with(num, direction: :out).returns(pin)
44
+ end
45
+ end
46
+
47
+ def expects_all_off
48
+ [17, 25, 22].each do |num|
49
+ expects_pin(num).expects(:value).with(0)
50
+ end
51
+ end
52
+
53
+ end
54
+
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roxanne::Jenkins::Consumer do
4
+
5
+ def jobs(*colors)
6
+ { 'jobs' => colors.map{|color| {'color'=>color} } }.to_json
7
+ end
8
+
9
+ it 'defaults to green' do
10
+ subject.new.handle_response(jobs).must_equal :green
11
+ end
12
+
13
+ it 'ignores unknown job colors' do
14
+ subject.new.handle_response(jobs('british_racing_green')).must_equal :green
15
+ end
16
+
17
+ it 'returns green if all good' do
18
+ subject.new.handle_response(jobs('blue', 'yellow')).must_equal :green
19
+ end
20
+
21
+ it 'returns orange if one of the jobs is orange' do
22
+ subject.new.handle_response(jobs('yellow_anime', 'blue', 'yellow')).must_equal :orange
23
+ subject.new.handle_response(jobs('blue_anime', 'blue', 'yellow')).must_equal :orange
24
+ subject.new.handle_response(jobs('red_anime', 'blue', 'yellow_anime')).must_equal :orange
25
+ end
26
+
27
+ it 'returns red if one of the jobs is read' do
28
+ subject.new.handle_response(jobs('red', 'blue', 'yellow_anime')).must_equal :red
29
+ end
30
+
31
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roxanne::Loop do
4
+ before do
5
+ @publisher = mock
6
+ @config = Roxanne::Configuration::Base.new
7
+ @config.stubs(:publisher).returns @publisher
8
+ end
9
+
10
+ it 'disables publishers unless active' do
11
+ @config.expects(:activated).returns false
12
+ @publisher.expects(:disable)
13
+ subject.new(@config).cycle
14
+ end
15
+
16
+ describe 'activated' do
17
+
18
+ before do
19
+ @config.expects(:activated).at_least(1).returns true
20
+ @publisher.expects(:disable).never
21
+
22
+ 3.times do
23
+ @config.consumers << mock
24
+ end
25
+ end
26
+
27
+ it 'publishes green if all of consumers answer green' do
28
+ @config.consumers.each do |consumer|
29
+ consumer.expects(:pull).returns :green
30
+ end
31
+ @publisher.expects(:push).with(nil, :green)
32
+ subject.new(@config).cycle
33
+ end
34
+
35
+ it 'publishes red if one of the consumers answers red' do
36
+ @config.consumers.first.expects(:pull).returns :red
37
+ @publisher.expects(:push).with(nil, :red)
38
+ subject.new(@config).cycle
39
+ end
40
+
41
+ def expects_pulls(*statuses)
42
+ @config.consumers.each_with_index do |consumer, i|
43
+ consumer.expects(:pull).returns statuses[i] if statuses[i]
44
+ end
45
+ end
46
+
47
+ it 'publishes orange if a consumer answers orange and the previous status wasnt green' do
48
+ loop = subject.new(@config)
49
+ # First cycle to turn it red
50
+ expects_pulls(:red)
51
+ @publisher.expects(:push).with(nil, :red)
52
+ loop.cycle
53
+
54
+ # Second cycle to orange
55
+ expects_pulls(:green, :orange, :green)
56
+ @publisher.expects(:push).with(:red, :orange)
57
+ loop.cycle
58
+ end
59
+
60
+ it 'publishes green if orange and previous state wasnt red' do
61
+ loop = subject.new(@config)
62
+
63
+ expects_pulls(:green, :green, :green)
64
+ @publisher.expects(:push).with(nil, :green)
65
+ loop.cycle
66
+
67
+ expects_pulls(:orange, :green, :green)
68
+ @publisher.expects(:push).with(:green, :green)
69
+ loop.cycle
70
+ end
71
+
72
+ end
73
+
74
+ it 'publishes nil on reset' do
75
+ loop = subject.new(@config)
76
+ @publisher.expects(:push).with(nil, nil)
77
+ loop.reset
78
+ end
79
+
80
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roxanne::Server do
4
+
5
+ describe 'with a test double' do
6
+ class ServerDouble < Roxanne::Server
7
+ attr_reader :slept_for, :looped
8
+
9
+ def initialize(configuration, opts)
10
+ @config = configuration
11
+ super(opts)
12
+ end
13
+
14
+ def loop(&block)
15
+ @looped = true
16
+ yield
17
+ end
18
+
19
+ def sleep(time)
20
+ @slept_for = time
21
+ end
22
+
23
+ def config(args)
24
+ @config
25
+ end
26
+ end
27
+
28
+ before do
29
+ @configuration = Roxanne::Configuration::Base.new
30
+ @server = ServerDouble.new(
31
+ @configuration,
32
+ working_dir: @working_dir = File.join(File.dirname(__FILE__), '../..')
33
+ )
34
+ end
35
+
36
+ it 'logs, cycle and sleep' do
37
+ STDOUT.expects(:puts).with("Roxanne starting in #{@working_dir}")
38
+ controller = Roxanne::Loop.new(@configuration)
39
+ Roxanne::Loop.expects(:new).with(@configuration).returns(controller)
40
+ controller.expects(:cycle)
41
+ @server.start([])
42
+ @server.looped.must_equal true
43
+ @server.slept_for.must_equal 5
44
+ end
45
+
46
+ it 'stops' do
47
+ @server.instance_variable_set(:@controller, controller = mock)
48
+ controller.expects(:reset)
49
+ @server.stop
50
+ end
51
+ end
52
+
53
+ it 'creates a YAML configuration using the default path' do
54
+ Roxanne::Configuration::YAML.expects(:new).with('config/config.yml').returns(config = mock)
55
+ subject.new({working_dir: ''}).config([]).must_equal config
56
+ end
57
+
58
+ it 'creates a YAML configuration using the provided path' do
59
+ Roxanne::Configuration::YAML.expects(:new).with('specific-config.yml').returns(config = mock)
60
+ subject.new({working_dir: ''}).config(['specific-config.yml']).must_equal config
61
+ end
62
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roxanne::Travis::Consumer do
4
+
5
+ before do
6
+ @subject = subject.new
7
+ @subject.organization_or_user = 'servebox'
8
+ end
9
+
10
+ def expects_repositories_state( *repos )
11
+ mock_repos = repos.map do |repo|
12
+ mock.tap do |mock|
13
+ mock.stubs(:active?).returns(repo[:active].nil? ? true : repo[:active])
14
+ mock.stubs(:last_build_state).returns(repo[:build_state])
15
+ end
16
+ end
17
+ Travis::Repository.expects(:find_all).with(owner_name: 'servebox').returns(mock_repos)
18
+ end
19
+
20
+ it 'defaults to green' do
21
+ expects_repositories_state
22
+ @subject.pull.must_equal :green
23
+ end
24
+
25
+ it 'ignores inactive repositories' do
26
+ expects_repositories_state({ active: false, build_state: 'failed' })
27
+ @subject.pull.must_equal :green
28
+ end
29
+
30
+ it 'returns green if all good' do
31
+ expects_repositories_state({ build_state: 'passed' })
32
+ @subject.pull.must_equal :green
33
+ end
34
+
35
+ it 'returns orange if one of the jobs is orange' do
36
+ expects_repositories_state({ build_state: 'started' }, {build_state: 'passed'})
37
+ @subject.pull.must_equal :orange
38
+ end
39
+
40
+ it 'returns red if one of the jobs is read' do
41
+ expects_repositories_state({ build_state: 'failed' }, { build_state: 'started' },
42
+ {build_state: 'passed'})
43
+ @subject.pull.must_equal :red
44
+ end
45
+
46
+ end
@@ -0,0 +1,20 @@
1
+ #require 'simplecov'
2
+ #require 'coveralls'
3
+ #
4
+ #SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ # SimpleCov::Formatter::HTMLFormatter,
6
+ # Coveralls::SimpleCov::Formatter
7
+ #]
8
+ #
9
+ #SimpleCov.start do
10
+ # add_filter '/spec/'
11
+ #end
12
+
13
+ require 'roxanne'
14
+ require 'minitest'
15
+ require 'minitest/spec'
16
+ require 'minitest/autorun'
17
+ require 'minitest/pride'
18
+ require 'minitest-implicit-subject'
19
+ require 'timecop'
20
+ require 'mocha/setup'
@@ -0,0 +1,8 @@
1
+ roxanne:
2
+ consumers:
3
+ consumer_id:
4
+ class: "Roxanne::Spec::Consumer"
5
+ consumer_opt: "some-value"
6
+ publisher:
7
+ class: "Roxanne::Spec::Publisher"
8
+ publisher_opt: "another-value"
@@ -0,0 +1,12 @@
1
+ roxanne:
2
+ activation:
3
+ days: !ruby/range 1..3
4
+ # Active from ~ 08:00 to 18:59
5
+ timerange: !ruby/range 9..18
6
+ consumers:
7
+ consumer_id:
8
+ class: "Roxanne::Spec::Consumer"
9
+ consumer_opt: "some-value"
10
+ publisher:
11
+ class: "Roxanne::Spec::Publisher"
12
+ publisher_opt: "another-value"
metadata ADDED
@@ -0,0 +1,280 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roxanne
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jef Mathiot
8
+ - Patrice Izzo
9
+ - Fabrice Nourisson
10
+ - Benjamin Severac
11
+ - Eric Hartmann
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+ date: 2014-04-03 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: json
19
+ requirement: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: daemon-spawn
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ - !ruby/object:Gem::Dependency
46
+ name: activesupport
47
+ requirement: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 3.0.0
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 3.0.0
59
+ - !ruby/object:Gem::Dependency
60
+ name: taopaipai
61
+ requirement: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - "~>"
64
+ - !ruby/object:Gem::Version
65
+ version: 0.1.1
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: 0.1.1
73
+ - !ruby/object:Gem::Dependency
74
+ name: travis
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: 1.6.8
80
+ type: :runtime
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: 1.6.8
87
+ - !ruby/object:Gem::Dependency
88
+ name: bundler
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: '1.6'
94
+ type: :development
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: '1.6'
101
+ - !ruby/object:Gem::Dependency
102
+ name: rake
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ type: :development
109
+ prerelease: false
110
+ version_requirements: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ - !ruby/object:Gem::Dependency
116
+ name: minitest
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - "~>"
120
+ - !ruby/object:Gem::Version
121
+ version: 5.0.7
122
+ type: :development
123
+ prerelease: false
124
+ version_requirements: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: 5.0.7
129
+ - !ruby/object:Gem::Dependency
130
+ name: minitest-implicit-subject
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: 1.4.0
136
+ type: :development
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: 1.4.0
143
+ - !ruby/object:Gem::Dependency
144
+ name: rb-readline
145
+ requirement: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: 0.5.0
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - "~>"
155
+ - !ruby/object:Gem::Version
156
+ version: 0.5.0
157
+ - !ruby/object:Gem::Dependency
158
+ name: guard-minitest
159
+ requirement: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - "~>"
162
+ - !ruby/object:Gem::Version
163
+ version: 2.1.3
164
+ type: :development
165
+ prerelease: false
166
+ version_requirements: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - "~>"
169
+ - !ruby/object:Gem::Version
170
+ version: 2.1.3
171
+ - !ruby/object:Gem::Dependency
172
+ name: timecop
173
+ requirement: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ - !ruby/object:Gem::Dependency
186
+ name: mocha
187
+ requirement: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ type: :development
193
+ prerelease: false
194
+ version_requirements: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
+ description: 'Roxanne: publish your CI status to your device of choice'
200
+ email:
201
+ - foss@servebox.com
202
+ executables:
203
+ - roxanne
204
+ extensions: []
205
+ extra_rdoc_files: []
206
+ files:
207
+ - ".gitignore"
208
+ - ".ruby-version"
209
+ - ".travis.yml"
210
+ - Gemfile
211
+ - Guardfile
212
+ - LICENSE.txt
213
+ - README.md
214
+ - Rakefile
215
+ - bin/roxanne
216
+ - config/config.yml
217
+ - lib/roxanne.rb
218
+ - lib/roxanne/configuration.rb
219
+ - lib/roxanne/configuration/yaml.rb
220
+ - lib/roxanne/consumers.rb
221
+ - lib/roxanne/gpio/publisher.rb
222
+ - lib/roxanne/http/consumer.rb
223
+ - lib/roxanne/http_support.rb
224
+ - lib/roxanne/jenkins/consumer.rb
225
+ - lib/roxanne/loop.rb
226
+ - lib/roxanne/publishers.rb
227
+ - lib/roxanne/server.rb
228
+ - lib/roxanne/test/consumer.rb
229
+ - lib/roxanne/test/publisher.rb
230
+ - lib/roxanne/travis/consumer.rb
231
+ - lib/roxanne/version.rb
232
+ - roxanne.gemspec
233
+ - service/etc_init.d_roxanne
234
+ - service/roxanne.sh
235
+ - spec/roxanne/configuration/yaml_spec.rb
236
+ - spec/roxanne/configuration_spec.rb
237
+ - spec/roxanne/gpio/publisher_spec.rb
238
+ - spec/roxanne/jenkins/consumer_spec.rb
239
+ - spec/roxanne/loop_spec.rb
240
+ - spec/roxanne/server_spec.rb
241
+ - spec/roxanne/travis/consumer_spec.rb
242
+ - spec/spec_helper.rb
243
+ - spec/yaml/defaults.yml
244
+ - spec/yaml/full_blown.yml
245
+ homepage: http://github.com/servebox/roxanne
246
+ licenses:
247
+ - MIT
248
+ metadata: {}
249
+ post_install_message:
250
+ rdoc_options: []
251
+ require_paths:
252
+ - lib
253
+ required_ruby_version: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ required_rubygems_version: !ruby/object:Gem::Requirement
259
+ requirements:
260
+ - - ">="
261
+ - !ruby/object:Gem::Version
262
+ version: '0'
263
+ requirements: []
264
+ rubyforge_project:
265
+ rubygems_version: 2.2.2
266
+ signing_key:
267
+ specification_version: 4
268
+ summary: Aggregate the status of Continuous Integration jobs or other sources and
269
+ publish them
270
+ test_files:
271
+ - spec/roxanne/configuration/yaml_spec.rb
272
+ - spec/roxanne/configuration_spec.rb
273
+ - spec/roxanne/gpio/publisher_spec.rb
274
+ - spec/roxanne/jenkins/consumer_spec.rb
275
+ - spec/roxanne/loop_spec.rb
276
+ - spec/roxanne/server_spec.rb
277
+ - spec/roxanne/travis/consumer_spec.rb
278
+ - spec/spec_helper.rb
279
+ - spec/yaml/defaults.yml
280
+ - spec/yaml/full_blown.yml