crashbreak 0.0.2 → 0.9.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.
- checksums.yaml +4 -4
- data/crashbreak.gemspec +3 -0
- data/lib/crashbreak.rb +16 -2
- data/lib/crashbreak/AWS.rb +30 -0
- data/lib/crashbreak/config/configurator.rb +29 -0
- data/lib/crashbreak/dumpers_data_repository.rb +34 -0
- data/lib/crashbreak/exception_notifier.rb +14 -4
- data/lib/crashbreak/exceptions_repository.rb +24 -4
- data/lib/crashbreak/github_integration_service.rb +65 -0
- data/lib/crashbreak/request_parser.rb +33 -0
- data/lib/crashbreak/version.rb +1 -1
- data/lib/dumpers/database_dumper.rb +39 -0
- data/lib/dumpers/request_dumper.rb +15 -0
- data/lib/generators/crashbreak/templates/test.rb +11 -0
- data/lib/generators/crashbreak/test_generator.rb +12 -0
- data/lib/restorers/database_restorer.rb +35 -0
- data/lib/restorers/request_restorer.rb +9 -0
- data/lib/restorers/state_restorer.rb +37 -0
- data/lib/tasks/crashbreak.rake +14 -0
- data/spec/dumpers/request_dumper_spec.rb +14 -0
- data/spec/features/sending_error_report_spec.rb +6 -4
- data/spec/lib/dumpers_data_repository_spec.rb +19 -0
- data/spec/lib/exception_notifier_spec.rb +36 -2
- data/spec/lib/exceptions_repository_spec.rb +12 -2
- data/spec/lib/generators/test_generator_spec.rb +16 -0
- data/spec/lib/github_integration_service_spec.rb +47 -0
- data/spec/lib/request_sender_spec.rb +33 -0
- data/spec/restorers/state_restorer_spec.rb +29 -0
- metadata +67 -8
- data/lib/dumpers/program_name_dumper.rb +0 -16
- data/lib/restorers/program_name_restorer.rb +0 -7
- data/spec/dumpers/program_name_dumper_spec.rb +0 -12
- data/spec/restorers/program_name_restorer_spec.rb +0 -11
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 29371eea672de29bc9369c0280e99a3c16d08ca8
         | 
| 4 | 
            +
              data.tar.gz: 432c7a98e58df84245f5b4f27a8aa5cfb541969c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 115c2e65b82096eb44a8550a4dbdb6a48a52f05e0358d4913b57a9f1d4e0a40b5b66079aebb4403eb2d646bc881d28b8081478643327ca87346f163a3ec86784
         | 
| 7 | 
            +
              data.tar.gz: 8046ae60fb3f1722f9c326e932a36901c86612e9a1161b4a06abf7fbb1be8910558705985cf8bdd4797981d808b3095a4312cbdee81a4eacc8ae75658760a218
         | 
    
        data/crashbreak.gemspec
    CHANGED
    
    | @@ -22,7 +22,10 @@ Gem::Specification.new do |spec| | |
| 22 22 | 
             
              spec.add_development_dependency 'rails'
         | 
| 23 23 | 
             
              spec.add_development_dependency 'webmock'
         | 
| 24 24 | 
             
              spec.add_development_dependency 'simplecov'
         | 
| 25 | 
            +
              spec.add_development_dependency 'deepstruct'
         | 
| 25 26 |  | 
| 26 27 | 
             
              spec.add_runtime_dependency 'faraday', '>= 0'
         | 
| 27 28 | 
             
              spec.add_runtime_dependency 'request_store', '>= 0'
         | 
| 29 | 
            +
              spec.add_runtime_dependency 'octokit', '>= 0'
         | 
| 30 | 
            +
              spec.add_runtime_dependency 'aws-sdk', '~> 2'
         | 
| 28 31 | 
             
            end
         | 
    
        data/lib/crashbreak.rb
    CHANGED
    
    | @@ -1,6 +1,8 @@ | |
| 1 1 | 
             
            require 'rails'
         | 
| 2 2 | 
             
            require 'faraday'
         | 
| 3 3 | 
             
            require 'request_store'
         | 
| 4 | 
            +
            require 'octokit'
         | 
| 5 | 
            +
            require 'aws-sdk'
         | 
| 4 6 | 
             
            require 'crashbreak/version'
         | 
| 5 7 | 
             
            require 'crashbreak/exception_notifier'
         | 
| 6 8 | 
             
            require 'crashbreak/formatters/basic_formatter'
         | 
| @@ -13,9 +15,17 @@ require 'crashbreak/config/configurator' | |
| 13 15 | 
             
            require 'crashbreak/config/configurable'
         | 
| 14 16 | 
             
            require 'crashbreak/exception_catcher_middleware'
         | 
| 15 17 | 
             
            require 'crashbreak/exceptions_repository'
         | 
| 18 | 
            +
            require 'crashbreak/dumpers_data_repository'
         | 
| 19 | 
            +
            require 'crashbreak/request_parser'
         | 
| 20 | 
            +
            require 'crashbreak/github_integration_service'
         | 
| 21 | 
            +
            require 'crashbreak/aws'
         | 
| 16 22 |  | 
| 17 | 
            -
            require 'dumpers/ | 
| 18 | 
            -
            require ' | 
| 23 | 
            +
            require 'dumpers/database_dumper'
         | 
| 24 | 
            +
            require 'dumpers/request_dumper'
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            require 'restorers/database_restorer'
         | 
| 27 | 
            +
            require 'restorers/state_restorer'
         | 
| 28 | 
            +
            require 'restorers/request_restorer'
         | 
| 19 29 |  | 
| 20 30 | 
             
            module Crashbreak
         | 
| 21 31 | 
             
              extend Configurable
         | 
| @@ -29,4 +39,8 @@ module Crashbreak | |
| 29 39 | 
             
                  load 'tasks/crashbreak.rake'
         | 
| 30 40 | 
             
                end
         | 
| 31 41 | 
             
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def self.root
         | 
| 44 | 
            +
                File.expand_path '../..', __FILE__
         | 
| 45 | 
            +
              end
         | 
| 32 46 | 
             
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            module Crashbreak
         | 
| 2 | 
            +
              module AWS
         | 
