Module: RScout

Defined in:
lib/rscout.rb

Constant Summary collapse

DEFAULT_LOGGER =
Logger.new(STDOUT)
DEFAULT_OPTIONS =
{
  logger: DEFAULT_LOGGER,
  verbose: false,
  env: 'development',
  from_email: 'rscout@localhost'
}

Class Method Summary collapse

Class Method Details

.capture_stdout(&block) ⇒ Object



156
157
158
159
160
161
162
# File 'lib/rscout.rb', line 156

def capture_stdout(&block)
  previous_stdout, $stdout = $stdout, StringIO.new
  yield
  $stdout.string
ensure
  $stdout = previous_stdout
end

.envObject



37
38
39
# File 'lib/rscout.rb', line 37

def env
  options[:env]
end

.log(msg) ⇒ Object



29
30
31
# File 'lib/rscout.rb', line 29

def log(msg)
  options[:logger].add(options[:severity]) { msg }
end

.loggerObject



33
34
35
# File 'lib/rscout.rb', line 33

def logger
  options[:logger]
end

.optionsObject



25
26
27
# File 'lib/rscout.rb', line 25

def options
  @@options ||= DEFAULT_OPTIONS.clone
end

.run_suite(dir) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rscout.rb', line 41

def run_suite(dir)
  verbose = options[:verbose]
  gemfile = File.join(dir, 'Gemfile')
  configfile = File.join(dir, 'config', 'rscout.yml')

  Bundler.with_clean_env do
    Dir.chdir(dir) do
      yaml = Hashie::Mash.new(YAML.load_file configfile)
      config = yaml[env]

      output = Hashie::Mash.new({
        txt: StringIO.new,
        html: StringIO.new,
        json: StringIO.new,
        stdout: nil,
        results: nil,
        error: Hashie::Mash.new({backtrace:[], message:nil})
      })

      failed = false
      begin
        html_formatter = RSpec::Core::Formatters::HtmlFormatter.new output.html
        txt_formatter = RSpec::Core::Formatters::DocumentationFormatter.new output.txt
        json_formatter = RSpec::Core::Formatters::JsonFormatter.new output.json

        reporter = RSpec::Core::Reporter.new(json_formatter, txt_formatter, html_formatter)

        rspec = RSpec.configuration
        rspec.instance_variable_set(:@reporter, reporter)

        tests = Dir.glob File.join(dir, 'spec/**/*_spec.rb')

        rspec_task = lambda { RSpec::Core::Runner.run tests }

        if verbose
          rspec_task.call
        else
          output.stdout = capture_stdout &rspec_task
        end

        output.results = json_formatter.output_hash

        failed = output.results[:summary][:failure_count] > 0
        failure_count = output.results[:summary][:failure_count].to_s
      rescue => e
        failed = true
        logger.error "Exception encountered while running RSpec: #{e.message}"
        logger.error e.backtrace
        output.error = e
      ensure
        output.txt.close unless output.txt.closed?
        output.html.close unless output.html.closed?
        output.json.close unless output.json.closed?
      end

      if failed
        logger.info "Tests failed."
        send_failure_notifications config, env, output
      end

      failed
    end
  end
end

.send_failure_notifications(config, env, output) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/rscout.rb', line 106

def send_failure_notifications(config, env, output)
  email_body = [output.txt.string, output.error.backtrace.join("\n")].join("\n")
  if config.email_enabled && config.email
    logger.info "Sending emails alert to #{config.email}"
    begin
      mail = Mail.new do
        from     options[:from_email]
        to       config.email
        subject  "RScout Alert: Tests failing on #{config.name.to_s.humanize.titleize} (#{env})"
        add_file filename: 'results.html', content: output.html.string

        header["X-Priority"] = "1 (Highest)"
        header["X-MSMail-Priority"] = "High"
        header["Importance"] = "High"

        text_part do
          body email_body
        end
      end

      mail.deliver!
    rescue => e
      logger.error "Failed to send email alert!"
      logger.error e.message + "\n " + e.backtrace.join("\n ")
    end
  end

  if config.pagerduty_enabled && config.pagerduty_service_key
    logger.info "Triggering PagerDuty incident to #{config.pagerduty_service_key}"
    begin
      if config.pagerduty_service_key.match(/@(.*)pagerduty.com$/)
        mail = Mail.new do
           from    options[:from_email]
           to      config.pagerduty_service_key
           subject "DOWN alert: RScout tests failing on #{config.name.to_s.humanize.titleize} (#{env})"
           body    email_body
        end

        mail.deliver!
      else
        p = Pagerduty.new config.pagerduty_service_key, ['scout', env].join('_')
        incident = p.trigger 'RScout tests failing!', output.results
      end
    rescue => e
      logger.error "Failed to send PagerDuty alert!"
      logger.error e.message + "\n " + e.backtrace.join("\n ")
    end
  end
end