test-rescue-agent 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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6f948ce1f72d8f7d993bc034a71551c3407dd312216f0c9b7e2037c30698a576
4
+ data.tar.gz: 5254ae06d79886f4809acf6dc3bcb33fa2365b84aa07ef98464f51f613843e30
5
+ SHA512:
6
+ metadata.gz: ace19be132cbf1a16fe65ca102494a80c4905ca90482e1352a63ad424d80b5951e9cd2f62294baaae71da618811b7cdebdc82a865f9891eb349d32ec102088d2
7
+ data.tar.gz: a636c268910ea7e1526962870d338e1c539b8bed9a573ddef98d8057050c7c8c54119a9208575e59def4dec723187d56823beec809a0fe5238d9ead9f0520781
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test-rescue-agent'
4
+ TestRescueAgent::TestRunner.run
@@ -0,0 +1,3 @@
1
+ require 'test_rescue_agent/rspec_configuration'
2
+ require 'test_rescue_agent/cucumber_configuration'
3
+ require 'test_rescue_agent/test_runner'
@@ -0,0 +1,40 @@
1
+ return unless ENV["SUITE_RUN_ID"] && ENV["TEST_RESCUE_TYPE"] == "cucumber"
2
+
3
+ require 'test_rescue_agent/test_rescue_client'
4
+ require 'cucumber'
5
+
6
+ client = TestRescueAgent::TestRescueClient.new(
7
+ repository_id: ENV["REPOSITORY_ID"],
8
+ endpoint: ENV["TEST_RESCUE_ENDPOINT"],
9
+ secret: ENV["TEST_RESCUE_SECRET"],
10
+ api_key: ENV["TEST_RESCUE_API_KEY"]
11
+ )
12
+
13
+ at_exit do
14
+ client.complete_file_run(ENV["SUITE_RUN_ID"], ENV["FILE_RUN_ID"])
15
+ end
16
+
17
+ start = nil
18
+ Before do
19
+ start = Time.now
20
+ end
21
+
22
+ After do |scenario|
23
+ failure_details = nil
24
+ if scenario.failed?
25
+ failure_details = [
26
+ scenario.exception.message.lines,
27
+ scenario.exception.backtrace
28
+ ].flatten.join("\n")
29
+ end
30
+ duration = Time.now - start
31
+ client.create_test_run(
32
+ ENV["SUITE_RUN_ID"],
33
+ ENV["FILE_RUN_ID"],
34
+ description: scenario.name,
35
+ location: scenario.location.to_s,
36
+ result: scenario.passed?,
37
+ failure_details: failure_details,
38
+ duration: duration
39
+ )
40
+ end
@@ -0,0 +1,62 @@
1
+ return unless ENV["SUITE_RUN_ID"] && ENV["TEST_RESCUE_TYPE"] == "rspec"
2
+
3
+ require 'test_rescue_agent/test_rescue_client'
4
+ require 'rspec'
5
+
6
+ RSpec.configure do |config|
7
+ def test_rescue_client
8
+ test_rescue_client = TestRescueAgent::TestRescueClient.new(
9
+ repository_id: ENV["REPOSITORY_ID"],
10
+ endpoint: ENV["TEST_RESCUE_ENDPOINT"],
11
+ secret: ENV["TEST_RESCUE_SECRET"],
12
+ api_key: ENV["TEST_RESCUE_API_KEY"]
13
+ )
14
+ end
15
+ config.color = true
16
+ config.tty = true
17
+
18
+ module TestRescueRSpecReporter
19
+ def notify_non_example_exception(exception, context_description)
20
+ example = RSpec::Core::Example.new(RSpec::Core::AnonymousExampleGroup, context_description, {})
21
+ presenter = RSpec::Core::Formatters::ExceptionPresenter.new(exception, example, indentation: 0)
22
+ failure_details = [presenter.colorized_message_lines, presenter.colorized_formatted_backtrace].flatten.join("\n")
23
+
24
+ test_rescue_client.create_file_run_exception(
25
+ ENV["SUITE_RUN_ID"],
26
+ ENV["FILE_RUN_ID"],
27
+ description: example.full_description,
28
+ location: example.location,
29
+ failure_details: failure_details,
30
+ )
31
+ super(exception, context_description)
32
+ end
33
+ end
34
+
35
+ module RSpec::Core
36
+ class Reporter
37
+ prepend TestRescueRSpecReporter
38
+ end
39
+ end
40
+
41
+ at_exit do
42
+ test_rescue_client.complete_file_run(ENV["SUITE_RUN_ID"], ENV["FILE_RUN_ID"])
43
+ end
44
+
45
+ config.after(:each) do |example|
46
+ failure_details = nil
47
+ if example.exception
48
+ presenter = RSpec::Core::Formatters::ExceptionPresenter.new(example.exception, example)
49
+ failure_details = [presenter.colorized_message_lines, presenter.colorized_formatted_backtrace].flatten.join("\n")
50
+ end
51
+ duration = Time.now - example.execution_result.started_at
52
+ test_rescue_client.create_test_run(
53
+ ENV["SUITE_RUN_ID"],
54
+ ENV["FILE_RUN_ID"],
55
+ description: example.full_description,
56
+ location: example.location,
57
+ result: !example.exception,
58
+ failure_details: failure_details,
59
+ duration: duration
60
+ )
61
+ end
62
+ end
@@ -0,0 +1,96 @@
1
+ require 'test_rescue_agent/test_rescue_client/suite_run'
2
+ require 'test_rescue_agent/test_rescue_client/file_run'
3
+ require 'test_rescue_agent/test_rescue_client/file_run_exception'
4
+ require 'test_rescue_agent/test_rescue_client/test_run'
5
+ require 'httparty'
6
+ begin
7
+ require 'webmock'
8
+ rescue LoadError
9
+ end
10
+
11
+ module TestRescueAgent
12
+ class TestRescueClient
13
+ def initialize(options={})
14
+ @endpoint = options[:endpoint]
15
+ @repository_id = options[:repository_id]
16
+ @api_key = options[:api_key]
17
+ @secret = options[:secret]
18
+ end
19
+
20
+ def create_suite_run(sha:)
21
+ response = post('/suite_runs', suite_run: {
22
+ head_branch: 'master',
23
+ sha: sha,
24
+ title: 'Collect Pull Request Title from GitHub'
25
+ })
26
+ TestRescueClient::SuiteRun.new(self, JSON.parse(response.body))
27
+ end
28
+
29
+ def create_file_run(suite_run_id, attributes)
30
+ response = post("/suite_runs/#{suite_run_id}/file_runs", file_run: attributes)
31
+ TestRescueClient::FileRun.new(self, JSON.parse(response.body))
32
+ end
33
+
34
+ def create_file_run_exception(suite_run_id, file_run_id, attributes)
35
+ response = post("/suite_runs/#{suite_run_id}/file_runs/#{file_run_id}/exceptions", file_run_exception: attributes)
36
+ TestRescueClient::FileRunException.new(self, JSON.parse(response.body))
37
+ end
38
+
39
+ def claim_file_run(suite_run_id, container_id)
40
+ response = post("/suite_runs/#{suite_run_id}/file_runs/claim", container_id: container_id)
41
+ json = JSON.parse(response.body)
42
+ TestRescueClient::FileRun.new(self, json) if json
43
+ end
44
+
45
+ def complete_file_run(suite_run_id, file_run_id)
46
+ update_file_run(suite_run_id, file_run_id, {completed_at: Time.now.iso8601})
47
+ end
48
+
49
+ def update_file_run(suite_run_id, file_run_id, attributes)
50
+ patch("/suite_runs/#{suite_run_id}/file_runs/#{file_run_id}", file_run: attributes)
51
+ end
52
+
53
+ def create_test_run(suite_run_id, file_run_id, attributes)
54
+ response = post("/suite_runs/#{suite_run_id}/file_runs/#{file_run_id}/test_runs", test_run: attributes)
55
+ TestRescueClient::TestRun.new(self, JSON.parse(response.body))
56
+ end
57
+
58
+ private
59
+
60
+ def headers
61
+ {
62
+ 'Content-Type' => 'application/json',
63
+ 'Accept' => 'application/json',
64
+ 'X-Api-Key' => @api_key,
65
+ 'X-Api-Secret' => @secret
66
+ }
67
+ end
68
+
69
+ def handle_webmock
70
+ instance = WebMock::Config.instance
71
+ if instance.allow.nil?
72
+ instance.allow = 'www.testrescue.com'
73
+ elsif instance.allow.is_a?(Array)
74
+ instance.allow.push('www.testrescue.com') unless instance.allow.include?('www.testrescue.com')
75
+ else
76
+ WebMock::Config.instance.allow = [WebMock::Config.instance.allow, 'www.testrescue.com']
77
+ end
78
+ rescue NameError
79
+ # no problem. webmock not being resident means this code wasn't needed anyway
80
+ rescue
81
+ # TODO: report this to sentry, but still try to move on
82
+ end
83
+
84
+ def post(path, body)
85
+ handle_webmock
86
+ url = "#{@endpoint}/repositories/#{@repository_id}#{path}"
87
+ HTTParty.post(url, body: body.to_json, headers: headers)
88
+ end
89
+
90
+ def patch(path, body)
91
+ handle_webmock
92
+ url = "#{@endpoint}/repositories/#{@repository_id}#{path}"
93
+ HTTParty.patch(url, body: body.to_json, headers: headers)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,23 @@
1
+ module TestRescueAgent
2
+ class TestRescueClient
3
+ class FileRun
4
+ attr_reader :id, :path, :description, :suite_run_id, :test_file_id, :created_at, :updated_at, :command
5
+
6
+ def initialize(client, attributes={})
7
+ @client = client
8
+ @id = attributes["id"]
9
+ @path = attributes["path"]
10
+ @description = attributes["description"]
11
+ @suite_run_id = attributes["suite_run_id"]
12
+ @test_file_id = attributes["test_file_id"]
13
+ @created_at = attributes["created_at"]
14
+ @updated_at = attributes["updated_at"]
15
+ @command = attributes["command"]
16
+ end
17
+
18
+ def create_test_run(attributes)
19
+ @client.create_test_run(suite_run_id, id, attributes)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module TestRescueAgent
2
+ class TestRescueClient
3
+ class FileRunException
4
+ attr_reader :id, :suite_run_id, :file_run_id, :description, :location, :failure_details
5
+
6
+ def initialize(client, attributes={})
7
+ @client = client
8
+ @id = attributes["id"]
9
+ @suite_run_id = attributes["suite_run_id"]
10
+ @file_run_id = attributes["file_run_id"]
11
+ @description = attributes["description"]
12
+ @location = attributes["location"]
13
+ @failure_details = attributes["failure_details"]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module TestRescueAgent
2
+ class TestRescueClient
3
+ class SuiteRun
4
+ attr_reader :id, :repository_id, :created_at, :updated_at
5
+
6
+ def initialize(client, attributes={})
7
+ @client = client
8
+ @id = attributes["id"]
9
+ @repository_id = attributes["repository_id"]
10
+ @created_at = attributes["created_at"]
11
+ @updated_at = attributes["updated_at"]
12
+ end
13
+
14
+ def create_file_run(attributes)
15
+ @client.create_file_run(id, attributes)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module TestRescueAgent
2
+ class TestRescueClient
3
+ class TestRun
4
+ attr_reader :id, :file_run_id, :test_id, :description, :location, :result, :failure_details, :created_at, :updated_at
5
+
6
+ def initialize(client, attributes={})
7
+ @client = client
8
+ @id = attributes["id"]
9
+ @file_run_id = attributes["file_run_id"]
10
+ @test_id = attributes["test_id"]
11
+ @description = attributes["description"]
12
+ @location = attributes["location"]
13
+ @result = attributes["result"]
14
+ @failure_details = attributes["failure_details"]
15
+ @created_at = attributes["created_at"]
16
+ @updated_at = attributes["updated_at"]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ require 'test_rescue_agent/test_rescue_client'
2
+
3
+ module TestRescueAgent
4
+ class TestRunner
5
+ def self.run
6
+ client = TestRescueAgent::TestRescueClient.new(
7
+ repository_id: ENV["REPOSITORY_ID"],
8
+ endpoint: ENV["TEST_RESCUE_ENDPOINT"],
9
+ secret: ENV["TEST_RESCUE_SECRET"],
10
+ api_key: ENV["TEST_RESCUE_API_KEY"]
11
+ )
12
+ while file_run = client.claim_file_run(ENV["SUITE_RUN_ID"], ENV["CONTAINER_ID"])
13
+ puts "running \"#{file_run.command}\""
14
+ `#{file_run.command}`
15
+ end
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: test-rescue-agent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Fogle
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
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'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: |
42
+ Test Rescue is a massively parallelized continuous testing platform,
43
+ (http://www.testrescue.com). Test Rescue provides you with large scale
44
+ Test automation execution performance by parallelizing each individual
45
+ test in its own container automatically provisioned and run in the cloud.
46
+ Results are provided live as your tests complete.
47
+ Test Rescue provides you with deep information about the performance
48
+ of your test suite as it runs. The Test Rescue Agent is a Gem, hosted on
49
+ https://github.com/fogle/test-rescue-agent/
50
+ email: support@testrescue.com
51
+ executables:
52
+ - test-rescue
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - bin/test-rescue
57
+ - lib/test-rescue-agent.rb
58
+ - lib/test_rescue_agent/cucumber_configuration.rb
59
+ - lib/test_rescue_agent/rspec_configuration.rb
60
+ - lib/test_rescue_agent/test_rescue_client.rb
61
+ - lib/test_rescue_agent/test_rescue_client/file_run.rb
62
+ - lib/test_rescue_agent/test_rescue_client/file_run_exception.rb
63
+ - lib/test_rescue_agent/test_rescue_client/suite_run.rb
64
+ - lib/test_rescue_agent/test_rescue_client/test_run.rb
65
+ - lib/test_rescue_agent/test_runner.rb
66
+ homepage: https://github.com/fogle/test-rescue-agent
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 2.0.0
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">"
82
+ - !ruby/object:Gem::Version
83
+ version: 1.3.1
84
+ requirements: []
85
+ rubygems_version: 3.0.3
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Test Rescue Ruby Agent
89
+ test_files: []