| 3 | 
            +
                def client
         | 
| 4 | 
            +
                  @client ||= Aws::S3::Client.new
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def bucket_name
         | 
| 8 | 
            +
                  Crashbreak.configure.dumper_options[:aws_bucket_name]
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def aws_region
         | 
| 12 | 
            +
                  Crashbreak.configure.dumper_options[:aws_region] || ENV['AWS_REGION']
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def aws_key_id
         | 
| 16 | 
            +
                  Crashbreak.configure.dumper_options[:aws_access_key_id] || ENV['AWS_ACCESS_KEY_ID']
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def aws_secret_key
         | 
| 20 | 
            +
                  Crashbreak.configure.dumper_options[:aws_secret_access_key] || ENV['AWS_SECRET_ACCESS_KEY']
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def prepare_aws
         | 
| 24 | 
            +
                  Aws.config.update(
         | 
| 25 | 
            +
                      credentials: Aws::Credentials.new(aws_key_id, aws_secret_key),
         | 
| 26 | 
            +
                      s3: { region: aws_region }
         | 
| 27 | 
            +
                  )
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -3,6 +3,15 @@ module Crashbreak | |
| 3 3 | 
             
                attr_accessor :api_key
         | 
| 4 4 | 
             
                attr_accessor :exception_notifier
         | 
| 5 5 | 
             
                attr_accessor :error_serializers
         | 
| 6 | 
            +
                attr_accessor :dumpers
         | 
| 7 | 
            +
                attr_accessor :dumper_options
         | 
| 8 | 
            +
                attr_accessor :restorer_options
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                attr_accessor :github_login
         | 
| 11 | 
            +
                attr_accessor :github_password
         | 
| 12 | 
            +
                attr_accessor :github_repo_name
         | 
| 13 | 
            +
                attr_accessor :github_spec_file_path
         | 
| 14 | 
            +
                attr_accessor :github_development_branch
         | 
| 6 15 |  | 
| 7 16 | 
             
                def exception_notifier
         | 
| 8 17 | 
             
                  @exception_notifier || ExceptionNotifier.new
         | 
| @@ -11,5 +20,25 @@ module Crashbreak | |
| 11 20 | 
             
                def error_serializers
         | 
| 12 21 | 
             
                  @error_serializers || []
         | 
| 13 22 | 
             
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def github_spec_file_path
         | 
| 25 | 
            +
                  @github_spec_file_path || 'spec/crashbreak_error_spec.rb'
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def github_development_branch
         | 
| 29 | 
            +
                  @github_development_branch || 'master'
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def dumpers
         | 
| 33 | 
            +
                  @dumpers || []
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def dumper_options
         | 
| 37 | 
            +
                  @dumper_options || {}
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def restorer_options
         | 
| 41 | 
            +
                  @restorer_options || {}
         | 
| 42 | 
            +
                end
         | 
| 14 43 | 
             
              end
         | 
| 15 44 | 
             
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module Crashbreak
         | 
| 2 | 
            +
              class DumpersDataRepository
         | 
| 3 | 
            +
                BASE_URL = 'http://crashbreak.herokuapp.com/api'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(error_id)
         | 
| 6 | 
            +
                  @error_id = error_id
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def dumpers_data
         | 
| 10 | 
            +
                  JSON.parse request_body
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                private
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def request_body
         | 
| 16 | 
            +
                  connection.get do |req|
         | 
| 17 | 
            +
                    req.url request_url
         | 
| 18 | 
            +
                    req.headers['Content-Type'] = 'application/json'
         | 
| 19 | 
            +
                  end.body
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def connection
         | 
| 23 | 
            +
                  Faraday.new(url: request_url)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def request_url
         | 
| 27 | 
            +
                  "#{BASE_URL}/projects/#{project_token}/errors/#{@error_id}/dumpers_data"
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def project_token
         | 
| 31 | 
            +
                  Crashbreak.configure.api_key
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -1,19 +1,29 @@ | |
| 1 1 | 
             
            module Crashbreak
         | 
| 2 2 | 
             
              class ExceptionNotifier
         | 
| 3 3 | 
             
                def notify
         | 
| 4 | 
            -
                  exceptions_repository.create serialize_exception
         | 
| 4 | 
            +
                  error_id = exceptions_repository.create serialize_exception
         | 
| 5 | 
            +
                  GithubIntegrationService.new(error_id).push_test if Crashbreak.configure.github_repo_name.present?
         | 
| 5 6 | 
             
                end
         | 
| 6 7 |  | 
| 7 8 | 
             
                private
         | 
| 8 9 |  | 
| 9 10 | 
             
                def serialize_exception
         | 
| 10 11 | 
             
                  {}.tap do |exception_hash|
         | 
| 11 | 
            -
                    serializers.each  | 
| 12 | 
            -
             | 
| 13 | 
            -
                    end
         | 
| 12 | 
            +
                    serializers.each { |serializer| exception_hash.deep_merge!(serializer.serialize) }
         | 
| 13 | 
            +
                    exception_hash[:dumpers_data] = dumpers_data
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 | 
             
                end
         | 
| 16 16 |  | 
| 17 | 
            +
                def dumpers_data
         | 
| 18 | 
            +
                  dumpers.map do |dumper|
         | 
| 19 | 
            +
                    [dumper.class.to_s, dumper.dump]
         | 
| 20 | 
            +
                  end.to_h
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def dumpers
         | 
| 24 | 
            +
                  Crashbreak.configure.dumpers
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 17 27 | 
             
                def serializers
         | 
| 18 28 | 
             
                  [BasicInformationFormatter.new] + Crashbreak.configure.error_serializers
         | 
| 19 29 | 
             
                end
         | 
| @@ -3,23 +3,43 @@ module Crashbreak | |
| 3 3 | 
             
                BASE_URL = 'http://crashbreak.herokuapp.com/api'
         | 
| 4 4 |  | 
| 5 5 | 
             
                def create(error_report_hash)
         | 
| 6 | 
            +
                  JSON.parse(post_request(error_report_hash).body)['id']
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def resolve(error_id)
         | 
| 10 | 
            +
                  resolve_request error_id
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                private
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def post_request(error_report_hash)
         | 
