chicanery 0.1.0 → 0.1.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.
- data/Gemfile.lock +13 -13
- data/README.md +40 -8
- data/examples/chicanery.rb +15 -0
- data/lib/chicanery/cctray.rb +9 -21
- data/lib/chicanery/handlers.rb +1 -1
- data/lib/chicanery/repos.rb +26 -0
- data/lib/chicanery/{state_comparison.rb → servers.rb} +16 -9
- data/lib/chicanery/site.rb +26 -0
- data/lib/chicanery/sites.rb +32 -0
- data/lib/chicanery/summary.rb +6 -0
- data/lib/chicanery.rb +20 -31
- data/spec/chicanery/cctray_spec.rb +3 -4
- data/spec/chicanery/{state_comparison_spec.rb → servers_spec.rb} +2 -2
- data/spec/chicanery_spec.rb +1 -4
- metadata +10 -7
data/Gemfile.lock
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
chicanery (0.1.
|
4
|
+
chicanery (0.1.1)
|
5
5
|
nokogiri (~> 1)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
diff-lcs (1.1
|
10
|
+
diff-lcs (1.2.1)
|
11
11
|
fakeweb (1.3.0)
|
12
|
-
multi_json (1.
|
12
|
+
multi_json (1.6.1)
|
13
13
|
nokogiri (1.5.6)
|
14
|
-
rake (0.9.
|
15
|
-
rspec (2.
|
16
|
-
rspec-core (~> 2.
|
17
|
-
rspec-expectations (~> 2.
|
18
|
-
rspec-mocks (~> 2.
|
19
|
-
rspec-core (2.
|
20
|
-
rspec-expectations (2.
|
21
|
-
diff-lcs (
|
22
|
-
rspec-mocks (2.
|
14
|
+
rake (0.9.6)
|
15
|
+
rspec (2.13.0)
|
16
|
+
rspec-core (~> 2.13.0)
|
17
|
+
rspec-expectations (~> 2.13.0)
|
18
|
+
rspec-mocks (~> 2.13.0)
|
19
|
+
rspec-core (2.13.0)
|
20
|
+
rspec-expectations (2.13.0)
|
21
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
22
|
+
rspec-mocks (2.13.0)
|
23
23
|
simplecov (0.7.1)
|
24
24
|
multi_json (~> 1.0)
|
25
25
|
simplecov-html (~> 0.7.1)
|
26
26
|
simplecov-gem-adapter (1.0.1)
|
27
27
|
simplecov
|
28
28
|
simplecov-html (0.7.1)
|
29
|
-
vcr (2.
|
29
|
+
vcr (2.4.0)
|
30
30
|
|
31
31
|
PLATFORMS
|
32
32
|
ruby
|
data/README.md
CHANGED
@@ -16,18 +16,18 @@ State is persisted between executions so that it be scheduled to run regularly w
|
|
16
16
|
|
17
17
|
Create a configuration file. This file is just a ruby file that can make use of a few configuration and callback methods:
|
18
18
|
|
19
|
-
require 'chicanery/cctray'
|
20
19
|
require 'chicanery/git'
|
21
|
-
|
22
20
|
include Chicanery::Git
|
23
|
-
|
24
|
-
git_repo 'chicanery', '/tmp/chicanery', remotes: {
|
21
|
+
git 'chicanery', '.', branches: [:master], remotes: {
|
25
22
|
github: { url: 'git://github.com/markryall/chicanery.git' }
|
26
23
|
}
|
27
|
-
|
24
|
+
|
25
|
+
require 'chicanery/cctray'
|
26
|
+
include Chicanery::Cctray
|
27
|
+
cctray 'tddium', 'https://cihost.com/cctray.xml'
|
28
28
|
|
29
29
|
when_run do |state|
|
30
|
-
puts
|
30
|
+
puts state.has_failure? ? "something is wrong" : "all builds are fine"
|
31
31
|
end
|
32
32
|
|
33
33
|
when_commit do |repo, commit, previous|
|
@@ -66,6 +66,39 @@ If you want to specify an alternate location for this state file, add the follow
|
|
66
66
|
|
67
67
|
persist_state_to '/tmp/build_state'
|
68
68
|
|
69
|
+
# Callbacks
|
70
|
+
|
71
|
+
## General
|
72
|
+
|
73
|
+
The 'when_run' callback is executed on every poll.
|
74
|
+
|
75
|
+
## Servers
|
76
|
+
|
77
|
+
The following callbacks may be received after checking a CI server:
|
78
|
+
|
79
|
+
* when_started - when a new job has started
|
80
|
+
* when_succeeded - when a job finishes successfully
|
81
|
+
* when_failed - when a job finishes unsuccessfully
|
82
|
+
* when_broken - when a previously passing job fails
|
83
|
+
* when_fixed - when a previously failing job passes
|
84
|
+
|
85
|
+
## Repos
|
86
|
+
|
87
|
+
The following callbacks may be received after checking a source repository:
|
88
|
+
|
89
|
+
* when_commit - when a new commit is detected in the repository
|
90
|
+
|
91
|
+
Currently only git repositories are supported.
|
92
|
+
|
93
|
+
## Site
|
94
|
+
|
95
|
+
The following callbacks may be received after checking a web site:
|
96
|
+
|
97
|
+
* when_up - the website responded with a 2xx HTTP status
|
98
|
+
* when_down - the website did not responded with a 2xx HTTP status
|
99
|
+
* when_crashed - the website was previously up and is now down
|
100
|
+
* when_recovered - the website was previously down and is now up
|
101
|
+
|
69
102
|
## Supported CI servers
|
70
103
|
|
71
104
|
Currently only ci servers that can provide [cctray reporting format](http://confluence.public.thoughtworks.org/display/CI/Multiple+Project+Summary+Reporting+Standard) are supported.
|
@@ -88,7 +121,6 @@ Basic authentication is supported by passing :user => 'user', :password => 'pass
|
|
88
121
|
* monitoring a subversion repository for commit notifications
|
89
122
|
* monitoring heroku for deployment event notification
|
90
123
|
* monitoring more ci servers (atlassian bamboo, jetbrains team city, etc.)
|
91
|
-
* integration with the blinky gem to control a delcom build light
|
92
124
|
* other interesting notifier plugins or examples
|
93
125
|
|
94
126
|
## Contributing
|
@@ -97,4 +129,4 @@ Basic authentication is supported by passing :user => 'user', :password => 'pass
|
|
97
129
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
98
130
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
99
131
|
4. Push to the branch (`git push origin my-new-feature`)
|
100
|
-
5. Create new Pull Request
|
132
|
+
5. Create new Pull Request
|
data/examples/chicanery.rb
CHANGED
@@ -10,6 +10,8 @@ git 'chicanery', '.', branches: [:master], remotes: {
|
|
10
10
|
|
11
11
|
cctray 'travis', 'https://api.travis-ci.org/repositories/markryall/chicanery/cc.xml'
|
12
12
|
|
13
|
+
site 'travis', 'https://api.travis-ci.org/repositories/markryall/chicanery.json'
|
14
|
+
|
13
15
|
poll_period 10
|
14
16
|
|
15
17
|
def growlnotify message
|
@@ -18,6 +20,7 @@ end
|
|
18
20
|
|
19
21
|
when_run do |state|
|
20
22
|
puts state.has_failure? ? "something is wrong" : "all builds are fine"
|
23
|
+
puts state.site_down? ? "something is wrong" : "all sites are fine"
|
21
24
|
end
|
22
25
|
|
23
26
|
when_commit do |repo, commit, previous|
|
@@ -45,4 +48,16 @@ end
|
|
45
48
|
when_fixed do |job_name, job|
|
46
49
|
growlnotify "job #{job_name} is fixed"
|
47
50
|
`afplay ~/build_sounds/applause.mp3`
|
51
|
+
end
|
52
|
+
|
53
|
+
when_up do |name, site|
|
54
|
+
puts "#{name} returned #{site.code} in #{site.duration} seconds"
|
55
|
+
end
|
56
|
+
|
57
|
+
when_crashed do |name, site|
|
58
|
+
puts "#{name} has crashed with status of #{site.code}"
|
59
|
+
end
|
60
|
+
|
61
|
+
when_recovered do |name, site|
|
62
|
+
puts "#{name} has recovered with status of #{site.code}"
|
48
63
|
end
|
data/lib/chicanery/cctray.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'chicanery/site'
|
2
2
|
require 'nokogiri'
|
3
3
|
require 'date'
|
4
4
|
|
@@ -12,31 +12,14 @@ module Chicanery
|
|
12
12
|
server Cctray::Server.new *args
|
13
13
|
end
|
14
14
|
|
15
|
-
class Server
|
16
|
-
attr_reader :name, :uri, :options
|
17
|
-
|
18
|
-
def initialize name, url, options={}
|
19
|
-
@name, @uri, @options = name, URI(url), options
|
20
|
-
end
|
21
|
-
|
22
|
-
def get
|
23
|
-
req = Net::HTTP::Get.new(uri.path)
|
24
|
-
req.basic_auth options[:user], options[:password] if options[:user] and options[:password]
|
25
|
-
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
|
26
|
-
https.request(req)
|
27
|
-
end
|
28
|
-
res.value #check for success via a spectactulalry poorly named method
|
29
|
-
res.body
|
30
|
-
end
|
31
|
-
|
15
|
+
class Server < Chicanery::Site
|
32
16
|
def jobs
|
33
17
|
jobs = {}
|
34
|
-
response_body = get
|
35
|
-
Nokogiri::XML(response_body).css("Project").each do |project|
|
18
|
+
Nokogiri::XML(response_body = get).css("Project").each do |project|
|
36
19
|
job = {
|
37
20
|
activity: project[:activity] == 'Sleeping' ? :sleeping : :building,
|
38
21
|
last_build_status: parse_build_status(project[:lastBuildStatus]),
|
39
|
-
last_build_time:
|
22
|
+
last_build_time: parse_build_time(project[:lastBuildTime]),
|
40
23
|
url: project[:webUrl],
|
41
24
|
last_label: project[:lastBuildLabel]
|
42
25
|
}
|
@@ -46,6 +29,11 @@ module Chicanery
|
|
46
29
|
jobs
|
47
30
|
end
|
48
31
|
|
32
|
+
def parse_build_time time
|
33
|
+
return nil if time.nil? || time.empty?
|
34
|
+
DateTime.parse(time).to_time.to_i
|
35
|
+
end
|
36
|
+
|
49
37
|
def parse_build_status status
|
50
38
|
case status
|
51
39
|
when /^Success/ then :success
|
data/lib/chicanery/handlers.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Chicanery
|
2
2
|
module Handlers
|
3
|
-
%w{run started succeeded failed broken fixed commit}.each do |status|
|
3
|
+
%w{run started succeeded failed broken fixed commit up down crashed recovered}.each do |status|
|
4
4
|
class_eval <<-EOF
|
5
5
|
def when_#{status} &block
|
6
6
|
#{status}_handlers << block
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'chicanery/collections'
|
2
|
+
require 'chicanery/handlers'
|
3
|
+
|
4
|
+
module Chicanery
|
5
|
+
module Repos
|
6
|
+
include Collections
|
7
|
+
include Handlers
|
8
|
+
|
9
|
+
def check_repos current_state, previous_state
|
10
|
+
current_state[:repos] = {}
|
11
|
+
repos.each do |repo|
|
12
|
+
repo_state = repo.state
|
13
|
+
compare_repo_state repo.name, repo_state, previous_state[:repos][repo.name] if previous_state[:repos]
|
14
|
+
current_state[:repos][repo.name] = repo_state
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def compare_repo_state name, current, previous
|
19
|
+
return unless previous
|
20
|
+
current.each do |branch, state|
|
21
|
+
next unless previous[branch]
|
22
|
+
notify_commit_handlers "#{name}/#{branch}", state, previous[branch] if state != previous[branch]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,5 +1,20 @@
|
|
1
|
+
require 'chicanery/collections'
|
2
|
+
require 'chicanery/handlers'
|
3
|
+
|
1
4
|
module Chicanery
|
2
|
-
module
|
5
|
+
module Servers
|
6
|
+
include Collections
|
7
|
+
include Handlers
|
8
|
+
|
9
|
+
def check_servers current_state, previous_state
|
10
|
+
current_state[:servers] = {}
|
11
|
+
servers.each do |server|
|
12
|
+
current_jobs = server.jobs
|
13
|
+
compare_jobs current_jobs, previous_state[:servers][server.name] if previous_state[:servers]
|
14
|
+
current_state[:servers][server.name] = current_jobs
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
3
18
|
def compare_jobs current_jobs, previous_jobs
|
4
19
|
return unless previous_jobs
|
5
20
|
current_jobs.each do |job_name, job|
|
@@ -17,13 +32,5 @@ module Chicanery
|
|
17
32
|
notify_broken_handlers name, current if current[:last_build_status] == :failure and previous[:last_build_status] == :success
|
18
33
|
notify_fixed_handlers name, current if current[:last_build_status] == :success and previous[:last_build_status] == :failure
|
19
34
|
end
|
20
|
-
|
21
|
-
def compare_repo_state name, current, previous
|
22
|
-
return unless previous
|
23
|
-
current.each do |branch, state|
|
24
|
-
next unless previous[branch]
|
25
|
-
notify_commit_handlers "#{name}/#{branch}", state, previous[branch] if state != previous[branch]
|
26
|
-
end
|
27
|
-
end
|
28
35
|
end
|
29
36
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'benchmark'
|
3
|
+
|
4
|
+
module Chicanery
|
5
|
+
class Site
|
6
|
+
attr_reader :name, :uri, :options, :body, :code, :duration
|
7
|
+
|
8
|
+
def initialize name, url, options={}
|
9
|
+
@name, @uri, @options = name, URI(url), options
|
10
|
+
end
|
11
|
+
|
12
|
+
def get
|
13
|
+
req = Net::HTTP::Get.new uri.path
|
14
|
+
req.basic_auth options[:user], options[:password] if options[:user] and options[:password]
|
15
|
+
http_opts = { use_ssl: uri.scheme == 'https' }
|
16
|
+
http_opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE unless options[:verify_ssl]
|
17
|
+
start = Time.now
|
18
|
+
res = Net::HTTP.start uri.host, uri.port, http_opts do |https|
|
19
|
+
https.request req
|
20
|
+
end
|
21
|
+
@duration, @code, @body = (Time.now - start), res.code, res.body
|
22
|
+
res.value #check for success via a spectactularly poorly named method
|
23
|
+
res.body
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'chicanery/handlers'
|
2
|
+
require 'chicanery/site'
|
3
|
+
|
4
|
+
module Chicanery
|
5
|
+
module Sites
|
6
|
+
include Handlers
|
7
|
+
|
8
|
+
def sites
|
9
|
+
@sites ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def site *args
|
13
|
+
sites << Chicanery::Site.new(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_sites current_state, previous_state
|
17
|
+
current_state[:sites] = {}
|
18
|
+
sites.each do |site|
|
19
|
+
begin
|
20
|
+
content = site.get
|
21
|
+
current_state[:sites][site.name] = :up
|
22
|
+
notify_up_handlers site.name, site
|
23
|
+
notify_recovered_handlers site.name, site if previous_state && previous_state[:sites] && previous_state[:sites][site.name] == :down
|
24
|
+
rescue Exception
|
25
|
+
current_state[:sites][site.name] = :down
|
26
|
+
notify_down_handlers site.name, site
|
27
|
+
notify_crashed_handlers site.name, site if previous_state && previous_state[:sites] && previous_state[:sites][site.name] == :up
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/chicanery/summary.rb
CHANGED
data/lib/chicanery.rb
CHANGED
@@ -5,18 +5,18 @@ if ENV['COVERAGE']
|
|
5
5
|
end
|
6
6
|
|
7
7
|
require 'chicanery/persistence'
|
8
|
-
require 'chicanery/
|
9
|
-
require 'chicanery/
|
10
|
-
require 'chicanery/
|
8
|
+
require 'chicanery/servers'
|
9
|
+
require 'chicanery/repos'
|
10
|
+
require 'chicanery/sites'
|
11
11
|
require 'chicanery/summary'
|
12
12
|
|
13
13
|
module Chicanery
|
14
14
|
include Persistence
|
15
|
-
include
|
16
|
-
include
|
17
|
-
include
|
15
|
+
include Servers
|
16
|
+
include Repos
|
17
|
+
include Sites
|
18
18
|
|
19
|
-
VERSION = "0.1.
|
19
|
+
VERSION = "0.1.1"
|
20
20
|
|
21
21
|
def poll_period seconds=nil
|
22
22
|
@poll_period = seconds if seconds
|
@@ -24,40 +24,29 @@ module Chicanery
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def execute args
|
27
|
-
|
28
|
-
|
27
|
+
begin
|
28
|
+
load args.shift
|
29
|
+
run_every poll_period
|
30
|
+
rescue Interrupt
|
31
|
+
end
|
29
32
|
end
|
30
33
|
|
31
34
|
def run_every poll_period
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
sleep poll_period
|
37
|
-
end
|
38
|
-
rescue Interrupt
|
35
|
+
loop do
|
36
|
+
run
|
37
|
+
break unless poll_period
|
38
|
+
sleep poll_period
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
def run
|
43
43
|
previous_state = restore
|
44
|
-
current_state = {
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
repos.each do |repo|
|
49
|
-
repo_state = repo.state
|
50
|
-
compare_repo_state repo.name, repo_state, previous_state[:repos][repo.name] if previous_state[:repos]
|
51
|
-
current_state[:repos][repo.name] = repo_state
|
52
|
-
end
|
53
|
-
servers.each do |server|
|
54
|
-
current_jobs = server.jobs
|
55
|
-
compare_jobs current_jobs, previous_state[:servers][server.name] if previous_state[:servers]
|
56
|
-
current_state[:servers][server.name] = current_jobs
|
57
|
-
end
|
44
|
+
current_state = {}
|
45
|
+
check_servers current_state, previous_state
|
46
|
+
check_repos current_state, previous_state
|
47
|
+
check_sites current_state, previous_state
|
58
48
|
current_state.extend Chicanery::Summary
|
59
49
|
run_handlers.each {|handler| handler.call current_state, previous_state }
|
60
50
|
persist current_state
|
61
51
|
end
|
62
|
-
|
63
52
|
end
|
@@ -52,17 +52,16 @@ describe Chicanery::Cctray do
|
|
52
52
|
}
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
it 'should complain if there are no jobs in response' do
|
57
57
|
VCR.use_cassette('no_projects') do
|
58
58
|
expect{server.jobs}.to raise_error "could not find any jobs in response: [Nothing here but us chickens]"
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
it 'should complain if it gets a non 2xx response' do
|
63
63
|
VCR.use_cassette('redirect') do
|
64
64
|
expect{server.jobs}.to raise_error Net::HTTPRetriableError
|
65
65
|
end
|
66
|
-
end
|
67
|
-
|
66
|
+
end
|
68
67
|
end
|
data/spec/chicanery_spec.rb
CHANGED
@@ -15,10 +15,7 @@ describe Chicanery do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should persist new state' do
|
18
|
-
should_receive(:persist).with
|
19
|
-
servers: {},
|
20
|
-
repos: {}
|
21
|
-
})
|
18
|
+
should_receive(:persist).with servers: {}, repos: {}, sites: {}
|
22
19
|
end
|
23
20
|
|
24
21
|
it 'should sleep for specified time when poll period is provided' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chicanery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01
|
12
|
+
date: 2013-03-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -154,12 +154,15 @@ files:
|
|
154
154
|
- lib/chicanery/git.rb
|
155
155
|
- lib/chicanery/handlers.rb
|
156
156
|
- lib/chicanery/persistence.rb
|
157
|
-
- lib/chicanery/
|
157
|
+
- lib/chicanery/repos.rb
|
158
|
+
- lib/chicanery/servers.rb
|
159
|
+
- lib/chicanery/site.rb
|
160
|
+
- lib/chicanery/sites.rb
|
158
161
|
- lib/chicanery/summary.rb
|
159
162
|
- spec/chicanery/cctray_spec.rb
|
160
163
|
- spec/chicanery/collections_spec.rb
|
161
164
|
- spec/chicanery/persistence_spec.rb
|
162
|
-
- spec/chicanery/
|
165
|
+
- spec/chicanery/servers_spec.rb
|
163
166
|
- spec/chicanery/summary_spec.rb
|
164
167
|
- spec/chicanery_spec.rb
|
165
168
|
- spec/embedded_chicanery_spec.rb
|
@@ -177,7 +180,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
177
180
|
version: '0'
|
178
181
|
segments:
|
179
182
|
- 0
|
180
|
-
hash: -
|
183
|
+
hash: -3139042759217892738
|
181
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
185
|
none: false
|
183
186
|
requirements:
|
@@ -186,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
189
|
version: '0'
|
187
190
|
segments:
|
188
191
|
- 0
|
189
|
-
hash: -
|
192
|
+
hash: -3139042759217892738
|
190
193
|
requirements: []
|
191
194
|
rubyforge_project:
|
192
195
|
rubygems_version: 1.8.23
|
@@ -197,7 +200,7 @@ test_files:
|
|
197
200
|
- spec/chicanery/cctray_spec.rb
|
198
201
|
- spec/chicanery/collections_spec.rb
|
199
202
|
- spec/chicanery/persistence_spec.rb
|
200
|
-
- spec/chicanery/
|
203
|
+
- spec/chicanery/servers_spec.rb
|
201
204
|
- spec/chicanery/summary_spec.rb
|
202
205
|
- spec/chicanery_spec.rb
|
203
206
|
- spec/embedded_chicanery_spec.rb
|