From e3cef9c8f9050c0c21bcd3d000f6a6e1ef2f3818 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Wed, 31 Mar 2021 18:43:28 +0300 Subject: [PATCH 01/21] Merge pull request #9 from rubyroidlabs/add_hound Set up github actions --- .github/workflows/reviews.yml | 24 ++++++++++++++++++++++++ .gitmodules | 6 ++++++ 2 files changed, 30 insertions(+) create mode 100644 .github/workflows/reviews.yml create mode 100644 .gitmodules diff --git a/.github/workflows/reviews.yml b/.github/workflows/reviews.yml new file mode 100644 index 00000000..5f58aff6 --- /dev/null +++ b/.github/workflows/reviews.yml @@ -0,0 +1,24 @@ +name: Code review +on: +- push +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: 'true' + fetch-depth: 0 + - run: | + git fetch --no-tags --prune origin + - uses: borales/actions-yarn@v2.0.0 + with: + cmd: install + - uses: adwerx/pronto-ruby@v2.5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RUBOCOP_CONFIG: ./pronto/rubocop/rubocop.yml + YAMLLINT_OPTS: -c ./pronto/yamllint/yamllint.yml + with: + runners: >- + brakeman eslint_npm fasterer poper rails_best_practices rails_schema reek rubocop scss yamllint diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..78337ad0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "pronto/rubocop"] + path = pronto/rubocop + url = git@github.com:rubyroidlabs/rubocop.git +[submodule "pronto/yamllint"] + path = pronto/yamllint + url = git@github.com:rubyroidlabs/yamllint.git From ac2d1e144944996bf039a0b81e126219f9104f04 Mon Sep 17 00:00:00 2001 From: Valentine Zavadsky Date: Tue, 6 Apr 2021 16:06:20 +0300 Subject: [PATCH 02/21] Merge pull request #28 from rubyroidlabs/test_rubocop Test rubocop --- .github/workflows/reviews.yml | 11 +++-------- test-2.rb | 6 ++++++ test.rb | 8 ++++++++ 3 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 test-2.rb create mode 100644 test.rb diff --git a/.github/workflows/reviews.yml b/.github/workflows/reviews.yml index 5f58aff6..e9aa9fef 100644 --- a/.github/workflows/reviews.yml +++ b/.github/workflows/reviews.yml @@ -1,6 +1,5 @@ name: Code review -on: -- push +on: [push, pull_request] jobs: run: runs-on: ubuntu-latest @@ -11,14 +10,10 @@ jobs: fetch-depth: 0 - run: | git fetch --no-tags --prune origin - - uses: borales/actions-yarn@v2.0.0 - with: - cmd: install - - uses: adwerx/pronto-ruby@v2.5 + - uses: adwerx/pronto-ruby@v2.9 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} RUBOCOP_CONFIG: ./pronto/rubocop/rubocop.yml - YAMLLINT_OPTS: -c ./pronto/yamllint/yamllint.yml with: runners: >- - brakeman eslint_npm fasterer poper rails_best_practices rails_schema reek rubocop scss yamllint + brakeman rails_best_practices reek rubocop diff --git a/test-2.rb b/test-2.rb new file mode 100644 index 00000000..2dd83396 --- /dev/null +++ b/test-2.rb @@ -0,0 +1,6 @@ +a = b = 3 + +if a and b + puts "HEY" + a = a + 1 +end diff --git a/test.rb b/test.rb new file mode 100644 index 00000000..5933ffd9 --- /dev/null +++ b/test.rb @@ -0,0 +1,8 @@ +a = 1 +b = 2 +if a && b + a += 1 + b -= 1 +end + +puts 'a + b = ' + (a + b).to_s From 8520374419fe90c1059d0d790e792b0cf0dd4b4c Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Mon, 19 Apr 2021 12:16:07 +1000 Subject: [PATCH 03/21] Implement basic option parsing --- Pavel_Borisov/2/checker.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Pavel_Borisov/2/checker.rb diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb new file mode 100644 index 00000000..0bbd26ea --- /dev/null +++ b/Pavel_Borisov/2/checker.rb @@ -0,0 +1,18 @@ +require 'optparse' +# require 'csv' + +params = {} +OptionParser.new do |opts| + opts.banner = "Usage: #{__FILE__} [options] FILENAME" + opts.on('--no-subdomains', 'Exclude entries with subdomains', TrueClass) + opts.on('--filter=WORD', 'Filter out results containing WORD in page body', String) + opts.on('--exclude-solutions', 'Exclude common open-source solutions', TrueClass) +end.parse!(into: params) + +domain_list_filename = ARGV.first + +unless !domain_list_filename.nil? && File.exists?(domain_list_filename) + fail(ArgumentError, "Domain list filename incorrect or not provided") +end + + From b1473a897e97f29905477fe2579a6a0c3cd4c110 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 20 Apr 2021 12:53:09 +1000 Subject: [PATCH 04/21] Implement DomainsList and DomainChecker --- Pavel_Borisov/2/checker.rb | 67 +++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index 0bbd26ea..eebfc5a1 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -1,5 +1,8 @@ +# frozen_string_literal: true + require 'optparse' -# require 'csv' +require 'csv' +require 'net/http' params = {} OptionParser.new do |opts| @@ -15,4 +18,66 @@ fail(ArgumentError, "Domain list filename incorrect or not provided") end +class DomainsList + attr_reader :list + + def initialize(filename, params) + @list = CSV.read(filename).map(&:first) + + if params[:'no-subdomains'] + reject_subdomains! + end + + if params[:'exclude-solutions'] + reject_solutions! + end + end + + private + + def reject_subdomains! + @list.filter! { |domain| domain.count('.') == 1 } + end + + def reject_solutions! + @list.filter! do |domain| + !domain.match(/(\bgitlab\b|\bredmine\b|\bgit\b|\brepo\b|\brm\b|\bsource\b|\bsvn\b)/) + end + end +end + +class DomainChecker + attr_reader :domain, :code, :response_time, :body, :status + + def initialize(domain) + @uri = URI("https://#{domain}/") + @domain = domain + end + + def check! + begin + start_time = Time.now + response = Net::HTTP.get_response(@uri) + end_time = Time.now + @response_time = "#{((end_time - start_time) * 1000).round}ms" + @code = response.code + @body = response.body + @status = :success + rescue SocketError => e + @status = :failure + @error_message = "ERROR (#{e.cause})" + end + self + end + + def to_s + case @status + when :success + "#{@domain} - #{@code} (#{@response_time})" + when :failure + "#{domain} - #{error_message}" + end + end +end + From edb4e91dab570cda0566999ad2d69e5aafe64230 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 20 Apr 2021 14:54:07 +1000 Subject: [PATCH 05/21] Move class definitions to lib/machinery.rb --- Pavel_Borisov/2/checker.rb | 78 +++++---------------------- Pavel_Borisov/2/lib/machinery.rb | 92 ++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 66 deletions(-) create mode 100644 Pavel_Borisov/2/lib/machinery.rb diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index eebfc5a1..1f3d570d 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -1,83 +1,29 @@ # frozen_string_literal: true -require 'optparse' -require 'csv' -require 'net/http' +require_relative 'lib/machinery' +require 'pry' -params = {} -OptionParser.new do |opts| +command_line = Parser.new do |opts| opts.banner = "Usage: #{__FILE__} [options] FILENAME" + opts.separator '' + opts.separator 'Available options:' opts.on('--no-subdomains', 'Exclude entries with subdomains', TrueClass) opts.on('--filter=WORD', 'Filter out results containing WORD in page body', String) opts.on('--exclude-solutions', 'Exclude common open-source solutions', TrueClass) -end.parse!(into: params) - -domain_list_filename = ARGV.first - -unless !domain_list_filename.nil? && File.exists?(domain_list_filename) - fail(ArgumentError, "Domain list filename incorrect or not provided") end -class DomainsList - attr_reader :list - - def initialize(filename, params) - @list = CSV.read(filename).map(&:first) - - if params[:'no-subdomains'] - reject_subdomains! - end +command_line.parse! - if params[:'exclude-solutions'] - reject_solutions! - end - end +domain_list_filename = command_line.args.first - private +p command_line.options +p command_line.args - def reject_subdomains! - @list.filter! { |domain| domain.count('.') == 1 } - end - - def reject_solutions! - @list.filter! do |domain| - !domain.match(/(\bgitlab\b|\bredmine\b|\bgit\b|\brepo\b|\brm\b|\bsource\b|\bsvn\b)/) - end - end +unless !domain_list_filename.nil? && File.exists?(domain_list_filename) + print command_line.usage + exit end -class DomainChecker - attr_reader :domain, :code, :response_time, :body, :status - - def initialize(domain) - @uri = URI("https://#{domain}/") - @domain = domain - end - def check! - begin - start_time = Time.now - response = Net::HTTP.get_response(@uri) - end_time = Time.now - @response_time = "#{((end_time - start_time) * 1000).round}ms" - @code = response.code - @body = response.body - @status = :success - rescue SocketError => e - @status = :failure - @error_message = "ERROR (#{e.cause})" - end - self - end - - def to_s - case @status - when :success - "#{@domain} - #{@code} (#{@response_time})" - when :failure - "#{domain} - #{error_message}" - end - end -end diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb new file mode 100644 index 00000000..4be0ba9d --- /dev/null +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +require 'optparse' +require 'csv' +require 'net/http' + +class Parser + attr_reader :options, :args + + def initialize(&block) + @options = {} + @args = [] + @opt_parser = OptionParser.new(&block) + end + + def parse! + @opt_parser.parse!(into: @options) + @args = @opt_parser.instance_variable_get(:@default_argv) + end + + def to_s + @opt_parser.to_s + end + + def usage + to_s + end +end + + +class DomainsList + attr_reader :list + + def initialize(filename, params) + @list = CSV.read(filename).map(&:first) + + if params[:'no-subdomains'] + reject_subdomains! + end + + if params[:'exclude-solutions'] + reject_solutions! + end + end + + private + + def reject_subdomains! + @list.filter! { |domain| domain.count('.') == 1 } + end + + def reject_solutions! + @list.filter! do |domain| + !domain.match(/(\bgitlab\b|\bredmine\b|\bgit\b|\brepo\b|\brm\b|\bsource\b|\bsvn\b)/) + end + end +end + + +class DomainChecker + attr_reader :domain, :code, :response_time, :body, :status + + def initialize(domain) + @uri = URI("https://#{domain}/") + @domain = domain + end + + def check! + begin + start_time = Time.now + response = Net::HTTP.get_response(@uri) + end_time = Time.now + @response_time = "#{((end_time - start_time) * 1000).round}ms" + @code = response.code + @body = response.body + @status = :success + rescue SocketError => e + @status = :failure + @error_message = "ERROR (#{e.cause})" + end + self + end + + def to_s + case @status + when :success + "#{@domain} - #{@code} (#{@response_time})" + when :failure + "#{domain} - #{error_message}" + end + end +end From 15cd6f671619ffed6ffb44840d50b457a25b2e51 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Sat, 8 May 2021 16:12:29 +1000 Subject: [PATCH 06/21] Refactor classes --- Pavel_Borisov/2/checker.rb | 8 +++- Pavel_Borisov/2/lib/machinery.rb | 73 ++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index 1f3d570d..4e2b170a 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -3,7 +3,7 @@ require_relative 'lib/machinery' require 'pry' -command_line = Parser.new do |opts| +command_line = CliParser.new do |opts| opts.banner = "Usage: #{__FILE__} [options] FILENAME" opts.separator '' opts.separator 'Available options:' @@ -24,6 +24,12 @@ exit end +domains = DomainsList.new(domain_list_filename, command_line.options) +p domains.list +p "" + +domains.process! +p domains.list diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index 4be0ba9d..0f2e9eec 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -4,7 +4,7 @@ require 'csv' require 'net/http' -class Parser +class CliParser attr_reader :options, :args def initialize(&block) @@ -28,40 +28,11 @@ def usage end -class DomainsList - attr_reader :list - - def initialize(filename, params) - @list = CSV.read(filename).map(&:first) - - if params[:'no-subdomains'] - reject_subdomains! - end - - if params[:'exclude-solutions'] - reject_solutions! - end - end - - private - - def reject_subdomains! - @list.filter! { |domain| domain.count('.') == 1 } - end - - def reject_solutions! - @list.filter! do |domain| - !domain.match(/(\bgitlab\b|\bredmine\b|\bgit\b|\brepo\b|\brm\b|\bsource\b|\bsvn\b)/) - end - end -end - - class DomainChecker attr_reader :domain, :code, :response_time, :body, :status def initialize(domain) - @uri = URI("https://#{domain}/") + @uri = URI("http://#{domain}/") @domain = domain end @@ -86,7 +57,45 @@ def to_s when :success "#{@domain} - #{@code} (#{@response_time})" when :failure - "#{domain} - #{error_message}" + "#{@domain} - #{@error_message}" + end + end +end + + +class DomainsList + attr_reader :list + + def initialize(filename, options) + @initial_list = CSV.read(filename).map(&:first) + + if options[:'no-subdomains'] + reject_subdomains! + end + + if options[:'exclude-solutions'] + reject_solutions! + end + + @list = @initial_list.map { |domain| DomainChecker.new(domain) } + end + + def process! + @list.each { |item| item.check! } + end + + private + + def reject_subdomains! + @initial_list.filter! { |domain| domain.count('.') == 1 } + end + + def reject_solutions! + @initial_list.filter! do |domain| + !domain.match(/(\bgitlab\b|\bredmine\b|\bgit\b|\brepo\b|\brm\b|\bsource\b|\bsvn\b)/) end end end + + + From b7af79a0487ccaf9d08885fd4a3fabdfbb04e733 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Sat, 8 May 2021 18:33:20 +1000 Subject: [PATCH 07/21] Tweak HTTP request logic --- Pavel_Borisov/2/lib/machinery.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index 0f2e9eec..74a93485 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -32,22 +32,27 @@ class DomainChecker attr_reader :domain, :code, :response_time, :body, :status def initialize(domain) - @uri = URI("http://#{domain}/") @domain = domain end def check! begin + http = Net::HTTP.new(@domain) + http.read_timeout = 1 start_time = Time.now - response = Net::HTTP.get_response(@uri) + response = http.get('/') end_time = Time.now @response_time = "#{((end_time - start_time) * 1000).round}ms" @code = response.code @body = response.body @status = :success - rescue SocketError => e + rescue SocketError, Timeout::Error => e @status = :failure - @error_message = "ERROR (#{e.cause})" + cause = e.cause + if e.is_a? Timeout::Error + cause = 'Timeout' + end + @error_message = "ERROR (#{cause})" end self end From bb04d9e6f3b25f788da22295ff1943e555757f2d Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Sat, 8 May 2021 21:30:45 +1000 Subject: [PATCH 08/21] Implement basic functionality --- Pavel_Borisov/2/checker.rb | 14 +++-------- Pavel_Borisov/2/lib/machinery.rb | 42 ++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index 4e2b170a..88a41f64 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -16,20 +16,14 @@ domain_list_filename = command_line.args.first -p command_line.options -p command_line.args - -unless !domain_list_filename.nil? && File.exists?(domain_list_filename) +if domain_list_filename.nil? || !File.exists?(domain_list_filename) print command_line.usage exit end domains = DomainsList.new(domain_list_filename, command_line.options) -p domains.list -p "" domains.process! -p domains.list - - - +domains.results.each { |r| puts r } +puts "" +puts domains.stats diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index 74a93485..997d72bf 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -3,6 +3,7 @@ require 'optparse' require 'csv' require 'net/http' +require 'nokogiri' class CliParser attr_reader :options, :args @@ -43,11 +44,11 @@ def check! response = http.get('/') end_time = Time.now @response_time = "#{((end_time - start_time) * 1000).round}ms" - @code = response.code + @code = response.code.to_i @body = response.body - @status = :success + @status = :got_response rescue SocketError, Timeout::Error => e - @status = :failure + @status = :errored cause = e.cause if e.is_a? Timeout::Error cause = 'Timeout' @@ -59,9 +60,9 @@ def check! def to_s case @status - when :success + when :got_response "#{@domain} - #{@code} (#{@response_time})" - when :failure + when :errored "#{@domain} - #{@error_message}" end end @@ -82,13 +83,37 @@ def initialize(filename, options) reject_solutions! end + @filtered_word = options[:'filter'] @list = @initial_list.map { |domain| DomainChecker.new(domain) } end def process! @list.each { |item| item.check! } + if @filtered_word + reject_results_with_word!(@filtered_word) + end + end + + def results + @list.map(&:to_s) + end + + def stats + total = @list.count + errored = @list.count { |item| item.status == :errored } + + success = @list.count do |item| + item.status == :got_response && (200..399).include?(item.code) + end + + failed = @list.count do |item| + item.status == :got_response && (400..599).include?(item.code) + end + + "Total: #{total}, Success: #{success}, Failed: #{failed}, Errored: #{errored}" end + private def reject_subdomains! @@ -100,6 +125,13 @@ def reject_solutions! !domain.match(/(\bgitlab\b|\bredmine\b|\bgit\b|\brepo\b|\brm\b|\bsource\b|\bsvn\b)/) end end + + def reject_results_with_word!(word) + @list.reject! do |response| + body_text = Nokogiri::HTML.parse(response.body).css("body").text + body_text.downcase.match? word.downcase + end + end end From b3793d262afdbb1a08f7d3949af79869caf2b619 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 18:05:23 +1000 Subject: [PATCH 09/21] Fix linter warnings --- Pavel_Borisov/2/lib/machinery.rb | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index 997d72bf..4783e3fb 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -28,7 +28,6 @@ def usage end end - class DomainChecker attr_reader :domain, :code, :response_time, :body, :status @@ -49,10 +48,7 @@ def check! @status = :got_response rescue SocketError, Timeout::Error => e @status = :errored - cause = e.cause - if e.is_a? Timeout::Error - cause = 'Timeout' - end + cause = ('Timeout' if e.is_a? Timeout::Error) || e.cause @error_message = "ERROR (#{cause})" end self @@ -68,22 +64,16 @@ def to_s end end - class DomainsList attr_reader :list def initialize(filename, options) @initial_list = CSV.read(filename).map(&:first) - if options[:'no-subdomains'] - reject_subdomains! - end - - if options[:'exclude-solutions'] - reject_solutions! - end + reject_subdomains! if options[:'no-subdomains'] + reject_solutions! if options[:'exclude-solutions'] - @filtered_word = options[:'filter'] + @filtered_word = options[:filter] @list = @initial_list.map { |domain| DomainChecker.new(domain) } end @@ -103,21 +93,20 @@ def stats errored = @list.count { |item| item.status == :errored } success = @list.count do |item| - item.status == :got_response && (200..399).include?(item.code) + item.status == :got_response && (200..399).cover?(item.code) end failed = @list.count do |item| - item.status == :got_response && (400..599).include?(item.code) + item.status == :got_response && (400..599).cover?(item.code) end "Total: #{total}, Success: #{success}, Failed: #{failed}, Errored: #{errored}" end - private def reject_subdomains! - @initial_list.filter! { |domain| domain.count('.') == 1 } + @initial_list.filter! { |domain| domain.count('.') == 1 } end def reject_solutions! @@ -128,11 +117,8 @@ def reject_solutions! def reject_results_with_word!(word) @list.reject! do |response| - body_text = Nokogiri::HTML.parse(response.body).css("body").text + body_text = Nokogiri::HTML.parse(response.body).css('body').text body_text.downcase.match? word.downcase end end end - - - From a0e10693896a2adefb68696d37ff6997bfca1104 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 18:48:44 +1000 Subject: [PATCH 10/21] Add progress indicator --- Pavel_Borisov/2/checker.rb | 4 +++- Pavel_Borisov/2/lib/machinery.rb | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index 88a41f64..87233c6a 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -23,7 +23,9 @@ domains = DomainsList.new(domain_list_filename, command_line.options) -domains.process! +domains.process! do |percent, domain| + print "\e[1000D\e[0K#{percent}% complete – now checking #{domain}" +end domains.results.each { |r| puts r } puts "" puts domains.stats diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index 4783e3fb..e69eac5b 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -78,10 +78,16 @@ def initialize(filename, options) end def process! - @list.each { |item| item.check! } - if @filtered_word - reject_results_with_word!(@filtered_word) + total_count = @list.count + processed_count = 0 + @list.each do |item| + item.check! + processed_count += 1 + completion_percentage = (processed_count / total_count.to_f * 100).to_i + yield(completion_percentage, item.domain) if block_given? end + reject_results_with_word!(@filtered_word) if @filtered_word + self end def results From 393bd5ce0f46ebd3f51241db286fb4b9c055bc84 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 18:42:36 +1000 Subject: [PATCH 11/21] Tweak timeout and error handling --- Pavel_Borisov/2/lib/machinery.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index e69eac5b..c300c66c 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -38,6 +38,7 @@ def initialize(domain) def check! begin http = Net::HTTP.new(@domain) + http.open_timeout = 1 http.read_timeout = 1 start_time = Time.now response = http.get('/') @@ -46,7 +47,7 @@ def check! @code = response.code.to_i @body = response.body @status = :got_response - rescue SocketError, Timeout::Error => e + rescue StandardError => e @status = :errored cause = ('Timeout' if e.is_a? Timeout::Error) || e.cause @error_message = "ERROR (#{cause})" From 57a5d2824883703cc7365f6afe5a0f49fb415f84 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 18:45:02 +1000 Subject: [PATCH 12/21] Add :unchecked status --- Pavel_Borisov/2/lib/machinery.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index c300c66c..88d0890b 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -33,6 +33,7 @@ class DomainChecker def initialize(domain) @domain = domain + @status = :unchecked end def check! @@ -55,12 +56,14 @@ def check! self end - def to_s + def result case @status when :got_response "#{@domain} - #{@code} (#{@response_time})" when :errored "#{@domain} - #{@error_message}" + when :unchecked + "#{@domain} - hasn't been checked" end end end @@ -92,7 +95,7 @@ def process! end def results - @list.map(&:to_s) + @list.map(&:result) end def stats From ed963109f53c7cc8db87c268a3d351b2aa27d793 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 18:50:51 +1000 Subject: [PATCH 13/21] Add tests --- Pavel_Borisov/2/test/fixtures/domains.csv | 3 ++ Pavel_Borisov/2/test/machinery_test.rb | 57 +++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 Pavel_Borisov/2/test/fixtures/domains.csv create mode 100644 Pavel_Borisov/2/test/machinery_test.rb diff --git a/Pavel_Borisov/2/test/fixtures/domains.csv b/Pavel_Borisov/2/test/fixtures/domains.csv new file mode 100644 index 00000000..7ae5bf43 --- /dev/null +++ b/Pavel_Borisov/2/test/fixtures/domains.csv @@ -0,0 +1,3 @@ +example.com +subdomain.example.com +gitlab.com diff --git a/Pavel_Borisov/2/test/machinery_test.rb b/Pavel_Borisov/2/test/machinery_test.rb new file mode 100644 index 00000000..816dbbe6 --- /dev/null +++ b/Pavel_Borisov/2/test/machinery_test.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'minitest/autorun' +require_relative '../lib/machinery' + +class DomainCheckerTest < Minitest::Test + def test_initial_status_is_unchecked + assert_equal :unchecked, DomainChecker.new('example.com').status + end + + def test_unchecked_result_is_correct + assert_equal "example.com - hasn't been checked", + DomainChecker.new('example.com').result + end + + def test_valid_domain_checked_status_is_got_response + assert_equal :got_response, DomainChecker.new('example.com').check!.status + end + + def test_valid_domain_checked_result_is_correct + assert_match(/example.com - 200 \(\d+ms\)/, + DomainChecker.new('example.com').check!.result) + end + + def test_invalid_domain_checked_status_is_errored + assert_equal :errored, DomainChecker.new('example.com.invld').check!.status + end + + def test_invalid_domain_checked_result_is_correct + assert_match(/example.com.invld - ERROR/, + DomainChecker.new('example.com.invld').check!.result) + end +end + +class DomainsListTest < Minitest::Test + TEST_DOMAINS_FILE = "#{File.dirname(__FILE__)}/fixtures/domains.csv" + + def test_csv_file_is_read_correctly + assert_equal ['example.com', 'subdomain.example.com', 'gitlab.com'], + DomainsList.new(TEST_DOMAINS_FILE, {}).list.map(&:domain) + end + + def test_no_subdomains_option_rejects_subdomains + assert_equal ['example.com', 'gitlab.com'], + DomainsList.new(TEST_DOMAINS_FILE, { 'no-subdomains': true }).list.map(&:domain) + end + + def test_exclude_solutions_rejects_gitlab + assert_equal ['example.com', 'subdomain.example.com'], + DomainsList.new(TEST_DOMAINS_FILE, { 'exclude-solutions': true }).list.map(&:domain) + end + + def test_filter_word_rejects_results_with_word_in_body + assert_equal ['subdomain.example.com', 'gitlab.com'], + DomainsList.new(TEST_DOMAINS_FILE, { filter: 'example' }).process!.list.map(&:domain) + end +end From 8408670806a19b34259f090c0bf48731ec97986b Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 19:21:54 +1000 Subject: [PATCH 14/21] Fix linter warning --- Pavel_Borisov/2/checker.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index 87233c6a..bb6b52f5 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -16,7 +16,7 @@ domain_list_filename = command_line.args.first -if domain_list_filename.nil? || !File.exists?(domain_list_filename) +if domain_list_filename.nil? || !File.exist?(domain_list_filename) print command_line.usage exit end @@ -27,5 +27,5 @@ print "\e[1000D\e[0K#{percent}% complete – now checking #{domain}" end domains.results.each { |r| puts r } -puts "" +puts '' puts domains.stats From 47d1fbae3d8a3e359eccd7f131a3138a77a3e43f Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 19:23:45 +1000 Subject: [PATCH 15/21] Fix output formatting --- Pavel_Borisov/2/checker.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index bb6b52f5..089249c6 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -26,6 +26,7 @@ domains.process! do |percent, domain| print "\e[1000D\e[0K#{percent}% complete – now checking #{domain}" end +print "\e[1000D\e[0K" domains.results.each { |r| puts r } puts '' puts domains.stats From ffb0547193e4d53d29c21a5a3f2ac559e5df7406 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 20:12:22 +1000 Subject: [PATCH 16/21] Remove pry --- Pavel_Borisov/2/checker.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index 089249c6..77ccb0ae 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require_relative 'lib/machinery' -require 'pry' command_line = CliParser.new do |opts| opts.banner = "Usage: #{__FILE__} [options] FILENAME" From 1a704d3dd444ccbcfafe8696f9dba2a351a28cc9 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Tue, 11 May 2021 22:05:37 +1000 Subject: [PATCH 17/21] Add comments --- Pavel_Borisov/2/checker.rb | 1 + Pavel_Borisov/2/lib/machinery.rb | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Pavel_Borisov/2/checker.rb b/Pavel_Borisov/2/checker.rb index 77ccb0ae..fe8c5a6f 100644 --- a/Pavel_Borisov/2/checker.rb +++ b/Pavel_Borisov/2/checker.rb @@ -26,6 +26,7 @@ print "\e[1000D\e[0K#{percent}% complete – now checking #{domain}" end print "\e[1000D\e[0K" + domains.results.each { |r| puts r } puts '' puts domains.stats diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index 88d0890b..a978891b 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -5,6 +5,7 @@ require 'net/http' require 'nokogiri' +# Uses OptionParser to collect options into a hash class CliParser attr_reader :options, :args @@ -28,6 +29,7 @@ def usage end end +# Runs check for a single domain and contains the result class DomainChecker attr_reader :domain, :code, :response_time, :body, :status @@ -68,6 +70,9 @@ def result end end +# Reads domains list from a file, filters the list according to the supplied options. +# Checks the domains using DomainChecker, filters the results if --filter option is specified. +# Provides methods to format results and stats for output. class DomainsList attr_reader :list From a34737a143881c1b1ac412e773410b403907e270 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Wed, 12 May 2021 13:15:55 +1000 Subject: [PATCH 18/21] Fix hound warnings --- Pavel_Borisov/2/lib/machinery.rb | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index a978891b..7dcaac2f 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -40,16 +40,7 @@ def initialize(domain) def check! begin - http = Net::HTTP.new(@domain) - http.open_timeout = 1 - http.read_timeout = 1 - start_time = Time.now - response = http.get('/') - end_time = Time.now - @response_time = "#{((end_time - start_time) * 1000).round}ms" - @code = response.code.to_i - @body = response.body - @status = :got_response + timed_http_request rescue StandardError => e @status = :errored cause = ('Timeout' if e.is_a? Timeout::Error) || e.cause @@ -68,6 +59,21 @@ def result "#{@domain} - hasn't been checked" end end + + private + + def timed_http_request + http = Net::HTTP.new(@domain) + http.open_timeout = 1 + http.read_timeout = 1 + start_time = Time.now.utc + response = http.get('/') + end_time = Time.now.utc + @response_time = "#{((end_time - start_time) * 1000).round}ms" + @code = response.code.to_i + @body = response.body + @status = :got_response + end end # Reads domains list from a file, filters the list according to the supplied options. From 37533d2a444024afa5e92f0c815403df7799cbb0 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Wed, 12 May 2021 13:28:00 +1000 Subject: [PATCH 19/21] Cleanup stray files --- .github/workflows/reviews.yml | 19 ------------------- .gitmodules | 6 ------ test-2.rb | 6 ------ test.rb | 8 -------- 4 files changed, 39 deletions(-) delete mode 100644 .github/workflows/reviews.yml delete mode 100644 .gitmodules delete mode 100644 test-2.rb delete mode 100644 test.rb diff --git a/.github/workflows/reviews.yml b/.github/workflows/reviews.yml deleted file mode 100644 index e9aa9fef..00000000 --- a/.github/workflows/reviews.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Code review -on: [push, pull_request] -jobs: - run: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - submodules: 'true' - fetch-depth: 0 - - run: | - git fetch --no-tags --prune origin - - uses: adwerx/pronto-ruby@v2.9 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RUBOCOP_CONFIG: ./pronto/rubocop/rubocop.yml - with: - runners: >- - brakeman rails_best_practices reek rubocop diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 78337ad0..00000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "pronto/rubocop"] - path = pronto/rubocop - url = git@github.com:rubyroidlabs/rubocop.git -[submodule "pronto/yamllint"] - path = pronto/yamllint - url = git@github.com:rubyroidlabs/yamllint.git diff --git a/test-2.rb b/test-2.rb deleted file mode 100644 index 2dd83396..00000000 --- a/test-2.rb +++ /dev/null @@ -1,6 +0,0 @@ -a = b = 3 - -if a and b - puts "HEY" - a = a + 1 -end diff --git a/test.rb b/test.rb deleted file mode 100644 index 5933ffd9..00000000 --- a/test.rb +++ /dev/null @@ -1,8 +0,0 @@ -a = 1 -b = 2 -if a && b - a += 1 - b -= 1 -end - -puts 'a + b = ' + (a + b).to_s From 5b3490553d72fec0d1e7613ce59a08be121b44b7 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Wed, 12 May 2021 13:58:51 +1000 Subject: [PATCH 20/21] Fix filter logic [bugfix] --- Pavel_Borisov/2/lib/machinery.rb | 6 +++--- Pavel_Borisov/2/test/machinery_test.rb | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Pavel_Borisov/2/lib/machinery.rb b/Pavel_Borisov/2/lib/machinery.rb index 7dcaac2f..2dd3a92e 100644 --- a/Pavel_Borisov/2/lib/machinery.rb +++ b/Pavel_Borisov/2/lib/machinery.rb @@ -101,7 +101,7 @@ def process! completion_percentage = (processed_count / total_count.to_f * 100).to_i yield(completion_percentage, item.domain) if block_given? end - reject_results_with_word!(@filtered_word) if @filtered_word + keep_results_with_word!(@filtered_word) if @filtered_word self end @@ -136,8 +136,8 @@ def reject_solutions! end end - def reject_results_with_word!(word) - @list.reject! do |response| + def keep_results_with_word!(word) + @list.keep_if do |response| body_text = Nokogiri::HTML.parse(response.body).css('body').text body_text.downcase.match? word.downcase end diff --git a/Pavel_Borisov/2/test/machinery_test.rb b/Pavel_Borisov/2/test/machinery_test.rb index 816dbbe6..6eee4977 100644 --- a/Pavel_Borisov/2/test/machinery_test.rb +++ b/Pavel_Borisov/2/test/machinery_test.rb @@ -50,8 +50,8 @@ def test_exclude_solutions_rejects_gitlab DomainsList.new(TEST_DOMAINS_FILE, { 'exclude-solutions': true }).list.map(&:domain) end - def test_filter_word_rejects_results_with_word_in_body - assert_equal ['subdomain.example.com', 'gitlab.com'], + def test_filter_word_keeps_only_results_with_word_in_body + assert_equal ['example.com'], DomainsList.new(TEST_DOMAINS_FILE, { filter: 'example' }).process!.list.map(&:domain) end end From fa8ae6e3e789b4380d0dc69820417d2701665c22 Mon Sep 17 00:00:00 2001 From: ashpb <31402193+ashpb@users.noreply.github.com> Date: Sat, 15 May 2021 17:18:50 +1000 Subject: [PATCH 21/21] Add .gitignore --- Pavel_Borisov/2/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Pavel_Borisov/2/.gitignore diff --git a/Pavel_Borisov/2/.gitignore b/Pavel_Borisov/2/.gitignore new file mode 100644 index 00000000..fb6d573a --- /dev/null +++ b/Pavel_Borisov/2/.gitignore @@ -0,0 +1,3 @@ +*.sublime-project +*.sublime-workspace +