| 6 16 | 
             
                  connection.post do |req|
         | 
| 7 | 
            -
                    req.url  | 
| 17 | 
            +
                    req.url create_request_url
         | 
| 8 18 | 
             
                    req.body = error_report_hash.to_json
         | 
| 9 19 | 
             
                    req.headers['Content-Type'] = 'application/json'
         | 
| 10 20 | 
             
                  end
         | 
| 11 21 | 
             
                end
         | 
| 12 22 |  | 
| 13 | 
            -
                 | 
| 23 | 
            +
                def resolve_request(error_id)
         | 
| 24 | 
            +
                  connection.put do |req|
         | 
| 25 | 
            +
                    req.url resolve_request_url(error_id)
         | 
| 26 | 
            +
                    req.body = { error_report: { status: :resolved } }.to_json
         | 
| 27 | 
            +
                    req.headers['Content-Type'] = 'application/json'
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 14 30 |  | 
| 15 31 | 
             
                def connection
         | 
| 16 | 
            -
                  Faraday.new | 
| 32 | 
            +
                  Faraday.new
         | 
| 17 33 | 
             
                end
         | 
| 18 34 |  | 
| 19 | 
            -
                def  | 
| 35 | 
            +
                def create_request_url
         | 
| 20 36 | 
             
                  "#{BASE_URL}/projects/#{project_token}/errors"
         | 
| 21 37 | 
             
                end
         | 
| 22 38 |  | 
| 39 | 
            +
                def resolve_request_url(error_id)
         | 
| 40 | 
            +
                  "#{BASE_URL}/projects/#{project_token}/errors/#{error_id}"
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 23 43 | 
             
                def project_token
         | 
| 24 44 | 
             
                  Crashbreak.configure.api_key
         | 
| 25 45 | 
             
                end
         | 
| @@ -0,0 +1,65 @@ | |
| 1 | 
            +
            module Crashbreak
         | 
| 2 | 
            +
              class GithubIntegrationService
         | 
| 3 | 
            +
                def initialize(error_id)
         | 
| 4 | 
            +
                  @error_id = error_id
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def push_test
         | 
| 8 | 
            +
                  create_branch(branch_sha)
         | 
| 9 | 
            +
                  create_test_file
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def remove_test
         | 
| 13 | 
            +
                  client.delete_contents(repo_name, file_path, "Remove test for error #{@error_id}",
         | 
| 14 | 
            +
                                         test_file_sha, branch: "refs/#{error_branch_name}")
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def create_pull_request
         | 
| 18 | 
            +
                  client.create_pull_request(repo_name, development_branch_name, error_branch_name.gsub('heads/', ''), "Crashbreak - fix for error #{@error_id}", '')
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def branch_sha
         | 
| 24 | 
            +
                  @branch_sha ||= client.ref(repo_name, 'heads/master').object.sha
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def test_file_sha
         | 
| 28 | 
            +
                  @test_file_sha ||= client.contents(repo_name, path: file_path, ref: error_branch_name).sha
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def create_branch(sha)
         | 
| 32 | 
            +
                  client.create_ref repo_name, error_branch_name, sha
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def create_test_file
         | 
| 36 | 
            +
                  client.create_contents repo_name, file_path, "Add test file for error #{@error_id}",
         | 
| 37 | 
            +
                                         file_content, { branch: "refs/#{error_branch_name}" }
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def file_content
         | 
| 41 | 
            +
                  test_file_content = File.read("#{Crashbreak.root}/lib/generators/crashbreak/templates/test.rb")
         | 
| 42 | 
            +
                  test_file_content.gsub('<%= error_id %>', @error_id.to_s)
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def client
         | 
| 46 | 
            +
                  @client ||= Octokit::Client.new(login: Crashbreak.configure.github_login, password: Crashbreak.configure.github_password)
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def repo_name
         | 
| 50 | 
            +
                  Crashbreak.configure.github_repo_name
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def error_branch_name
         | 
| 54 | 
            +
                  "heads/crashbreak-error-#{@error_id}"
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def file_path
         | 
| 58 | 
            +
                  Crashbreak.configure.github_spec_file_path
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                def development_branch_name
         | 
| 62 | 
            +
                  Crashbreak.configure.github_development_branch
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            module Crashbreak
         | 
| 2 | 
            +
              class RequestParser
         | 
| 3 | 
            +
                def initialize(request_data)
         | 
| 4 | 
            +
                  @request = request_data
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def request_data
         | 
| 8 | 
            +
                  yield(request_method_sym, request_path, request_body, request_headers)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                private
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def request_method_sym
         | 
| 14 | 
            +
                  @request['REQUEST_METHOD'].underscore.to_sym
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def request_path
         | 
| 18 | 
            +
                  @request['PATH_INFO']
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def request_body
         | 
| 22 | 
            +
                  JSON.parse(request_hash_as_string.gsub('=>', ':')).symbolize_keys
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def request_hash_as_string
         | 
| 26 | 
            +
                  @request['action_dispatch.request.request_parameters'] || '{}'
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def request_headers
         | 
| 30 | 
            +
                  @request.select{|key| key.start_with?('HTTP_')}.map{|key, value| [key.gsub('HTTP_', ''), value]}.to_h
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
    
        data/lib/crashbreak/version.rb
    CHANGED
    
    
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            module Crashbreak
         | 
| 2 | 
            +
              class DatabaseDumper
         | 
| 3 | 
            +
                include Crashbreak::AWS
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def dump
         | 
| 6 | 
            +
                  dump_database
         | 
| 7 | 
            +
                  prepare_aws
         | 
| 8 | 
            +
                  upload_dump
         | 
| 9 | 
            +
                  remove_locally_dump
         | 
| 10 | 
            +
                  { file_name: aws_file_name }
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                private
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def dump_database
         | 
| 16 | 
            +
                  system(dump_command)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def upload_dump
         | 
| 20 | 
            +
                  client.put_object(bucket: bucket_name, key: aws_file_name, body: File.read(dump_location))
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def remove_locally_dump
         | 
| 24 | 
            +
                  File.delete(dump_location)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def aws_file_name
         | 
