right_support 2.5.5 → 2.6.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/lib/right_support/ci/junit_cucumber_formatter.rb +31 -0
- data/lib/right_support/ci/junit_rspec_formatter.rb +170 -0
- data/lib/right_support/ci/rake_task.rb +73 -0
- data/lib/right_support/ci.rb +11 -0
- data/lib/right_support/net/request_balancer.rb +2 -2
- data/lib/right_support/net/s3_helper.rb +18 -5
- data/lib/right_support.rb +5 -4
- data/right_support.gemspec +2 -2
- metadata +9 -5
@@ -0,0 +1,31 @@
|
|
1
|
+
module RightSupport::CI
|
2
|
+
if require_succeeds?('cucumber/formatter/junit')
|
3
|
+
class JUnitCucumberFormatter < Cucumber::Formatter::Junit
|
4
|
+
private
|
5
|
+
|
6
|
+
def build_testcase(duration, status, exception = nil, suffix = "")
|
7
|
+
@time += duration
|
8
|
+
# Use "cucumber" as a pseudo-package, and the feature name as a pseudo-class
|
9
|
+
classname = "cucumber.#{@feature_name}"
|
10
|
+
name = "#{@scenario}#{suffix}"
|
11
|
+
pending = [:pending, :undefined].include?(status)
|
12
|
+
passed = (status == :passed || (pending && !@options[:strict]))
|
13
|
+
|
14
|
+
@builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
|
15
|
+
unless passed
|
16
|
+
@builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
|
17
|
+
@builder.cdata! @output
|
18
|
+
@builder.cdata!(format_exception(exception)) if exception
|
19
|
+
end
|
20
|
+
@failures += 1
|
21
|
+
end
|
22
|
+
if passed and (status == :skipped || pending)
|
23
|
+
@builder.skipped
|
24
|
+
@skipped += 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
@tests += 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# Copyright (c) 2009-2011 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and the licensee.
|
10
|
+
|
11
|
+
require 'time'
|
12
|
+
|
13
|
+
module RightSupport::CI
|
14
|
+
if require_succeeds?('spec/runner/formatter/base_text_formatter')
|
15
|
+
# RSpec 1.x
|
16
|
+
class JUnitRSpecFormatter < Spec::Runner::Formatter::BaseTextFormatter
|
17
|
+
def initialize(*args)
|
18
|
+
begin
|
19
|
+
require 'builder'
|
20
|
+
rescue LoadError => e
|
21
|
+
raise NotImplementedError, "Your Gemfile or gemspec must include builder (~> 3.0) in order to use this class"
|
22
|
+
end
|
23
|
+
super(*args)
|
24
|
+
@current_example_group = nil
|
25
|
+
@test_times = {}
|
26
|
+
@test_groups = {}
|
27
|
+
@test_results = {}
|
28
|
+
@test_failures = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def example_group_started(example)
|
32
|
+
@current_example_group = example
|
33
|
+
end
|
34
|
+
|
35
|
+
def example_started(example)
|
36
|
+
@test_groups[example] = @current_example_group
|
37
|
+
@example_started_at = Time.now
|
38
|
+
end
|
39
|
+
|
40
|
+
def example_passed(example)
|
41
|
+
@test_times[example] = Time.now - @example_started_at
|
42
|
+
@test_results[example] = 'passed'
|
43
|
+
end
|
44
|
+
|
45
|
+
def example_failed(example, counter, failure)
|
46
|
+
@test_times[example] = Time.now - @example_started_at
|
47
|
+
@test_results[example] = 'failed'
|
48
|
+
@test_failures[example] = failure
|
49
|
+
end
|
50
|
+
|
51
|
+
def example_pending(example)
|
52
|
+
@test_times[example] = Time.now - @example_started_at
|
53
|
+
@test_results[example] = 'pending'
|
54
|
+
end
|
55
|
+
|
56
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
57
|
+
builder = Builder::XmlMarkup.new :indent => 2
|
58
|
+
builder.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
|
59
|
+
builder.testsuite :errors => 0, :failures => failure_count, :skipped => pending_count, :tests => example_count, :time => duration, :timestamp => Time.now.iso8601 do
|
60
|
+
builder.properties
|
61
|
+
@test_results.each_pair do |test, result|
|
62
|
+
classname = classname_for(test)
|
63
|
+
full_description = test.description
|
64
|
+
|
65
|
+
# The full description always begins with the classname, but this is useless info when
|
66
|
+
# generating the XML report.
|
67
|
+
if full_description.start_with?(classname)
|
68
|
+
full_description = full_description[classname.length..-1].strip
|
69
|
+
end
|
70
|
+
|
71
|
+
builder.testcase(:classname => classname, :name => full_description, :time => @test_times[test]) do
|
72
|
+
case result
|
73
|
+
when "failed"
|
74
|
+
builder.failure :message => "failed #{full_description}", :type => "failed" do
|
75
|
+
builder.cdata! failure_details_for(test)
|
76
|
+
end
|
77
|
+
when "pending" then
|
78
|
+
builder.skipped
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
output.puts builder.target!
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def failure_details_for(example)
|
89
|
+
exception = @test_failures[example].exception
|
90
|
+
exception.nil? ? "" : "#{exception.message}\n#{format_backtrace(exception.backtrace, example).join("\n")}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def classname_for(example)
|
94
|
+
# Take our best guess, by looking at the description of the example group
|
95
|
+
# and assuming the first word is a class name
|
96
|
+
group = @test_groups[example]
|
97
|
+
klass = group.description.split(/\s+/).first
|
98
|
+
"rspec.#{klass}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
elsif require_succeeds?('rspec/core/formatters/base_formatter')
|
102
|
+
# RSpec 2.x
|
103
|
+
class JUnitRSpecFormatter < RSpec::Core::Formatters::BaseFormatter
|
104
|
+
def initialize(*args)
|
105
|
+
begin
|
106
|
+
require 'builder'
|
107
|
+
rescue LoadError => e
|
108
|
+
raise NotImplementedError, "Your Gemfile or gemspec must include builder (~> 3.0) in order to use this class"
|
109
|
+
end
|
110
|
+
super(*args)
|
111
|
+
@test_results = []
|
112
|
+
end
|
113
|
+
|
114
|
+
def example_passed(example)
|
115
|
+
@test_results << example
|
116
|
+
end
|
117
|
+
|
118
|
+
def example_failed(example)
|
119
|
+
@test_results << example
|
120
|
+
end
|
121
|
+
|
122
|
+
def example_pending(example)
|
123
|
+
@test_results << example
|
124
|
+
end
|
125
|
+
|
126
|
+
def failure_details_for(example)
|
127
|
+
exception = example.exception
|
128
|
+
exception.nil? ? "" : "#{exception.message}\n#{format_backtrace(exception.backtrace, example).join("\n")}"
|
129
|
+
end
|
130
|
+
|
131
|
+
def classname_for(example)
|
132
|
+
eg = example.metadata[:example_group]
|
133
|
+
eg = eg[:example_group] while eg.key?(:example_group)
|
134
|
+
klass = eg[:description_args].to_s
|
135
|
+
"rspec.#{klass}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
139
|
+
builder = Builder::XmlMarkup.new :indent => 2
|
140
|
+
builder.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
|
141
|
+
builder.testsuite :errors => 0, :failures => failure_count, :skipped => pending_count, :tests => example_count, :time => duration, :timestamp => Time.now.iso8601 do
|
142
|
+
builder.properties
|
143
|
+
@test_results.each do |test|
|
144
|
+
classname = classname_for(test)
|
145
|
+
full_description = test.full_description
|
146
|
+
time = test.metadata[:execution_result][:run_time]
|
147
|
+
|
148
|
+
# The full description always begins with the classname, but this is useless info when
|
149
|
+
# generating the XML report.
|
150
|
+
if full_description.start_with?(classname)
|
151
|
+
full_description = full_description[classname.length..-1].strip
|
152
|
+
end
|
153
|
+
|
154
|
+
builder.testcase(:classname => classname, :name => full_description, :time => time) do
|
155
|
+
case test.metadata[:execution_result][:status]
|
156
|
+
when "failed"
|
157
|
+
builder.failure :message => "failed #{full_description}", :type => "failed" do
|
158
|
+
builder.cdata! failure_details_for test
|
159
|
+
end
|
160
|
+
when "pending" then
|
161
|
+
builder.skipped
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
output.puts builder.target!
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'rake/tasklib'
|
2
|
+
|
3
|
+
# Make sure the rest of RightSupport is required, since this file can be
|
4
|
+
# required directly.
|
5
|
+
require 'right_support'
|
6
|
+
|
7
|
+
module RightSupport::CI
|
8
|
+
# A Rake task definition that creates a CI namespace with appropriate
|
9
|
+
# tests.
|
10
|
+
class RakeTask < ::Rake::TaskLib
|
11
|
+
include ::Rake::DSL if defined?(::Rake::DSL)
|
12
|
+
|
13
|
+
# The namespace in which to define the continuous integration tasks.
|
14
|
+
#
|
15
|
+
# Default :ci
|
16
|
+
attr_accessor :ci_namespace
|
17
|
+
|
18
|
+
# The base directory for output files.
|
19
|
+
#
|
20
|
+
# Default 'measurement'
|
21
|
+
attr_accessor :output_path
|
22
|
+
|
23
|
+
def initialize(*args)
|
24
|
+
@ci_namespace = args.shift || :ci
|
25
|
+
|
26
|
+
yield self if block_given?
|
27
|
+
|
28
|
+
@output_path ||= 'measurement'
|
29
|
+
|
30
|
+
namespace @ci_namespace do
|
31
|
+
task :prep do
|
32
|
+
FileUtils.mkdir_p('measurement')
|
33
|
+
|
34
|
+
# Tweak RUBYOPT so RubyGems and RightSupport are automatically required.
|
35
|
+
# This is necessary because Cucumber doesn't have a -r equivalent we can
|
36
|
+
# use to inject ourselves into its process. (There is an -r, but it disables
|
37
|
+
# auto-loading.)
|
38
|
+
rubyopt = '-rright_support'
|
39
|
+
if ENV.key?('RUBYOPT')
|
40
|
+
rubyopt = ENV['RUBYOPT'] + ' ' + rubyopt
|
41
|
+
rubyopt = '-rrubygems ' + rubyopt unless (rubyopt =~ /ubygems/)
|
42
|
+
end
|
43
|
+
ENV['RUBYOPT'] = rubyopt
|
44
|
+
end
|
45
|
+
|
46
|
+
if require_succeeds?('rspec/core/rake_task')
|
47
|
+
# RSpec 2
|
48
|
+
desc "Run RSpec examples"
|
49
|
+
RSpec::Core::RakeTask.new(:spec => :prep) do |t|
|
50
|
+
t.rspec_opts = ['-f', JUnitRSpecFormatter.name,
|
51
|
+
'-o', File.join(@output_path, 'rspec', 'rspec.xml')]
|
52
|
+
end
|
53
|
+
elsif require_succeeds?('spec/rake/spectask')
|
54
|
+
# RSpec 1
|
55
|
+
Spec::Rake::SpecTask.new(:spec => :prep) do |t|
|
56
|
+
desc "Run RSpec Examples"
|
57
|
+
t.spec_opts = ['-f', JUnitRSpecFormatter.name + ":" + File.join(@output_path, 'rspec', 'rspec.xml')]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if require_succeeds?('cucumber/rake/task')
|
62
|
+
desc "Run Cucumber features"
|
63
|
+
Cucumber::Rake::Task.new do |t|
|
64
|
+
t.cucumber_opts = ['--no-color',
|
65
|
+
'--format', JUnitCucumberFormatter.name,
|
66
|
+
'--out', File.join(@output_path, 'cucumber')]
|
67
|
+
end
|
68
|
+
task :cucumber => [:prep]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module RightSupport
|
2
|
+
module CI
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'right_support/ci/junit_cucumber_formatter'
|
7
|
+
require 'right_support/ci/junit_rspec_formatter'
|
8
|
+
|
9
|
+
# Don't auto-require the Rake task; it mixes the Rake DSL into everything!
|
10
|
+
# Must defer loading of the Rake task to the Rakefiles
|
11
|
+
#require 'right_support/ci/rake_task'
|
@@ -63,10 +63,10 @@ module RightSupport::Net
|
|
63
63
|
# reflection to handle ALL RSpec-related exceptions.
|
64
64
|
spec_namespaces = if require_succeeds?('rspec')
|
65
65
|
# RSpec 2.x
|
66
|
-
[RSpec::Mocks, RSpec::Expectations]
|
66
|
+
[::RSpec::Mocks, ::RSpec::Expectations]
|
67
67
|
elsif require_succeeds?('spec')
|
68
68
|
# RSpec 1.x
|
69
|
-
[Spec::Expectations]
|
69
|
+
[::Spec::Expectations]
|
70
70
|
else
|
71
71
|
# RSpec is not present
|
72
72
|
[]
|
@@ -23,6 +23,8 @@ module RightSupport::Net
|
|
23
23
|
# RightSupport::Net::S3Helper.init(s3_config, Rightscale::S3, Encryptor)
|
24
24
|
# s3_health = RightSupport::Net::S3Helper.health_check
|
25
25
|
class S3Helper
|
26
|
+
class BucketNotFound < Exception; end
|
27
|
+
|
26
28
|
# Init() is the first method which must be called.
|
27
29
|
# This is configuration and integration with S3 and Encryptor
|
28
30
|
#
|
@@ -36,12 +38,22 @@ module RightSupport::Net
|
|
36
38
|
# @param [Class] encryptor Class which will be used to encrypt data
|
37
39
|
# encrypt() and decrypt() methods must be implemented
|
38
40
|
#
|
39
|
-
#
|
41
|
+
# @raise BucketNotFound if bucket name specified in config["bucket_name"] does not exist
|
42
|
+
#
|
43
|
+
# @return [true] always returns true
|
40
44
|
def self.init(config, s3, encryptor)
|
41
45
|
@config = config
|
42
46
|
@s3class = s3
|
43
47
|
@encryptor = encryptor
|
48
|
+
|
49
|
+
# Reset any S3 objects we'd been caching, since config may have changed
|
50
|
+
@s3 = @bucket = nil
|
51
|
+
# Make sure our bucket exists -- better to do it now than on first access!
|
52
|
+
self.bucket
|
53
|
+
|
54
|
+
true
|
44
55
|
end
|
56
|
+
|
45
57
|
# Checks S3 credentials syntax in config parameter
|
46
58
|
#
|
47
59
|
# @return [Boolean] true if s3 creadentials are ok or false if not
|
@@ -56,15 +68,16 @@ module RightSupport::Net
|
|
56
68
|
def self.config
|
57
69
|
@config
|
58
70
|
end
|
59
|
-
#
|
71
|
+
# Create (if does not exist) and return S3 object
|
60
72
|
def self.s3
|
61
73
|
@s3 ||= @s3class.new config["creds"]["aws_access_key_id"], config["creds"]["aws_secret_access_key"]
|
62
74
|
end
|
63
|
-
#
|
75
|
+
# Create Bucket object using S3 object
|
76
|
+
# @raise BucketNotFound if bucket name specified in config["bucket_name"] does not exist
|
64
77
|
def self.bucket
|
65
|
-
#TO DISCUSS: second param 'true' means 'create new bucket'
|
66
|
-
#@bucket ||= s3.bucket(config["bucket_name"], true)
|
67
78
|
@bucket ||= s3.bucket(config["bucket_name"])
|
79
|
+
raise BucketNotFound, "Bucket #{config["bucket_name"]} does not exist" if @bucket.nil?
|
80
|
+
@bucket
|
68
81
|
end
|
69
82
|
# Returns Master secret from config
|
70
83
|
def self.master_secret
|
data/lib/right_support.rb
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
require 'thread'
|
3
3
|
|
4
4
|
require 'right_support/ruby'
|
5
|
+
require 'right_support/log'
|
5
6
|
require 'right_support/data'
|
7
|
+
require 'right_support/validation'
|
6
8
|
require 'right_support/crypto'
|
7
|
-
require 'right_support/
|
9
|
+
require 'right_support/rack'
|
8
10
|
require 'right_support/db'
|
9
|
-
require 'right_support/log'
|
10
11
|
require 'right_support/net'
|
11
|
-
require 'right_support/
|
12
|
+
require 'right_support/config'
|
12
13
|
require 'right_support/stats'
|
13
|
-
require 'right_support/
|
14
|
+
require 'right_support/ci'
|
data/right_support.gemspec
CHANGED
@@ -7,8 +7,8 @@ spec = Gem::Specification.new do |s|
|
|
7
7
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
8
8
|
|
9
9
|
s.name = 'right_support'
|
10
|
-
s.version = '2.
|
11
|
-
s.date = '2012-
|
10
|
+
s.version = '2.6.1'
|
11
|
+
s.date = '2012-11-07'
|
12
12
|
|
13
13
|
s.authors = ['Tony Spataro', 'Sergey Sergyenko', 'Ryan Williamson', 'Lee Kirchhoff', 'Sergey Enin', 'Alexey Karpik']
|
14
14
|
s.email = 'support@rightscale.com'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 2.
|
8
|
+
- 6
|
9
|
+
- 1
|
10
|
+
version: 2.6.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tony Spataro
|
@@ -20,7 +20,7 @@ autorequire:
|
|
20
20
|
bindir: bin
|
21
21
|
cert_chain: []
|
22
22
|
|
23
|
-
date: 2012-
|
23
|
+
date: 2012-11-07 00:00:00 -08:00
|
24
24
|
default_executable:
|
25
25
|
dependencies: []
|
26
26
|
|
@@ -36,6 +36,10 @@ files:
|
|
36
36
|
- LICENSE
|
37
37
|
- README.rdoc
|
38
38
|
- lib/right_support.rb
|
39
|
+
- lib/right_support/ci.rb
|
40
|
+
- lib/right_support/ci/junit_cucumber_formatter.rb
|
41
|
+
- lib/right_support/ci/junit_rspec_formatter.rb
|
42
|
+
- lib/right_support/ci/rake_task.rb
|
39
43
|
- lib/right_support/config.rb
|
40
44
|
- lib/right_support/config/feature_set.rb
|
41
45
|
- lib/right_support/config/recursive_true_class.rb
|