New Upstream Release - ruby-github-pages-health-check

Ready changes

Summary

Merged new upstream version: 1.18.1 (was: 1.16.1).

Resulting package

Built on 2022-12-29T23:41 (took 6m23s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases ruby-github-pages-health-check

Lintian Result

Diff

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..b844b14
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+Gemfile.lock
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..e021c52
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,15 @@
+version: 2
+updates:
+- package-ecosystem: bundler
+  directory: "/"
+  schedule:
+    interval: daily
+    time: "10:00"
+    timezone: Europe/Vienna
+  pull-request-branch-name:
+    separator: "-"
+  open-pull-requests-limit: 99
+  allow:
+  - dependency-type: direct
+  - dependency-type: indirect
+  rebase-strategy: disabled
diff --git a/.github/workflows/push-cibuild.yml b/.github/workflows/push-cibuild.yml
new file mode 100644
index 0000000..27c3d0a
--- /dev/null
+++ b/.github/workflows/push-cibuild.yml
@@ -0,0 +1,19 @@
+on: push
+name: cibuild on push
+jobs:
+  build:
+    name: "GitHub Pages Health Check Tests"
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        ruby:
+          - 2.5
+          - 2.6
+          - 2.7
+          - 3.0
+    steps:
+    - uses: actions/checkout@master
+    - name: script/cibuild-docker
+      run: script/cibuild-docker
+      env:
+        RUBY_VERSION: ${{ matrix.ruby }}
diff --git a/.rubocop.yml b/.rubocop.yml
index 0f3d8a7..bad031d 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -17,7 +17,7 @@
 #
 
 AllCops:
-  TargetRubyVersion: 2.2
+  TargetRubyVersion: 2.6
   Exclude:
     - 'bin/**/*'
     - 'script/**/*'
@@ -30,10 +30,6 @@ Layout/EndAlignment:
 Lint/UnreachableCode:
   Severity: error
 
-Style/StringLiterals:
-  EnforcedStyle: double_quotes
-  Severity: error
-
 Style/StringLiteralsInInterpolation:
   EnforcedStyle: double_quotes
 
@@ -41,10 +37,10 @@ Style/HashSyntax:
   EnforcedStyle: hash_rockets
   Severity: error
 
-Layout/AlignHash:
+Layout/HashAlignment:
   SupportedLastArgumentHashStyles: always_ignore
 
-Layout/AlignParameters:
+Layout/ParameterAlignment:
   Enabled: false # This is usually true, but we often want to roll back to
                  # the start of a line.
 
@@ -55,13 +51,8 @@ Style/Attr:
 Style/ClassAndModuleChildren:
   Enabled: false # module X<\n>module Y is just as good as module X::Y.
 
-Style/PercentLiteralDelimiters:
-  PreferredDelimiters:
-    '%w': '{}'
-    '%r': '{}'
-
-Metrics/LineLength:
-  Max: 90
+Layout/LineLength:
+  Max: 120
   Severity: warning
   Exclude:
     - github-pages-health-check.gemspec
@@ -99,13 +90,12 @@ Naming/FileName: #Rubocop doesn't like the Git*H*ub namespace
   Enabled: false
 
 Metrics/ParameterLists: { Max: 4 }
-Metrics/AbcSize: { Max: 20 }
 
-Layout/IndentHash: { EnforcedStyle: consistent }
+Layout/FirstHashElementIndentation: { EnforcedStyle: consistent }
 Layout/MultilineMethodCallIndentation: { EnforcedStyle: indented }
 Layout/MultilineOperationIndentation: { EnforcedStyle: indented }
 Layout/FirstParameterIndentation: { EnforcedStyle: consistent }
-Layout/IndentArray: { EnforcedStyle: consistent }
+Layout/FirstArrayElementIndentation: { EnforcedStyle: consistent }
 Layout/ExtraSpacing: { AllowForAlignment: true }
 Style/SignalException: { EnforcedStyle: only_raise }
 Style/StringLiterals: { EnforcedStyle: double_quotes }
@@ -155,3 +145,10 @@ Style/FrozenStringLiteralComment:
 
 Gemspec/RequiredRubyVersion:
   Enabled: false
+
+Style/HashEachMethods:
+  Enabled: false
+Style/HashTransformKeys:
+  Enabled: false
+Style/HashTransformValues:
+  Enabled: false
diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 0000000..ef538c2
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+3.1.2
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 66aa871..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-language: ruby
-rvm:
-  - 2.4
-  - 2.5
-  - 2.6
-
-before_install:
-  - gem install bundler
-
-script: "script/cibuild"
-
-notifications:
-  email: false
-
-cache: bundler
-sudo: false
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..f548631
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,18 @@
+ARG RUBY_VERSION
+FROM ruby:$RUBY_VERSION-slim
+RUN set -ex \
+  && gem update --system --silent --quiet \
+  && apt-get update -y \
+  && apt-get upgrade -y \
+  && apt-get install -y \
+    build-essential \
+    git \
+    libcurl4-openssl-dev \
+  && apt-get clean
+WORKDIR /app/github-pages-health-check
+COPY Gemfile .
+COPY github-pages-health-check.gemspec .
+COPY lib/github-pages-health-check/version.rb lib/github-pages-health-check/version.rb
+RUN bundle install
+COPY . .
+ENTRYPOINT [ "/bin/bash" ]
diff --git a/Gemfile b/Gemfile
index be173b2..7ddd7c1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,4 +2,14 @@
 
 source "https://rubygems.org"
 
+group :development do
+  gem "dotenv", "~> 2.7"
+  gem "gem-release", "~> 2.1"
+  gem "pry", "~> 0.10"
+  gem "pry-byebug"
+  gem "rspec", "~> 3.0"
+  gem "rubocop", "~> 0.52"
+  gem "webmock", "~> 3.8"
+end
+
 gemspec
diff --git a/README.md b/README.md
index dc0b658..1eb0b8d 100644
--- a/README.md
+++ b/README.md
@@ -81,3 +81,40 @@ check = GitHubPages::HealthCheck::Site.new "github/pages-health-check", access_t
 ```
 
 You can also set `OCTOKIT_ACCESS_TOKEN` as an environmental variable, or via a `.env` file in your working directory.
+
+### Command Line
+
+```
+./script/check pages.github.com
+
+host: pages.github.com
+uri: https://pages.github.com/
+nameservers: :default
+dns_resolves?: true
+proxied?: false
+cloudflare_ip?: false
+fastly_ip?: false
+old_ip_address?: false
+a_record?: false
+cname_record?: true
+mx_records_present?: false
+valid_domain?: true
+apex_domain?: false
+should_be_a_record?: false
+cname_to_github_user_domain?: true
+cname_to_pages_dot_github_dot_com?: false
+cname_to_fastly?: false
+pointed_to_github_pages_ip?: false
+non_github_pages_ip_present?: false
+pages_domain?: true
+served_by_pages?: true
+valid?: true
+reason:
+https?: true
+enforces_https?: true
+https_error:
+https_eligible?: true
+caa_error:
+dns_zone_soa?: false
+dns_zone_ns?: false
+```
diff --git a/config/cloudflare-ips.txt b/config/cloudflare-ips.txt
index 2800771..fd160bd 100644
--- a/config/cloudflare-ips.txt
+++ b/config/cloudflare-ips.txt
@@ -9,6 +9,14 @@
 197.234.240.0/22
 198.41.128.0/17
 162.158.0.0/15
-104.16.0.0/12
+104.16.0.0/13
+104.24.0.0/14
 172.64.0.0/13
 131.0.72.0/22
+2400:cb00::/32
+2606:4700::/32
+2803:f800::/32
+2405:b500::/32
+2405:8100::/32
+2a06:98c0::/29
+2c0f:f248::/32
\ No newline at end of file
diff --git a/config/fastly-ips.txt b/config/fastly-ips.txt
index daac7eb..29d9649 100644
--- a/config/fastly-ips.txt
+++ b/config/fastly-ips.txt
@@ -4,9 +4,18 @@
 103.245.222.0/23
 103.245.224.0/24
 104.156.80.0/20
+140.248.64.0/18
+140.248.128.0/17
+146.75.0.0/17
 151.101.0.0/16
 157.52.64.0/18
+167.82.0.0/17
+167.82.128.0/20
+167.82.160.0/20
+167.82.224.0/20
 172.111.64.0/18
 185.31.16.0/22
 199.27.72.0/21
-199.232.0.0/16
\ No newline at end of file
+199.232.0.0/16
+2a04:4e40::/32
+2a04:4e42::/32
\ No newline at end of file
diff --git a/debian/changelog b/debian/changelog
index c9b6756..f10ec22 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,11 +1,14 @@
-ruby-github-pages-health-check (1.16.1-4) UNRELEASED; urgency=medium
+ruby-github-pages-health-check (1.18.1-1) UNRELEASED; urgency=medium
 
   * Remove constraints unnecessary since buster (oldstable):
     + ruby-github-pages-health-check: Drop versioned constraint on ruby-dnsruby
       in Depends.
   * Update standards version to 4.6.1, no changes needed.
+  * New upstream release.
+  * Drop patch 0002-Relax-version-dependency-on-publicsuffix-gem.patch, present
+    upstream.
 
- -- Debian Janitor <janitor@jelmer.uk>  Wed, 21 Sep 2022 16:09:37 -0000
+ -- Debian Janitor <janitor@jelmer.uk>  Thu, 29 Dec 2022 23:35:26 -0000
 
 ruby-github-pages-health-check (1.16.1-3) unstable; urgency=medium
 
diff --git a/debian/patches/0001-Replace-git-execution-from-gemspec.patch b/debian/patches/0001-Replace-git-execution-from-gemspec.patch
index 0dd0a0f..8ec8e45 100644
--- a/debian/patches/0001-Replace-git-execution-from-gemspec.patch
+++ b/debian/patches/0001-Replace-git-execution-from-gemspec.patch
@@ -6,10 +6,10 @@ Subject: Replace git execution from gemspec
  github-pages-health-check.gemspec | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
-diff --git a/github-pages-health-check.gemspec b/github-pages-health-check.gemspec
-index b6ee220..bab1c19 100644
---- a/github-pages-health-check.gemspec
-+++ b/github-pages-health-check.gemspec
+Index: ruby-github-pages-health-check.git/github-pages-health-check.gemspec
+===================================================================
+--- ruby-github-pages-health-check.git.orig/github-pages-health-check.gemspec
++++ ruby-github-pages-health-check.git/github-pages-health-check.gemspec
 @@ -13,7 +13,7 @@ Gem::Specification.new do |s|
    s.email                 = "support@github.com"
    s.homepage              = "https://github.com/github/github-pages-health-check"
diff --git a/debian/patches/0002-Relax-version-dependency-on-publicsuffix-gem.patch b/debian/patches/0002-Relax-version-dependency-on-publicsuffix-gem.patch
deleted file mode 100644
index f6bbaf1..0000000
--- a/debian/patches/0002-Relax-version-dependency-on-publicsuffix-gem.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-From: =?utf-8?q?C=C3=A9dric_Boutillier?= <boutil@debian.org>
-Date: Tue, 26 Oct 2021 14:46:02 +0200
-Subject: Relax version dependency on publicsuffix gem
-
----
- github-pages-health-check.gemspec | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/github-pages-health-check.gemspec b/github-pages-health-check.gemspec
-index bab1c19..4363400 100644
---- a/github-pages-health-check.gemspec
-+++ b/github-pages-health-check.gemspec
-@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
-   s.add_dependency("addressable", "~> 2.3")
-   s.add_dependency("dnsruby", "~> 1.60")
-   s.add_dependency("octokit", "~> 4.0")
--  s.add_dependency("public_suffix", "~> 3.0")
-+  s.add_dependency("public_suffix", ">= 3.0", "< 5.0")
-   s.add_dependency("typhoeus", "~> 1.3")
- 
-   s.add_development_dependency("dotenv", "~> 1.0")
diff --git a/debian/patches/series b/debian/patches/series
index 029c171..2b06a4b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1 @@
 0001-Replace-git-execution-from-gemspec.patch
-0002-Relax-version-dependency-on-publicsuffix-gem.patch
diff --git a/github-pages-health-check.gemspec b/github-pages-health-check.gemspec
index b6ee220..87ad564 100644
--- a/github-pages-health-check.gemspec
+++ b/github-pages-health-check.gemspec
@@ -19,13 +19,6 @@ Gem::Specification.new do |s|
   s.add_dependency("addressable", "~> 2.3")
   s.add_dependency("dnsruby", "~> 1.60")
   s.add_dependency("octokit", "~> 4.0")
-  s.add_dependency("public_suffix", "~> 3.0")
+  s.add_dependency("public_suffix", ">= 3.0", "< 5.0")
   s.add_dependency("typhoeus", "~> 1.3")
-
-  s.add_development_dependency("dotenv", "~> 1.0")
-  s.add_development_dependency("gem-release", "~> 0.7")
-  s.add_development_dependency("pry", "~> 0.10")
-  s.add_development_dependency("rspec", "~> 3.0")
-  s.add_development_dependency("rubocop", "~> 0.52")
-  s.add_development_dependency("webmock", "~> 1.21")
 end
diff --git a/lib/github-pages-health-check.rb b/lib/github-pages-health-check.rb
index 2b75724..c14e019 100644
--- a/lib/github-pages-health-check.rb
+++ b/lib/github-pages-health-check.rb
@@ -37,19 +37,9 @@ module GitHubPages
     # DNS and HTTP timeout, in seconds
     TIMEOUT = 7
 
-    HUMAN_NAME = "GitHub Pages Health Check".freeze
-    URL = "https://github.com/github/pages-health-check".freeze
-    USER_AGENT = "Mozilla/5.0 (compatible; #{HUMAN_NAME}/#{VERSION}; +#{URL})".freeze
-
-    TYPHOEUS_OPTIONS = {
-      :followlocation => true,
-      :timeout => TIMEOUT,
-      :accept_encoding => "gzip",
-      :method => :head,
-      :headers => {
-        "User-Agent" => USER_AGENT
-      }
-    }.freeze
+    HUMAN_NAME = "GitHub Pages Health Check"
+    URL = "https://github.com/github/pages-health-check"
+    USER_AGENT = "Mozilla/5.0 (compatible; #{HUMAN_NAME}/#{VERSION}; +#{URL})"
 
     # surpress warn-level feedback due to unsupported record types
     def self.without_warnings(&block)
@@ -63,5 +53,27 @@ module GitHubPages
     def self.check(repository_or_domain, access_token: nil)
       Site.new repository_or_domain, :access_token => access_token
     end
+
+    # rubocop:disable Naming/AccessorMethodName (this is not an accessor method)
+    def self.set_proxy(proxy_url)
+      @typhoeus_options = typhoeus_options.merge(:proxy => proxy_url).freeze
+      nil
+    end
+    # rubocop:enable Naming/AccessorMethodName
+
+    def self.typhoeus_options
+      return @typhoeus_options if defined?(@typhoeus_options)
+
+      @typhoeus_options = {
+        :followlocation => true,
+        :timeout => TIMEOUT,
+        :accept_encoding => "gzip",
+        :method => :head,
+        :headers => {
+          "User-Agent" => USER_AGENT
+        },
+        :proxy => nil
+      }.freeze
+    end
   end
 end
diff --git a/lib/github-pages-health-check/caa.rb b/lib/github-pages-health-check/caa.rb
index 3e49774..e9e8a7f 100644
--- a/lib/github-pages-health-check/caa.rb
+++ b/lib/github-pages-health-check/caa.rb
@@ -9,7 +9,7 @@ module GitHubPages
     class CAA
       attr_reader :host, :error, :nameservers
 
-      def initialize(host, nameservers: :default)
+      def initialize(host:, nameservers: :default)
         raise ArgumentError, "host cannot be nil" if host.nil?
 
         @host = host
diff --git a/lib/github-pages-health-check/domain.rb b/lib/github-pages-health-check/domain.rb
index cfc35f6..ff39189 100644
--- a/lib/github-pages-health-check/domain.rb
+++ b/lib/github-pages-health-check/domain.rb
@@ -77,15 +77,25 @@ module GitHubPages
         185.199.111.153
       ).freeze
 
+      CURRENT_IPV6_ADDRESSES = %w(
+        2606:50c0:8000::153
+        2606:50c0:8001::153
+        2606:50c0:8002::153
+        2606:50c0:8003::153
+      ).freeze
+
+      CURRENT_IP_ADDRESSES_ALL =
+        (CURRENT_IP_ADDRESSES + CURRENT_IPV6_ADDRESSES).freeze
+
       HASH_METHODS = %i[
         host uri nameservers dns_resolves? proxied? cloudflare_ip?
-        fastly_ip? old_ip_address? a_record? cname_record?
-        mx_records_present? valid_domain? apex_domain? should_be_a_record?
-        cname_to_github_user_domain? cname_to_pages_dot_github_dot_com?
-        cname_to_fastly? pointed_to_github_pages_ip?
-        non_github_pages_ip_present? pages_domain?
+        fastly_ip? old_ip_address? a_record? aaaa_record? a_record_present? aaaa_record_present?
+        cname_record? mx_records_present? valid_domain? apex_domain?
+        should_be_a_record? cname_to_github_user_domain?
+        cname_to_pages_dot_github_dot_com? cname_to_fastly?
+        pointed_to_github_pages_ip? non_github_pages_ip_present? pages_domain?
         served_by_pages? valid? reason valid_domain? https?
-        enforces_https? https_error https_eligible? caa_error
+        enforces_https? https_error https_eligible? caa_error dns_zone_soa? dns_zone_ns?
       ].freeze
 
       def self.redundant(host)
@@ -100,22 +110,24 @@ module GitHubPages
         @host = normalize_host(host)
         @nameservers = nameservers
         @resolver = GitHubPages::HealthCheck::Resolver.new(self.host,
-          :nameservers => nameservers)
+                                                           :nameservers => nameservers)
       end
 
       # Runs all checks, raises an error if invalid
+      # rubocop:disable Metrics/AbcSize
       def check!
-        raise Errors::InvalidDomainError, :domain => self unless valid_domain?
-        raise Errors::InvalidDNSError, :domain => self    unless dns_resolves?
-        raise Errors::DeprecatedIPError, :domain => self if deprecated_ip?
+        raise Errors::InvalidDomainError.new :domain => self unless valid_domain?
+        raise Errors::InvalidDNSError.new :domain => self    unless dns_resolves?
+        raise Errors::DeprecatedIPError.new :domain => self  if deprecated_ip?
         return true if proxied?
-        raise Errors::InvalidARecordError, :domain => self    if invalid_a_record?
-        raise Errors::InvalidCNAMEError, :domain => self      if invalid_cname?
-        raise Errors::InvalidAAAARecordError, :domain => self if invalid_aaaa_record?
-        raise Errors::NotServedByPagesError, :domain => self  unless served_by_pages?
+        raise Errors::InvalidARecordError.new :domain => self    if invalid_a_record?
+        raise Errors::InvalidCNAMEError.new :domain => self      if invalid_cname?
+        raise Errors::InvalidAAAARecordError.new :domain => self if invalid_aaaa_record?
+        raise Errors::NotServedByPagesError.new :domain => self  unless served_by_pages?
 
         true
       end
+      # rubocop:enable Metrics/AbcSize
 
       def deprecated_ip?
         return @deprecated_ip if defined? @deprecated_ip
@@ -126,14 +138,13 @@ module GitHubPages
       def invalid_aaaa_record?
         return @invalid_aaaa_record if defined? @invalid_aaaa_record
 
-        @invalid_aaaa_record = (valid_domain? && should_be_a_record? &&
-                                aaaa_record_present?)
+        @invalid_aaaa_record = (valid_domain? && aaaa_record_present? && !should_be_a_record?)
       end
 
       def invalid_a_record?
         return @invalid_a_record if defined? @invalid_a_record
 
-        @invalid_a_record = (valid_domain? && a_record? && !should_be_a_record?)
+        @invalid_a_record = (valid_domain? && a_record_present? && !should_be_a_record?)
       end
 
       def invalid_cname?
@@ -162,7 +173,10 @@ module GitHubPages
       # Is this domain an apex domain, meaning a CNAME would be innapropriate
       def apex_domain?
         return @apex_domain if defined?(@apex_domain)
-        return unless valid_domain?
+
+        return false unless valid_domain?
+
+        return true if dns_zone_soa? && dns_zone_ns?
 
         # PublicSuffix.domain pulls out the apex-level domain name.
         # E.g. PublicSuffix.domain("techblog.netflix.com") # => "netflix.com"
@@ -175,6 +189,30 @@ module GitHubPages
                             :ignore_private => true) == unicode_host
       end
 
+      #
+      # Does the domain have an associated SOA record?
+      #
+      def dns_zone_soa?
+        return @soa_records if defined?(@soa_records)
+        return false unless dns?
+
+        @soa_records = dns.any? do |answer|
+          answer.type == Dnsruby::Types::SOA && answer.name.to_s == host
+        end
+      end
+
+      #
+      # Does the domain have assoicated NS records?
+      #
+      def dns_zone_ns?
+        return @ns_records if defined?(@ns_records)
+        return false unless dns?
+
+        @ns_records = dns.any? do |answer|
+          answer.type == Dnsruby::Types::NS && answer.name.to_s == host
+        end
+      end
+
       # Should the domain use an A record?
       def should_be_a_record?
         !pages_io_domain? && (apex_domain? || mx_records_present?)
@@ -184,20 +222,20 @@ module GitHubPages
         !should_be_a_record?
       end
 
-      # Is the domain's first response an A record to a valid GitHub Pages IP?
+      # Is the domain's first response an A or AAAA record to a valid GitHub Pages IP?
       def pointed_to_github_pages_ip?
-        a_record? && CURRENT_IP_ADDRESSES.include?(dns.first.address.to_s)
+        return false unless address_record?
+
+        CURRENT_IP_ADDRESSES_ALL.include?(dns.first.address.to_s.downcase)
       end
 
-      # Are any of the domain's A records pointing elsewhere?
+      # Are any of the domain's A or AAAA records pointing elsewhere?
       def non_github_pages_ip_present?
         return unless dns?
 
-        a_records = dns.select { |answer| answer.type == Dnsruby::Types::A }
-
-        a_records.any? { |answer| !github_pages_ip?(answer.address.to_s) }
-
-        false
+        dns
+          .select { |a| Dnsruby::Types::A == a.type || Dnsruby::Types::AAAA == a.type }
+          .any? { |a| !github_pages_ip?(a.address.to_s) }
       end
 
       # Is the domain's first response a CNAME to a pages domain?
@@ -276,7 +314,9 @@ module GitHubPages
         Dnsruby::Types::A,
         Dnsruby::Types::AAAA,
         Dnsruby::Types::CNAME,
-        Dnsruby::Types::MX
+        Dnsruby::Types::MX,
+        Dnsruby::Types::NS,
+        Dnsruby::Types::SOA
       ].freeze
 
       # Returns an array of DNS answers
@@ -314,15 +354,32 @@ module GitHubPages
 
       # Is this domain's first response an A record?
       def a_record?
+        return @is_a_record if defined?(@is_a_record)
+        return unless dns?
+
+        @is_a_record = Dnsruby::Types::A == dns.first.type
+      end
+
+      # Is this domain's first response an AAAA record?
+      def aaaa_record?
+        return @is_aaaa_record if defined?(@is_aaaa_record)
+        return unless dns?
+
+        @is_aaaa_record = Dnsruby::Types::AAAA == dns.first.type
+      end
+
+      # Does this domain has an A record setup (not necessarily as the first record)?
+      def a_record_present?
         return unless dns?
 
-        dns.first.type == Dnsruby::Types::A
+        dns.any? { |answer| answer.type == Dnsruby::Types::A && answer.name.to_s == host }
       end
 
+      # Does this domain has an AAAA record setup (not necessarily as the first record)?
       def aaaa_record_present?
         return unless dns?
 
-        dns.any? { |answer| answer.type == Dnsruby::Types::AAAA }
+        dns.any? { |answer| answer.type == Dnsruby::Types::AAAA && answer.name.to_s == host }
       end
 
       # Is this domain's first response a CNAME record?
@@ -337,6 +394,8 @@ module GitHubPages
       # The domain to which this domain's CNAME resolves
       # Returns nil if the domain is not a CNAME
       def cname
+        return unless dns?
+
         cnames = dns.take_while { |answer| answer.type == Dnsruby::Types::CNAME }
         return if cnames.empty?
 
@@ -354,11 +413,10 @@ module GitHubPages
         return unless dns_resolves?
 
         @served_by_pages = begin
-          return false unless response.mock? || response.return_code == :ok
           return true if response.headers["Server"] == "GitHub.com"
 
           # Typhoeus mangles the case of the header, compare insensitively
-          response.headers.any? { |k, _v| k =~ /X-GitHub-Request-Id/i }
+          response.headers.any? { |k, _v| k.downcase == "x-github-request-id" }
         end
       end
 
@@ -391,10 +449,11 @@ module GitHubPages
       def https_eligible?
         # Can't have any IP's which aren't GitHub's present.
         return false if non_github_pages_ip_present?
-        # Can't have any AAAA records present
-        return false if aaaa_record_present?
-        # Must be a CNAME or point to our IPs.
 
+        # Can't have underscores in the domain name (Let's Encrypt does not allow it)
+        return false if host.include?("_")
+
+        # Must be a CNAME or point to our IPs.
         # Only check the one domain if a CNAME. Don't check the parent domain.
         return true if cname_to_github_user_domain?
 
@@ -404,27 +463,34 @@ module GitHubPages
 
       # Any errors querying CAA records
       def caa_error
-        return nil unless caa.errored?
+        return nil unless caa&.errored?
 
         caa.error.class.name
       end
 
       private
 
+      def address_record?
+        a_record? || aaaa_record?
+      end
+
       def caa
-        @caa ||= GitHubPages::HealthCheck::CAA.new(host, :nameservers => nameservers)
+        @caa ||= GitHubPages::HealthCheck::CAA.new(
+          :host => cname&.host || host,
+          :nameservers => nameservers
+        )
       end
 
       # The domain's response to HTTP(S) requests, following redirects
       def response
         return @response if defined? @response
 
-        @response = Typhoeus.head(uri, TYPHOEUS_OPTIONS)
+        @response = Typhoeus.head(uri, GitHubPages::HealthCheck.typhoeus_options)
 
         # Workaround for webmock not playing nicely with Typhoeus redirects
         # See https://github.com/bblimke/webmock/issues/237
         if @response.mock? && @response.headers["Location"]
-          @response = Typhoeus.head(response.headers["Location"], TYPHOEUS_OPTIONS)
+          @response = Typhoeus.head(response.headers["Location"], GitHubPages::HealthCheck.typhoeus_options)
         end
 
         @response
@@ -432,13 +498,13 @@ module GitHubPages
 
       # The domain's response to HTTP requests, without following redirects
       def http_response
-        options = TYPHOEUS_OPTIONS.merge(:followlocation => false)
+        options = GitHubPages::HealthCheck.typhoeus_options.merge(:followlocation => false)
         @http_response ||= Typhoeus.head(uri(:scheme => "http"), options)
       end
 
       # The domain's response to HTTPS requests, without following redirects
       def https_response
-        options = TYPHOEUS_OPTIONS.merge(:followlocation => false)
+        options = GitHubPages::HealthCheck.typhoeus_options.merge(:followlocation => false)
         @https_response ||= Typhoeus.head(uri(:scheme => "https"), options)
       end
 
@@ -482,10 +548,12 @@ module GitHubPages
       def cdn_ip?(cdn)
         return unless dns?
 
-        a_records = dns.select { |answer| answer.type == Dnsruby::Types::A }
-        return false if !a_records || a_records.empty?
+        address_records = dns.select do |answer|
+          Dnsruby::Types::A == answer.type || Dnsruby::Types::AAAA == answer.type
+        end
+        return false if !address_records || address_records.empty?
 
-        a_records.all? do |answer|
+        address_records.all? do |answer|
           cdn.controls_ip?(answer.address)
         end
       end
@@ -495,7 +563,7 @@ module GitHubPages
       end
 
       def github_pages_ip?(ip_addr)
-        CURRENT_IP_ADDRESSES.include?(ip_addr)
+        CURRENT_IP_ADDRESSES_ALL.include?(ip_addr&.to_s&.downcase)
       end
     end
   end
diff --git a/lib/github-pages-health-check/error.rb b/lib/github-pages-health-check/error.rb
index f478182..61b4018 100644
--- a/lib/github-pages-health-check/error.rb
+++ b/lib/github-pages-health-check/error.rb
@@ -3,8 +3,8 @@
 module GitHubPages
   module HealthCheck
     class Error < StandardError
-      DOCUMENTATION_BASE = "https://help.github.com".freeze
-      DOCUMENTATION_PATH = "/categories/github-pages-basics/".freeze
+      DOCUMENTATION_BASE = "https://help.github.com"
+      DOCUMENTATION_PATH = "/categories/github-pages-basics/"
       LOCAL_ONLY = false # Error is only used when running locally
 
       attr_reader :repository, :domain
diff --git a/lib/github-pages-health-check/errors.rb b/lib/github-pages-health-check/errors.rb
index 7ef1c04..6c25e80 100644
--- a/lib/github-pages-health-check/errors.rb
+++ b/lib/github-pages-health-check/errors.rb
@@ -1,6 +1,6 @@
 # frozen_string_literal: true
 
-Dir[File.expand_path("errors/*_error.rb", __dir__)].each do |f|
+Dir[File.expand_path("errors/*_error.rb", __dir__)].sort.each do |f|
   require f
 end
 
diff --git a/lib/github-pages-health-check/errors/build_error.rb b/lib/github-pages-health-check/errors/build_error.rb
index 438c4d9..ca83563 100644
--- a/lib/github-pages-health-check/errors/build_error.rb
+++ b/lib/github-pages-health-check/errors/build_error.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     module Errors
       class BuildError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/troubleshooting-jekyll-builds/".freeze
+        DOCUMENTATION_PATH = "/articles/troubleshooting-jekyll-builds/"
         LOCAL_ONLY = true
       end
     end
diff --git a/lib/github-pages-health-check/errors/deprecated_ip_error.rb b/lib/github-pages-health-check/errors/deprecated_ip_error.rb
index d4e5d44..fff3f52 100644
--- a/lib/github-pages-health-check/errors/deprecated_ip_error.rb
+++ b/lib/github-pages-health-check/errors/deprecated_ip_error.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     module Errors
       class DeprecatedIPError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/".freeze
+        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/"
 
         def message
           <<-MSG
diff --git a/lib/github-pages-health-check/errors/invalid_a_record_error.rb b/lib/github-pages-health-check/errors/invalid_a_record_error.rb
index 8563a9e..3becf88 100644
--- a/lib/github-pages-health-check/errors/invalid_a_record_error.rb
+++ b/lib/github-pages-health-check/errors/invalid_a_record_error.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     module Errors
       class InvalidARecordError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/".freeze
+        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/"
 
         def message
           <<-MSG
diff --git a/lib/github-pages-health-check/errors/invalid_aaaa_record_error.rb b/lib/github-pages-health-check/errors/invalid_aaaa_record_error.rb
index 8afa42c..2d8ed7c 100644
--- a/lib/github-pages-health-check/errors/invalid_aaaa_record_error.rb
+++ b/lib/github-pages-health-check/errors/invalid_aaaa_record_error.rb
@@ -4,13 +4,13 @@ module GitHubPages
   module HealthCheck
     module Errors
       class InvalidAAAARecordError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/".freeze
+        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/"
 
         def message
           <<-MSG
-             Your site's DNS settings are using a custom subdomain, #{domain.host},
-             that's set up with an AAAA record. GitHub Pages currently does not support
-             IPv6.
+          Your site's DNS settings are using a custom subdomain, #{domain.host},
+          that's set up as an AAAA record. We recommend you change this to a CNAME
+          record pointing at #{username}.github.io.
           MSG
         end
       end
diff --git a/lib/github-pages-health-check/errors/invalid_cname_error.rb b/lib/github-pages-health-check/errors/invalid_cname_error.rb
index 5bd3669..e62c04c 100644
--- a/lib/github-pages-health-check/errors/invalid_cname_error.rb
+++ b/lib/github-pages-health-check/errors/invalid_cname_error.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     module Errors
       class InvalidCNAMEError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/".freeze
+        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/"
 
         def message
           <<-MSG
diff --git a/lib/github-pages-health-check/errors/invalid_dns_error.rb b/lib/github-pages-health-check/errors/invalid_dns_error.rb
index 85c197d..9fa9bc8 100644
--- a/lib/github-pages-health-check/errors/invalid_dns_error.rb
+++ b/lib/github-pages-health-check/errors/invalid_dns_error.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     module Errors
       class InvalidDNSError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/".freeze
+        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/"
 
         def message
           "Domain's DNS record could not be retrieved"
diff --git a/lib/github-pages-health-check/errors/invalid_domain_error.rb b/lib/github-pages-health-check/errors/invalid_domain_error.rb
index adbb56c..c33cd25 100644
--- a/lib/github-pages-health-check/errors/invalid_domain_error.rb
+++ b/lib/github-pages-health-check/errors/invalid_domain_error.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     module Errors
       class InvalidDomainError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/".freeze
+        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/"
 
         def message
           "Domain is not a valid domain"
diff --git a/lib/github-pages-health-check/errors/not_served_by_pages_error.rb b/lib/github-pages-health-check/errors/not_served_by_pages_error.rb
index d1b7349..7b3c57c 100644
--- a/lib/github-pages-health-check/errors/not_served_by_pages_error.rb
+++ b/lib/github-pages-health-check/errors/not_served_by_pages_error.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     module Errors
       class NotServedByPagesError < GitHubPages::HealthCheck::Error
-        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/".freeze
+        DOCUMENTATION_PATH = "/articles/setting-up-a-custom-domain-with-github-pages/"
 
         def message
           "Domain does not resolve to the GitHub Pages server"
diff --git a/lib/github-pages-health-check/printer.rb b/lib/github-pages-health-check/printer.rb
index 5cb3ff1..0004a8d 100644
--- a/lib/github-pages-health-check/printer.rb
+++ b/lib/github-pages-health-check/printer.rb
@@ -4,7 +4,7 @@ module GitHubPages
   module HealthCheck
     class Printer
       PRETTY_LEFT_WIDTH = 11
-      PRETTY_JOINER = " | ".freeze
+      PRETTY_JOINER = " | "
 
       attr_reader :health_check
 
diff --git a/lib/github-pages-health-check/repository.rb b/lib/github-pages-health-check/repository.rb
index 4bf2a1f..800a5c4 100644
--- a/lib/github-pages-health-check/repository.rb
+++ b/lib/github-pages-health-check/repository.rb
@@ -47,11 +47,11 @@ module GitHubPages
       alias reason build_error
 
       def build_duration
-        last_build && last_build.duration
+        last_build&.duration
       end
 
       def last_built
-        last_build && last_build.updated_at
+        last_build&.updated_at
       end
 
       def domain
diff --git a/lib/github-pages-health-check/resolver.rb b/lib/github-pages-health-check/resolver.rb
index 009fa84..9d161d7 100644
--- a/lib/github-pages-health-check/resolver.rb
+++ b/lib/github-pages-health-check/resolver.rb
@@ -43,16 +43,16 @@ module GitHubPages
                         self.class.default_resolver
                       when :authoritative
                         Dnsruby::Resolver.new(DEFAULT_RESOLVER_OPTIONS.merge(
-                          :nameservers => authoritative_nameservers
-                        ))
+                                                :nameservers => authoritative_nameservers
+                                              ))
                       when :public
                         Dnsruby::Resolver.new(DEFAULT_RESOLVER_OPTIONS.merge(
-                          :nameservers => PUBLIC_NAMESERVERS
-                        ))
+                                                :nameservers => PUBLIC_NAMESERVERS
+                                              ))
                       when Array
                         Dnsruby::Resolver.new(DEFAULT_RESOLVER_OPTIONS.merge(
-                          :nameservers => nameservers
-                        ))
+                                                :nameservers => nameservers
+                                              ))
                       else
                         raise "Invalid nameserver type: #{nameservers.inspect}"
                       end
diff --git a/lib/github-pages-health-check/version.rb b/lib/github-pages-health-check/version.rb
index 9b8d9dd..86b9bdf 100644
--- a/lib/github-pages-health-check/version.rb
+++ b/lib/github-pages-health-check/version.rb
@@ -2,6 +2,6 @@
 
 module GitHubPages
   module HealthCheck
-    VERSION = "1.16.1".freeze
+    VERSION = "1.18.1"
   end
 end
diff --git a/script/check b/script/check
index 2328b0a..742daff 100755
--- a/script/check
+++ b/script/check
@@ -3,6 +3,8 @@
 #
 # Usage: script/check [DOMAIN]
 
+require "rubygems"
+require "bundler/setup"
 require_relative "../lib/github-pages-health-check"
 
 if ARGV.count != 1
diff --git a/script/cibuild b/script/cibuild
index e311b09..7831760 100755
--- a/script/cibuild
+++ b/script/cibuild
@@ -4,7 +4,7 @@ set -ex
 
 script/bootstrap
 
-script/test
+script/test $@
 script/check-cdn-ips
 bundle exec script/check www.parkermoore.de | grep 'valid?: true'
 bundle exec script/check ben.balter.com | grep 'valid?: true'
diff --git a/script/cibuild-docker b/script/cibuild-docker
new file mode 100755
index 0000000..605b3dd
--- /dev/null
+++ b/script/cibuild-docker
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+: ${RUBY_VERSION:="2.7"}
+docker build -t github-pages-health-check --build-arg RUBY_VERSION=$RUBY_VERSION .
+if [ -n "$DEBUG" ]; then
+  # Run a shell.
+  docker run -it --rm -v $(pwd):/app/github-pages-health-check github-pages-health-check
+else
+  # Run CI
+  docker run --rm github-pages-health-check script/cibuild --profile --fail-fast
+fi
diff --git a/script/test b/script/test
index ca04f20..6eead4a 100755
--- a/script/test
+++ b/script/test
@@ -3,4 +3,4 @@
 set -e
 
 bundle exec rspec $@
-script/fmt $@
+script/fmt
diff --git a/script/update-cdn-ips b/script/update-cdn-ips
index 1cbfa00..a496f4f 100755
--- a/script/update-cdn-ips
+++ b/script/update-cdn-ips
@@ -8,15 +8,43 @@ require "open-uri"
 require "json"
 
 SOURCES = {
-  :cloudflare => "https://www.cloudflare.com/ips-v4",
-  :fastly => "https://api.fastly.com/public-ip-list"
+  :cloudflare => ["https://www.cloudflare.com/ips-v4", "https://www.cloudflare.com/ips-v6"],
+  :fastly => ["https://api.fastly.com/public-ip-list"]
 }.freeze
 
-SOURCES.each do |source, url|
+def parse_fastly(data)
+  json_data = JSON.parse(data)
+  (json_data["addresses"] + json_data["ipv6_addresses"]).join("\n")
+end
+
+def parse_cloudflare(data)
+  data
+end
+
+def fetch_ips_from_cdn(urls)
+  urls.map do |url|
+    puts "Fetching #{url}..."
+    URI.parse(url).open.read
+  end.join("\n")
+end
+
+def update_cdn_file(source, data)
   file = "config/#{source}-ips.txt"
-  puts "Fetching #{url}..."
-  data = open(url).read
-  data = JSON.parse(data)["addresses"].join("\n") if source == :fastly
   File.write(file, data)
+  puts "Writing contents to #{file} and staging changes."
   `git add --verbose #{file}`
 end
+
+def parse_cdn_response(source, ips)
+  send("parse_#{source}", ips)
+end
+
+def update_cdn_ips(source, urls)
+  ips = fetch_ips_from_cdn(urls)
+  data = parse_cdn_response(source, ips)
+  update_cdn_file(source, data)
+end
+
+SOURCES.each do |source, urls|
+  update_cdn_ips(source, urls)
+end

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/share/rubygems-integration/all/specifications/github-pages-health-check-1.18.1.gemspec

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/share/rubygems-integration/all/specifications/github-pages-health-check-1.16.1.gemspec

Control files: lines which differ (wdiff format)

  • Ruby-Versions: all

More details

Full run details