| 28 | 
            +
                  @aws_file_name ||= "Crashbreak - database dump #{DateTime.now.utc}"
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def dump_location
         | 
| 32 | 
            +
                  Crashbreak.configure.dumper_options[:dump_location]
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def dump_command
         | 
| 36 | 
            +
                  Crashbreak.configure.dumper_options[:dump_command]
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            describe 'error id: <%= error_id %>', type: :request do
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              let(:restorers_data) { StateRestorer.new('<%= error_id %>').restore }
         | 
| 4 | 
            +
              let(:request_parser) { Crashbreak::RequestParser.new restorers_data[:request] }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              it 'sends request' do
         | 
| 7 | 
            +
                request_parser.request_data do |request_method, url, body, headers|
         | 
| 8 | 
            +
                  method(request_method).call url, body, headers
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
            end
         | 
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            module Crashbreak
         | 
| 2 | 
            +
              module Generators
         | 
| 3 | 
            +
                class TestGenerator < Rails::Generators::Base
         | 
| 4 | 
            +
                  source_root File.expand_path('../templates', __FILE__)
         | 
| 5 | 
            +
                  argument :error_id, type: :string
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def create_test_file
         | 
| 8 | 
            +
                    template 'test.rb', 'spec/error_request_spec.rb'
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            module Crashbreak
         | 
| 2 | 
            +
              class DatabaseRestorer
         | 
| 3 | 
            +
                include AWS
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(dump_data)
         | 
| 6 | 
            +
                  @file_name = dump_data['file_name']
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def restore
         | 
| 10 | 
            +
                  system('dropdb crashbreak-test')
         | 
| 11 | 
            +
                  system('createdb -T template0 crashbreak-test')
         | 
| 12 | 
            +
                  prepare_aws
         | 
| 13 | 
            +
                  download_dump
         | 
| 14 | 
            +
                  restore_database
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                private
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def restore_database
         | 
| 20 | 
            +
                  system(restore_command)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def download_dump
         | 
| 24 | 
            +
                  File.open("#{Rails.root}/tmp/db.dump", 'wb') do |file|
         | 
| 25 | 
            +
                    client.get_object(bucket: bucket_name, key: @file_name) do |data|
         | 
| 26 | 
            +
                      file.write(data)
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def restore_command
         | 
| 32 | 
            +
                  Crashbreak.configure.restorer_options[:restore_command]
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            class StateRestorer
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def initialize(error_id)
         | 
| 4 | 
            +
                @error_id = error_id
         | 
| 5 | 
            +
              end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              def restore
         | 
| 8 | 
            +
                {}.tap do |restorers_hash|
         | 
| 9 | 
            +
                  restorers.each do |restorer|
         | 
| 10 | 
            +
                    restorers_hash[key_name(restorer)] = restorer.new(dumper_data(restorer)).restore
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              private
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def dumpers_data
         | 
| 18 | 
            +
                @dumpers_data ||= Crashbreak::DumpersDataRepository.new(@error_id).dumpers_data
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              def restorers
         | 
| 22 | 
            +
                dumpers_data.keys.map {|dumper_name| restorer_class_by_dumper_name(dumper_name)}
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              def restorer_class_by_dumper_name(dumper_name)
         | 
| 26 | 
            +
                dumper_name.gsub('Dumper', 'Restorer').constantize
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              def dumper_data(restorer)
         | 
| 30 | 
            +
                dumper_name = restorer.to_s.gsub('Restorer', 'Dumper')
         | 
| 31 | 
            +
                dumpers_data[dumper_name]
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def key_name(restorer)
         | 
| 35 | 
            +
                restorer.to_s.gsub('Restorer', '').underscore.to_sym
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
    
        data/lib/tasks/crashbreak.rake
    CHANGED
    
    | @@ -10,6 +10,20 @@ namespace :crashbreak do | |
| 10 10 |  | 
| 11 11 | 
             
                puts 'Done, now check if error exists on crashbreak.com!'
         | 
| 12 12 | 
             
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              task resolve_error: :environment do
         | 
| 15 | 
            +
                return puts 'error_id must be set (e.g rake crashbreak:resolve_error error_id=123)' if ENV['error_id'].nil?
         | 
| 16 | 
            +
                service = Crashbreak::GithubIntegrationService.new ENV['error_id']
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                puts 'Removing test file from github...'
         | 
| 19 | 
            +
                service.remove_test
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                puts 'Creating pull request'
         | 
| 22 | 
            +
                service.create_pull_request
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                puts 'Resolving error in CrashBreak...'
         | 
| 25 | 
            +
                Crashbreak::ExceptionsRepository.new.resolve ENV['error_id']
         | 
| 26 | 
            +
              end
         | 
| 13 27 | 
             
            end
         | 
| 14 28 |  | 
| 15 29 | 
             
            class CrashbreakTestError < StandardError
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            describe RequestDumper do
         | 
| 2 | 
            +
              subject { described_class.new }
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              let(:example_request) { double(:request, env: Hash['REQUEST_URI' => 'example_uri']) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              before(:each) do
         | 
| 7 | 
            +
                RequestStore.store[:request] = example_request
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it 'returns a request hash' do
         | 
| 11 | 
            +
                expect(subject.dump).to eq example_request.env
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            end
         | 
| @@ -12,15 +12,16 @@ describe 'Sending error report to server' do | |
| 12 12 | 
             
              before(:each) do
         | 
| 13 13 | 
             
                Crashbreak.configure.api_key = project_token
         | 
| 14 14 | 
             
                Crashbreak.configure.error_serializers = [summary_formatter, Crashbreak::EnvironmentVariablesFormatter.new, TestErrorFormatter.new]
         | 
| 15 | 
            +
                Crashbreak.configure.dumpers = [RequestDumper.new]
         | 
| 15 16 |  | 
| 16 17 | 
             
                allow(crashing_app).to receive(:call).and_raise(example_error)
         | 
| 17 18 | 
             
                allow(example_error).to receive(:backtrace).and_return(%w(example backtrace))
         | 
| 18 | 
            -
                 | 
| 19 | 
            +
                allow_any_instance_of(Crashbreak::BasicFormatter).to receive(:request).and_return(example_request)
         | 
| 19 20 | 
             
              end
         | 
| 20 21 |  | 
| 21 22 | 
             
              let!(:create_exception_request) do
         | 
| 22 23 | 
             
                stub_request(:post, "#{Crashbreak::ExceptionsRepository::BASE_URL}/projects/#{project_token}/errors").
         | 
| 23 | 
            -
                    with(body: error_report_hash.to_json).to_return(status: 200)
         | 
| 24 | 
            +
                    with(body: error_report_hash.to_json).to_return(status: 200, body: { id: 1 }.to_json)
         | 
| 24 25 | 
             
              end
         | 
| 25 26 |  | 
| 26 27 | 
             
              let(:error_report_hash) do
         | 
| @@ -28,7 +29,8 @@ describe 'Sending error report to server' do | |
| 28 29 | 
             
                    name: example_error.to_s, message: example_error.message, backtrace: example_error.backtrace, environment: 'test',
         | 
| 29 30 | 
             
                    summary: { action: example_request.env['PATH_INFO'], controller_name: example_controller.class.to_s,
         | 
| 30 31 | 
             
                               file: example_error.backtrace[0], url: example_request.env['REQUEST_URI'], user_agent: example_request.env['HTTP_USER_AGENT'] },
         | 
| 31 | 
            -
                    additional_data: { environment: ENV.to_hash, test: { formatter: true } }
         | 
| 32 | 
            +
                    additional_data: { environment: ENV.to_hash, test: { formatter: true } },
         | 
| 33 | 
            +
                    dumpers_data: { 'RequestDumper' => example_request.env }
         | 
| 32 34 | 
             
                }
         | 
| 33 35 | 
             
              end
         | 
| 34 36 |  | 
| @@ -36,4 +38,4 @@ describe 'Sending error report to server' do | |
| 36 38 | 
             
                expect{ catching_middleware.call(env) }.to raise_error(TestError)
         | 
| 37 39 | 
             
                expect(create_exception_request).to have_been_made
         | 
| 38 40 | 
             
              end
         | 
| 39 | 
            -
            end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            describe Crashbreak::DumpersDataRepository do
         | 
| 2 | 
            +
              subject { described_class.new error_id }
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              let(:error_id) { 1 }
         | 
| 5 | 
            +
              let(:project_token) { 'example_project_token' }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              before(:each) do
         | 
| 8 | 
            +
                Crashbreak.configure.api_key = project_token
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                stub_request(:get, "#{described_class::BASE_URL}/projects/#{project_token}/errors/#{error_id}/dumpers_data").
         | 
| 11 | 
            +
                    to_return(status: 200, body: dumpers_data.to_json)
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              let(:dumpers_data) { Hash['example_dumpers_data' => 'example'] }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              it 'sends request to create exception report' do
         | 
| 17 | 
            +
                expect(subject.dumpers_data).to eq dumpers_data
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -6,19 +6,53 @@ describe Crashbreak::ExceptionNotifier do | |
| 6 6 |  | 
| 7 7 | 
             
              before(:each) do
         | 
| 8 8 | 
             
                allow(error).to receive(:backtrace).and_return(%w(example backtrace))
         | 
| 9 | 
            +
                allow_any_instance_of(Crashbreak::Configurator).to receive(:error_serializers).and_return([])
         | 
| 10 | 
            +
                allow_any_instance_of(described_class).to receive(:dumpers).and_return([])
         | 
| 11 | 
            +
                allow_any_instance_of(Crashbreak::GithubIntegrationService).to receive(:push_test).and_return(true)
         | 
| 12 | 
            +
             | 
| 9 13 | 
             
                RequestStore[:exception] = error
         | 
| 14 | 
            +
                RequestStore[:request] = double(:request, env: { request: :example_request_data } )
         | 
| 10 15 | 
             
              end
         | 
| 11 16 |  | 
| 12 17 | 
             
              let(:exception_basic_hash) do
         | 
| 13 | 
            -
                { name: error_name, message: error_message, backtrace: error.backtrace, environment: ENV['RACK_ENV'] }
         | 
| 18 | 
            +
                { name: error_name, message: error_message, backtrace: error.backtrace, environment: ENV['RACK_ENV'], dumpers_data: {} }
         | 
| 14 19 | 
             
              end
         | 
| 15 20 |  | 
| 16 21 | 
             
              context 'without additional serializers' do
         | 
| 17 | 
            -
                before(:each) { allow_any_instance_of(Crashbreak::Configurator).to receive(:error_serializers).and_return([]) }
         | 
| 18 22 | 
             
                it 'sends pure error' do
         | 
| 19 23 | 
             
                  expect_any_instance_of(Crashbreak::ExceptionsRepository).to receive(:create).with(exception_basic_hash)
         | 
| 20 24 | 
             
                  subject.notify
         | 
| 21 25 | 
             
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                context 'with dumpers' do
         | 
| 28 | 
            +
                  let(:expected_hash) { exception_basic_hash.merge(dumpers_hash) }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  let(:dumpers_hash) do
         | 
| 31 | 
            +
                    { dumpers_data: { 'RequestDumper' => { request: 'example_request_data' } } }
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  before(:each) do
         | 
| 35 | 
            +
                    allow_any_instance_of(described_class).to receive(:dumpers).and_return([RequestDumper.new])
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  it 'sends dump data' do
         | 
| 39 | 
            +
                    expect_any_instance_of(Crashbreak::ExceptionsRepository).to receive(:create).with(expected_hash)
         | 
| 40 | 
            +
                    subject.notify
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                context 'github integration' do
         | 
| 45 | 
            +
                  let(:error_id) { 1 }
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  it 'passes error id from request to github integration service' do
         | 
| 48 | 
            +
                    Crashbreak.configure.github_repo_name = 'user/repo'
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    allow_any_instance_of(Crashbreak::ExceptionsRepository).to receive(:create).and_return(error_id)
         | 
| 51 | 
            +
                    expect_any_instance_of(Crashbreak::GithubIntegrationService).to receive(:initialize).with(error_id)
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    subject.notify
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 22 56 | 
             
              end
         | 
| 23 57 |  | 
| 24 58 | 
             
              context 'with additional serializers' do
         | 
| @@ -2,6 +2,7 @@ describe Crashbreak::ExceptionsRepository do | |
| 2 2 | 
             
              subject { described_class.new }
         | 
| 3 3 |  | 
| 4 4 | 
             
              let(:project_token) { 'example_project_token' }
         | 
| 5 | 
            +
              let(:exception_id) { 1 }
         | 
| 5 6 |  | 
| 6 7 | 
             
              before(:each) do
         | 
| 7 8 | 
             
                Crashbreak.configure.api_key = project_token
         | 
| @@ -16,11 +17,20 @@ describe Crashbreak::ExceptionsRepository do | |
| 16 17 |  | 
| 17 18 | 
             
              let!(:create_exception_request) do
         | 
| 18 19 | 
             
                stub_request(:post, "#{described_class::BASE_URL}/projects/#{project_token}/errors").
         | 
| 19 | 
            -
                    with(body: error_report_hash.to_json).to_return(status: 200)
         | 
| 20 | 
            +
                    with(body: error_report_hash.to_json).to_return(status: 200, body: { id: exception_id }.to_json)
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              let!(:resolve_exception_request) do
         | 
| 24 | 
            +
                stub_request(:put, "#{described_class::BASE_URL}/projects/#{project_token}/errors/#{exception_id}").
         | 
| 25 | 
            +
                    with(body: { error_report: { status: :resolved } }.to_json)
         | 
| 20 26 | 
             
              end
         | 
| 21 27 |  | 
| 22 28 | 
             
              it 'sends request to create exception report' do
         | 
| 23 | 
            -
                subject.create error_report_hash
         | 
| 29 | 
            +
                expect(subject.create error_report_hash).to eq exception_id
         | 
| 24 30 | 
             
                expect(create_exception_request).to have_been_made
         | 
| 25 31 | 
             
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              it 'resolves error' do
         | 
| 34 | 
            +
                subject.resolve exception_id
         | 
| 35 | 
            +
              end
         | 
| 26 36 | 
             
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            require 'generator_spec'
         | 
| 2 | 
            +
            require_relative '../../../lib/generators/crashbreak/test_generator'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Crashbreak::Generators::TestGenerator do
         | 
| 5 | 
            +
              destination File.expand_path('../../../../tmp', __FILE__)
         | 
| 6 | 
            +
              arguments %w(example_error_id)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              before(:all) do
         | 
| 9 | 
            +
                prepare_destination
         | 
| 10 | 
            +
                run_generator
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it 'creates a test' do
         | 
| 14 | 
            +
                assert_file 'spec/error_request_spec.rb', /example_error_id/
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            describe Crashbreak::GithubIntegrationService do
         | 
| 2 | 
            +
              subject { described_class.new error_id }
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              let(:error_id) { 1 }
         | 
| 5 | 
            +
              let(:branch_name) { 'refs/heads/crashbreak-error-1' }
         | 
| 6 | 
            +
              let(:git_sha) { 'example_sha' }
         | 
| 7 | 
            +
              let(:file_content) { 'example_file_content' }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              let(:github_refs_url) { 'https://api.github.com/repos/user/repo/git/refs' }
         | 
| 10 | 
            +
              let(:github_master_ref_url) { "#{github_refs_url}/heads/master" }
         | 
| 11 | 
            +
              let(:github_create_content_url) { 'https://api.github.com/repos/user/repo/contents' }
         | 
| 12 | 
            +
              let(:github_test_file_url) { 'https://api.github.com/repos/user/repo/contents/spec/crashbreak_error_spec.rb' }
         | 
| 13 | 
            +
              let(:github_pull_requests_url) { 'https://api.github.com/repos/user/repo/pulls' }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              before(:each) do
         | 
| 16 | 
            +
                Crashbreak.configure.github_spec_file_path = 'spec/crashbreak_error_spec.rb'
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              it 'pushes test to github' do
         | 
| 20 | 
            +
                stub_request(:get, github_master_ref_url).to_return(body: DeepStruct.wrap(object: { sha: git_sha } ))
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                stub_request(:post, github_refs_url).with(body: { ref: 'refs/heads/crashbreak-error-1', sha: git_sha}.to_json)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                stub_request(:put, "#{github_create_content_url}/#{Crashbreak.configure.github_spec_file_path}").
         | 
| 25 | 
            +
                    with(body: { branch: branch_name, content: Base64.strict_encode64(file_content), message: 'Add test file for error 1' }.to_json)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                allow(subject).to receive(:file_content).and_return(file_content)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                subject.push_test
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              it 'removes test from github' do
         | 
| 33 | 
            +
                stub_request(:get, "#{github_test_file_url}?ref=heads/crashbreak-error-1").to_return(body: DeepStruct.wrap(sha: git_sha))
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                stub_request(:delete, github_test_file_url).
         | 
| 36 | 
            +
                    with(body: { branch: 'refs/heads/crashbreak-error-1', message: 'Remove test for error 1', sha: git_sha }.to_json)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                subject.remove_test
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              it 'creates pull request' do
         | 
| 42 | 
            +
                stub_request(:post, github_pull_requests_url).
         | 
| 43 | 
            +
                    with(body: { base: 'master', head: 'crashbreak-error-1', title: 'Crashbreak - fix for error 1', body: '' }.to_json)
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                subject.create_pull_request
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            describe Crashbreak::RequestParser do
         | 
| 2 | 
            +
              subject { described_class.new request_data }
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              context 'simple get without headers' do
         | 
| 5 | 
            +
                let(:request_data) { Hash['REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/projects' ]}
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                it 'yields with request data' do
         | 
| 8 | 
            +
                  expect{|y| subject.request_data(&y) }.to yield_with_args(:get, '/projects', {}, {})
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              context 'get with headers' do
         | 
| 13 | 
            +
                let(:request_data) { Hash['REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/projects',
         | 
| 14 | 
            +
                                          'HTTP_ACCEPT' => 'text/html', 'HTTP_CACHE_CONTROL' => 'max-age=0']}
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                it 'yields with request data' do
         | 
| 17 | 
            +
                  expect{|y| subject.request_data(&y) }.to yield_with_args(:get, '/projects', {}, { 'ACCEPT' => 'text/html', 'CACHE_CONTROL' => 'max-age=0' })
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              context 'post with body' do
         | 
| 22 | 
            +
                let(:request_data) { Hash['REQUEST_METHOD' => 'POST', 'PATH_INFO' => '/projects',
         | 
| 23 | 
            +
                                          'HTTP_ACCEPT' => 'text/html', 'HTTP_CACHE_CONTROL' => 'max-age=0',
         | 
| 24 | 
            +
                                          'action_dispatch.request.request_parameters' => request_parameters.to_json
         | 
| 25 | 
            +
                ]}
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                let(:request_parameters) { Hash[test_parameter: 'test_value', second_test_parameter: 'second_test_value'] }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                it 'yields with request data' do
         | 
| 30 | 
            +
                  expect{|y| subject.request_data(&y) }.to yield_with_args(:post, '/projects', request_parameters, { 'ACCEPT' => 'text/html', 'CACHE_CONTROL' => 'max-age=0' })
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            describe StateRestorer do
         | 
| 2 | 
            +
              subject { described_class.new error_id }
         | 
| 3 | 
            +
              let(:error_id) { 1 }
         | 
| 4 | 
            +
              let(:project_token) { 'example_project_token'}
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              before(:each) do
         | 
| 7 | 
            +
                Crashbreak.configure.api_key = project_token
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                stub_request(:get, "#{Crashbreak::DumpersDataRepository::BASE_URL}/projects/#{project_token}/errors/#{error_id}/dumpers_data").
         | 
| 10 | 
            +
                    to_return(status: 200, body: dumpers_data.to_json)
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              let(:dumpers_data) { Hash['TestDumper' => 'test_data'] }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              it 'returns a hash with all restorers data' do
         | 
| 16 | 
            +
                expect_any_instance_of(TestRestorer).to receive(:initialize).with('test_data')
         | 
| 17 | 
            +
                expect(subject.restore).to eq(test: 'restored_test_data')
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            class TestRestorer
         | 
| 22 | 
            +
              def initialize(data)
         | 
| 23 | 
            +
                @data = data
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def restore
         | 
| 27 | 
            +
                'restored_test_data'
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: crashbreak
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0 | 
| 4 | 
            +
              version: 0.9.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Michal Janeczek
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2015- | 
| 11 | 
            +
            date: 2015-04-07 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -94,6 +94,20 @@ dependencies: | |
| 94 94 | 
             
                - - ">="
         | 
| 95 95 | 
             
                  - !ruby/object:Gem::Version
         | 
| 96 96 | 
             
                    version: '0'
         | 
| 97 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 98 | 
            +
              name: deepstruct
         | 
| 99 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 | 
            +
                requirements:
         | 
| 101 | 
            +
                - - ">="
         | 
| 102 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            +
                    version: '0'
         | 
| 104 | 
            +
              type: :development
         | 
| 105 | 
            +
              prerelease: false
         | 
| 106 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 | 
            +
                requirements:
         | 
| 108 | 
            +
                - - ">="
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            +
                    version: '0'
         | 
| 97 111 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 98 112 | 
             
              name: faraday
         | 
| 99 113 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -122,6 +136,34 @@ dependencies: | |
| 122 136 | 
             
                - - ">="
         | 
| 123 137 | 
             
                  - !ruby/object:Gem::Version
         | 
| 124 138 | 
             
                    version: '0'
         | 
| 139 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 140 | 
            +
              name: octokit
         | 
| 141 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 142 | 
            +
                requirements:
         | 
| 143 | 
            +
                - - ">="
         | 
| 144 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 145 | 
            +
                    version: '0'
         | 
| 146 | 
            +
              type: :runtime
         | 
| 147 | 
            +
              prerelease: false
         | 
| 148 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 149 | 
            +
                requirements:
         | 
| 150 | 
            +
                - - ">="
         | 
| 151 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 152 | 
            +
                    version: '0'
         | 
| 153 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 154 | 
            +
              name: aws-sdk
         | 
| 155 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 156 | 
            +
                requirements:
         | 
| 157 | 
            +
                - - "~>"
         | 
| 158 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 159 | 
            +
                    version: '2'
         | 
| 160 | 
            +
              type: :runtime
         | 
| 161 | 
            +
              prerelease: false
         | 
| 162 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 163 | 
            +
                requirements:
         | 
| 164 | 
            +
                - - "~>"
         | 
| 165 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 166 | 
            +
                    version: '2'
         | 
| 125 167 | 
             
            description: Maybe later... :)
         | 
| 126 168 | 
             
            email:
         | 
| 127 169 | 
             
            - michal.janeczek@ymail.com
         | 
| @@ -138,8 +180,10 @@ files: | |
| 138 180 | 
             
            - Rakefile
         | 
| 139 181 | 
             
            - crashbreak.gemspec
         | 
| 140 182 | 
             
            - lib/crashbreak.rb
         | 
| 183 | 
            +
            - lib/crashbreak/AWS.rb
         | 
| 141 184 | 
             
            - lib/crashbreak/config/configurable.rb
         | 
| 142 185 | 
             
            - lib/crashbreak/config/configurator.rb
         | 
| 186 | 
            +
            - lib/crashbreak/dumpers_data_repository.rb
         | 
| 143 187 | 
             
            - lib/crashbreak/exception_catcher_middleware.rb
         | 
| 144 188 | 
             
            - lib/crashbreak/exception_notifier.rb
         | 
| 145 189 | 
             
            - lib/crashbreak/exceptions_repository.rb
         | 
| @@ -149,16 +193,24 @@ files: | |
| 149 193 | 
             
            - lib/crashbreak/formatters/environment_variables_formatter.rb
         | 
| 150 194 | 
             
            - lib/crashbreak/formatters/hash_formatter.rb
         | 
| 151 195 | 
             
            - lib/crashbreak/formatters/summary_formatter.rb
         | 
| 196 | 
            +
            - lib/crashbreak/github_integration_service.rb
         | 
| 197 | 
            +
            - lib/crashbreak/request_parser.rb
         | 
| 152 198 | 
             
            - lib/crashbreak/version.rb
         | 
| 153 | 
            -
            - lib/dumpers/ | 
| 199 | 
            +
            - lib/dumpers/database_dumper.rb
         | 
| 200 | 
            +
            - lib/dumpers/request_dumper.rb
         | 
| 154 201 | 
             
            - lib/generators/crashbreak/install_generator.rb
         | 
| 155 202 | 
             
            - lib/generators/crashbreak/templates/crashbreak.rb
         | 
| 156 | 
            -
            - lib/ | 
| 203 | 
            +
            - lib/generators/crashbreak/templates/test.rb
         | 
| 204 | 
            +
            - lib/generators/crashbreak/test_generator.rb
         | 
| 205 | 
            +
            - lib/restorers/database_restorer.rb
         | 
| 206 | 
            +
            - lib/restorers/request_restorer.rb
         | 
| 207 | 
            +
            - lib/restorers/state_restorer.rb
         | 
| 157 208 | 
             
            - lib/tasks/crashbreak.rake
         | 
| 158 | 
            -
            - spec/dumpers/ | 
| 209 | 
            +
            - spec/dumpers/request_dumper_spec.rb
         | 
| 159 210 | 
             
            - spec/features/sending_error_report_spec.rb
         | 
| 160 211 | 
             
            - spec/lib/config/configurable_spec.rb
         | 
| 161 212 | 
             
            - spec/lib/config/configurator_spec.rb
         | 
| 213 | 
            +
            - spec/lib/dumpers_data_repository_spec.rb
         | 
| 162 214 | 
             
            - spec/lib/exception_catcher_middleware_spec.rb
         | 
| 163 215 | 
             
            - spec/lib/exception_notifier_spec.rb
         | 
| 164 216 | 
             
            - spec/lib/exceptions_repository_spec.rb
         | 
| @@ -167,7 +219,10 @@ files: | |
| 167 219 | 
             
            - spec/lib/formatters/group_formatter_spec.rb
         | 
| 168 220 | 
             
            - spec/lib/formatters/summary_formatter_spec.rb
         | 
| 169 221 | 
             
            - spec/lib/generators/install_generator_spec.rb
         | 
| 170 | 
            -
            - spec/ | 
| 222 | 
            +
            - spec/lib/generators/test_generator_spec.rb
         | 
| 223 | 
            +
            - spec/lib/github_integration_service_spec.rb
         | 
| 224 | 
            +
            - spec/lib/request_sender_spec.rb
         | 
| 225 | 
            +
            - spec/restorers/state_restorer_spec.rb
         | 
| 171 226 | 
             
            - spec/spec_helper.rb
         | 
| 172 227 | 
             
            - spec/support/rspec_config.rb
         | 
| 173 228 | 
             
            - spec/support/test_error.rb
         | 
| @@ -197,10 +252,11 @@ signing_key: | |
| 197 252 | 
             
            specification_version: 4
         | 
| 198 253 | 
             
            summary: Take a break from crashes!
         | 
| 199 254 | 
             
            test_files:
         | 
| 200 | 
            -
            - spec/dumpers/ | 
| 255 | 
            +
            - spec/dumpers/request_dumper_spec.rb
         | 
| 201 256 | 
             
            - spec/features/sending_error_report_spec.rb
         | 
| 202 257 | 
             
            - spec/lib/config/configurable_spec.rb
         | 
| 203 258 | 
             
            - spec/lib/config/configurator_spec.rb
         | 
| 259 | 
            +
            - spec/lib/dumpers_data_repository_spec.rb
         | 
| 204 260 | 
             
            - spec/lib/exception_catcher_middleware_spec.rb
         | 
| 205 261 | 
             
            - spec/lib/exception_notifier_spec.rb
         | 
| 206 262 | 
             
            - spec/lib/exceptions_repository_spec.rb
         | 
| @@ -209,7 +265,10 @@ test_files: | |
| 209 265 | 
             
            - spec/lib/formatters/group_formatter_spec.rb
         | 
| 210 266 | 
             
            - spec/lib/formatters/summary_formatter_spec.rb
         | 
| 211 267 | 
             
            - spec/lib/generators/install_generator_spec.rb
         | 
| 212 | 
            -
            - spec/ | 
| 268 | 
            +
            - spec/lib/generators/test_generator_spec.rb
         | 
| 269 | 
            +
            - spec/lib/github_integration_service_spec.rb
         | 
| 270 | 
            +
            - spec/lib/request_sender_spec.rb
         | 
| 271 | 
            +
            - spec/restorers/state_restorer_spec.rb
         | 
| 213 272 | 
             
            - spec/spec_helper.rb
         | 
| 214 273 | 
             
            - spec/support/rspec_config.rb
         | 
| 215 274 | 
             
            - spec/support/test_error.rb
         | 
| @@ -1,12 +0,0 @@ | |
| 1 | 
            -
            describe Crashbreak::ProgramNameDumper do
         | 
| 2 | 
            -
              subject { described_class.new }
         | 
| 3 | 
            -
              let(:file_path) { subject.dump.path }
         | 
| 4 | 
            -
             | 
| 5 | 
            -
              it 'file name should be relevant to class' do
         | 
| 6 | 
            -
                expect(File.basename(file_path)).to eq 'program_name.dump'
         | 
| 7 | 
            -
              end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
              it 'checks file content' do
         | 
| 10 | 
            -
                expect(File.read(file_path)).to match $PROGRAM_NAME
         | 
| 11 | 
            -
              end
         | 
| 12 | 
            -
            end
         | 
| @@ -1,11 +0,0 @@ | |
| 1 | 
            -
            describe Crashbreak::ProgramNameRestorer do
         | 
| 2 | 
            -
              subject { described_class.new }
         | 
| 3 | 
            -
              let(:program_name) { 'crashbreak' }
         | 
| 4 | 
            -
             | 
| 5 | 
            -
              before(:each) { allow(File).to receive(:readlines).and_return([program_name]) }
         | 
| 6 | 
            -
             | 
| 7 | 
            -
              it 'restore global variable $PROGRAM_NAME from file' do
         | 
| 8 | 
            -
                subject.restore
         | 
| 9 | 
            -
                expect($PROGRAM_NAME).to eq program_name
         | 
| 10 | 
            -
              end
         | 
| 11 | 
            -
            end
         |