diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..db7f139
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,32 @@
+name: Test
+
+on:
+  - push
+
+jobs:
+  build-test:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: ['3.7', '3.8', '3.9', 'pypy-3.7']
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: actions/setup-python@v2
+        with:
+          python-version: ${{ matrix.python-version }}
+          architecture: x64
+          cache: 'pip'
+          cache-dependency-path: '**/dev-requirements'
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          python -m pip install --upgrade setuptools
+          python -m pip install -e .[dev]
+          python -m pip install tox tox-gh-actions
+      - name: Test with tox
+        run: tox
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 2a7b03b..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: python
-
-python:
-  - "3.8"
-  - "3.7"
-  - "3.6"
-  - "3.5"
-  - "2.7"
-  - "pypy"
-  - "pypy3"
-
-install:
-  - pip install --upgrade pip
-  - pip install --upgrade setuptools
-  - pip install -e .[dev]
-  - pip install tox-travis
-
-script:
-  - tox
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 662301d..fc09522 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -64,8 +64,8 @@ You can setup your local environment for developing patches for cpplint like thi
     # run all tests
     ./setup.py test
     ./setup.py lint
-    ./setup.py style
     ./setup.py ci # all the above
+    ./flake8
     tox    # all of the above in all python environments
 
 Releasing
@@ -129,7 +129,7 @@ To incorporate google's changes:
     git status --untracked-files=no | grep 'nothing to commit' && git rebase --skip
 
     git push -u origin updates
-    # check travis
+    # check github action
     git push origin --delete updates
 
     git rebase updates master
diff --git a/README.rst b/README.rst
index 18af13c..9ff67c0 100644
--- a/README.rst
+++ b/README.rst
@@ -1,9 +1,6 @@
 cpplint - static code checker for C++
 =====================================
 
-.. image:: https://travis-ci.org/cpplint/cpplint.svg?branch=master
-    :target: https://travis-ci.org/cpplint/cpplint
-
 .. image:: https://img.shields.io/pypi/v/cpplint.svg
     :target: https://pypi.python.org/pypi/cpplint
 
@@ -62,7 +59,7 @@ The modifications in this fork are minor fixes and cosmetic changes, such as:
 * python 3 compatibility
 * more default file extensions
 * customizable file extensions with the --extensions argument
-* continuous integration on travis
+* continuous integration on github
 * support for recursive file discovery via the --recursive argument
 * support for excluding files via --exclude
 * JUnit XML output format
diff --git a/changelog.rst b/changelog.rst
index d009717..17ca4a1 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+1.6.0 (2022-02-19)
+-----
+
+* Fix #188: "Include the directory when naming header files" also for header files with other names like "*.hpp"
+
 1.5.5 (2021-05-20)
 -----
 
diff --git a/cpplint.py b/cpplint.py
index 3bf3441..6b78b30 100755
--- a/cpplint.py
+++ b/cpplint.py
@@ -41,6 +41,11 @@ We do a small hack, which is to ignore //'s with "'s after them on the
 same line, but it is far from perfect (in either direction).
 """
 
+# cpplint predates fstrings
+# pylint: disable=consider-using-f-string
+
+# pylint: disable=invalid-name
+
 import codecs
 import copy
 import getopt
@@ -59,7 +64,7 @@ import xml.etree.ElementTree
 # if empty, use defaults
 _valid_extensions = set([])
 
-__VERSION__ = '1.5.5'
+__VERSION__ = '1.6.0'
 
 try:
   xrange          # Python 2
@@ -1915,6 +1920,7 @@ class CleansedLines(object):
     self.raw_lines = lines
     self.num_lines = len(lines)
     self.lines_without_raw_strings = CleanseRawStrings(lines)
+    # # pylint: disable=consider-using-enumerate
     for linenum in range(len(self.lines_without_raw_strings)):
       self.lines.append(CleanseComments(
           self.lines_without_raw_strings[linenum]))
@@ -5068,10 +5074,12 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
   #
   # We also make an exception for Lua headers, which follow google
   # naming convention but not the include convention.
-  match = Match(r'#include\s*"([^/]+\.h)"', line)
-  if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
-    error(filename, linenum, 'build/include_subdir', 4,
-          'Include the directory when naming .h files')
+  match = Match(r'#include\s*"([^/]+\.(.*))"', line)
+  if match:
+    if (IsHeaderExtension(match.group(2)) and
+        not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1))):
+      error(filename, linenum, 'build/include_subdir', 4,
+            'Include the directory when naming header files')
 
   # we shouldn't include a file more than once. actually, there are a
   # handful of instances where doing so is okay, but in general it's
@@ -6523,7 +6531,7 @@ def ProcessConfigOverrides(filename):
       continue
 
     try:
-      with open(cfg_file) as file_handle:
+      with open(cfg_file, encoding='utf-8') as file_handle:
         for line in file_handle:
           line, _, _ = line.partition('#')  # Remove comments.
           if not line.strip():
diff --git a/cpplint_clitest.py b/cpplint_clitest.py
index eababc9..c6edd63 100755
--- a/cpplint_clitest.py
+++ b/cpplint_clitest.py
@@ -86,10 +86,10 @@ class TemporaryFolderClassSetup(object):
             cls._root = os.path.realpath(tempfile.mkdtemp())
             shutil.copytree('samples', os.path.join(cls._root, 'samples'))
             cls.prepare_directory(cls._root)
-        except Exception as e:
+        except Exception:
             try:
                 cls.tearDownClass()
-            except Exception as e2:
+            except Exception:
                 pass
             raise
 
diff --git a/cpplint_unittest.py b/cpplint_unittest.py
index beab5d6..957c7b5 100755
--- a/cpplint_unittest.py
+++ b/cpplint_unittest.py
@@ -136,6 +136,7 @@ class MockIo(object):
     class EnterableList(list):
       def __enter__(self):
         return self
+
       def __exit__(self, type, value, tb):
         return self
     self.mock_file = EnterableList(mock_file)
@@ -351,7 +352,6 @@ class CpplintTest(CpplintTestBase):
     results = self.GetNamespaceResults(lines)
     self.assertEquals(results, '')
 
-
   # Test get line width.
   def testGetLineWidth(self):
     self.assertEquals(0, cpplint.GetLineWidth(''))
@@ -1253,20 +1253,19 @@ class CpplintTest(CpplintTestBase):
 
   def testRawStrings(self):
     self.TestMultiLineLint(
-      """
-      int main() {
-        struct A {
-           A(std::string s, A&& a);
-        };
-      }""",
+        """
+        int main() {
+          struct A {
+             A(std::string s, A&& a);
+          };
+        }""",
         '')
-
     self.TestMultiLineLint(
-      """
-      template <class T, class D = default_delete<T>> class unique_ptr {
-       public:
-          unique_ptr(unique_ptr&& u) noexcept;
-      };""",
+        """
+        template <class T, class D = default_delete<T>> class unique_ptr {
+         public:
+            unique_ptr(unique_ptr&& u) noexcept;
+        };""",
         '')
     self.TestMultiLineLint(
         """
@@ -1965,7 +1964,6 @@ class CpplintTest(CpplintTestBase):
     self.TestLint('  VLOG(FATAL)', errmsg)
     self.TestLint('  VLOG(DFATAL)', errmsg)
 
-
   # Test potential format string bugs like printf(foo).
   def testFormatStrings(self):
     self.TestLint('printf("foo")', '')
@@ -2966,7 +2964,6 @@ class CpplintTest(CpplintTestBase):
                   'Missing space around colon in range-based for loop'
                   '  [whitespace/forcolon] [2]')
 
-
   # Static or global STL strings.
   def testStaticOrGlobalSTLStrings(self):
     # A template for the error message for a const global/static string.
@@ -3189,8 +3186,8 @@ class CpplintTest(CpplintTestBase):
     self.TestLint('//====', '')
     self.TestLint('//////', '')
     self.TestLint('////// x', '')
-    self.TestLint('///< x', '') # After-member Doxygen comment
-    self.TestLint('//!< x', '') # After-member Doxygen comment
+    self.TestLint('///< x', '')  # After-member Doxygen comment
+    self.TestLint('//!< x', '')  # After-member Doxygen comment
     self.TestLint('////x', 'Should have a space between // and comment'
                   '  [whitespace/comments] [4]')
     self.TestLint('//}', '')
@@ -3285,9 +3282,9 @@ class CpplintTest(CpplintTestBase):
     error_collector = ErrorCollector(self.assert_)
     raw_bytes = codecs_latin_encode('\xe9x\0')
     if sys.version_info < (3,):
-          unidata = unicode(raw_bytes, 'utf8', 'replace')
+      unidata = unicode(raw_bytes, 'utf8', 'replace')
     else:
-          unidata = str(raw_bytes, 'utf8', 'replace')
+      unidata = str(raw_bytes, 'utf8', 'replace')
     cpplint.ProcessFileData(
         'nul_utf8.cc', 'cc',
         ['// Copyright 2014 Your Company.',
@@ -4796,7 +4793,7 @@ class CpplintTest(CpplintTestBase):
     # do not hardcode the 'styleguide' repository name, it could be anything.
     expected_prefix = re.sub(r'[^a-zA-Z0-9]', '_', styleguide_dir_name).upper() + '_'
     # do not have 'styleguide' repo in '/'
-    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' %(expected_prefix),
+    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' % (expected_prefix),
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     # To run the 'relative path' tests, we must be in the directory of this test file.
@@ -4811,9 +4808,9 @@ class CpplintTest(CpplintTestBase):
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     styleguide_rel_path = os.path.relpath(styleguide_parent_path,
-                                          this_files_path) # '../..'
+                                          this_files_path)  # '../..'
     cpplint._root = styleguide_rel_path
-    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' %(expected_prefix),
+    self.assertEquals('%sCPPLINT_CPPLINT_TEST_HEADER_H_' % (expected_prefix),
                       cpplint.GetHeaderGuardCPPVariable(file_path))
 
     cpplint._root = None
@@ -4971,8 +4968,13 @@ class CpplintTest(CpplintTestBase):
   def testBuildInclude(self):
     # Test that include statements have slashes in them.
     self.TestLint('#include "foo.h"',
-                  'Include the directory when naming .h files'
+                  'Include the directory when naming header files'
+                  '  [build/include_subdir] [4]')
+    self.TestLint('#include "bar.hh"',
+                  'Include the directory when naming header files'
                   '  [build/include_subdir] [4]')
+    self.TestLint('#include "baz.aa"', '')
+    self.TestLint('#include "dir/foo.h"', '')
     self.TestLint('#include "Python.h"', '')
     self.TestLint('#include "lua.h"', '')
 
@@ -6312,7 +6314,7 @@ class NestingStateTest(unittest.TestCase):
 
   def testTemplateDefaultArg(self):
     self.UpdateWithLines([
-      'template <class T, class D = default_delete<T>> class unique_ptr {',])
+      'template <class T, class D = default_delete<T>> class unique_ptr {'])
     self.assertEquals(len(self.nesting_state.stack), 1)
     self.assertTrue(self.nesting_state.stack[0], isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
 
@@ -6456,7 +6458,7 @@ class QuietTest(unittest.TestCase):
 
     cmd_line = [self.python_executable, cpplint_abspath] +                     \
         list(args) +                                                           \
-        [ self.cpplint_test_h ]
+        [self.cpplint_test_h]
 
     return_code = 0
     try:
@@ -6520,9 +6522,9 @@ class QuietTest(unittest.TestCase):
     # Output with no errors must be completely blank!
     self.assertEquals("", output)
 
-#class FileFilterTest(unittest.TestCase):
-#  def testFilterExcludedFiles(self):
-#    self.assertEquals([], _FilterExcludedFiles([]))
+# class FileFilterTest(unittest.TestCase):
+#   def testFilterExcludedFiles(self):
+#     self.assertEquals([], _FilterExcludedFiles([]))
 
 # pylint: disable=C6409
 def setUp():
diff --git a/debian/changelog b/debian/changelog
index 005108a..558368d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+cpplint (1.6.0-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Wed, 16 Mar 2022 22:55:20 -0000
+
 cpplint (1.5.5-2) unstable; urgency=medium
 
   [ Bastian Germann ]
diff --git a/debian/patches/0001-Ignore-version-requirement-for-pytest-runner.patch b/debian/patches/0001-Ignore-version-requirement-for-pytest-runner.patch
index 09bfa45..6540194 100644
--- a/debian/patches/0001-Ignore-version-requirement-for-pytest-runner.patch
+++ b/debian/patches/0001-Ignore-version-requirement-for-pytest-runner.patch
@@ -9,10 +9,10 @@ Subject: Ignore version requirement for pytest-runner
  setup.py | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
-diff --git a/setup.py b/setup.py
-index aef5c4e..030ea14 100755
---- a/setup.py
-+++ b/setup.py
+Index: cpplint/setup.py
+===================================================================
+--- cpplint.orig/setup.py
++++ cpplint/setup.py
 @@ -73,7 +73,7 @@ setup(name='cpplint',
        long_description=open('README.rst').read(),
        license='BSD-3-Clause',
diff --git a/dev-requirements b/dev-requirements
index 2dfe9ce..5a695b3 100644
--- a/dev-requirements
+++ b/dev-requirements
@@ -1,14 +1,9 @@
 # requirements to run development steps
 
 # also change in tox.ini
-flake8>=3.7.8
+flake8>=4.0.1
 flake8-polyfill
-pylint>=1.8.4
+pylint>=2.11.0
 tox>=3.0.0
 tox-pyenv
 importlib-metadata>=0.12
-
-# Below only run with python3, installed in tox.ini
-# mypy
-# coala
-# coala-bears
diff --git a/samples/boost-sample/exclude.def b/samples/boost-sample/exclude.def
index 102cbcc..2ba4f60 100644
--- a/samples/boost-sample/exclude.def
+++ b/samples/boost-sample/exclude.def
@@ -3,9 +3,10 @@
 4
 Done processing src/inspect/unnamed_namespace_check.hpp
 Done processing src/tr1/c_policy.hpp
-Total errors found: 106
+Total errors found: 107
 
 src/inspect/unnamed_namespace_check.hpp:0:  No #ifndef header guard found, suggested CPP variable is: SAMPLES_BOOST_SAMPLE_SRC_INSPECT_UNNAMED_NAMESPACE_CHECK_HPP_  [build/header_guard] [5]
+src/inspect/unnamed_namespace_check.hpp:11:  Include the directory when naming header files  [build/include_subdir] [4]
 src/inspect/unnamed_namespace_check.hpp:14:  Do not use unnamed namespaces in header files.  See https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces for more information.  [build/namespaces_headers] [4]
 src/inspect/unnamed_namespace_check.hpp:18:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/inspect/unnamed_namespace_check.hpp:19:  Closing ) should be moved to the previous line  [whitespace/parens] [2]
diff --git a/samples/boost-sample/headers_inspect.def b/samples/boost-sample/headers_inspect.def
index a2975a0..b54e21c 100644
--- a/samples/boost-sample/headers_inspect.def
+++ b/samples/boost-sample/headers_inspect.def
@@ -2,9 +2,10 @@ src/inspect/*
 1
 3
 Done processing src/inspect/unnamed_namespace_check.hpp
-Total errors found: 40
+Total errors found: 41
 
 src/inspect/unnamed_namespace_check.hpp:0:  No #ifndef header guard found, suggested CPP variable is: SAMPLES_BOOST_SAMPLE_SRC_INSPECT_UNNAMED_NAMESPACE_CHECK_HPP_  [build/header_guard] [5]
+src/inspect/unnamed_namespace_check.hpp:11:  Include the directory when naming header files  [build/include_subdir] [4]
 src/inspect/unnamed_namespace_check.hpp:14:  Do not use unnamed namespaces in header files.  See https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces for more information.  [build/namespaces_headers] [4]
 src/inspect/unnamed_namespace_check.hpp:18:  At least two spaces is best between code and comments  [whitespace/comments] [2]
 src/inspect/unnamed_namespace_check.hpp:19:  Closing ) should be moved to the previous line  [whitespace/parens] [2]
diff --git a/samples/chromium-sample/simple.def b/samples/chromium-sample/simple.def
index c2baca6..d1c4a68 100644
--- a/samples/chromium-sample/simple.def
+++ b/samples/chromium-sample/simple.def
@@ -7,7 +7,7 @@ Done processing src/io_thread.cc
 Done processing src/io_thread.h
 Total errors found: 13
 
-src/chrome_content_renderer_client.cc:113:  Include the directory when naming .h files  [build/include_subdir] [4]
+src/chrome_content_renderer_client.cc:113:  Include the directory when naming header files  [build/include_subdir] [4]
 src/chrome_content_renderer_client.cc:1156:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
 src/chrome_content_renderer_client.cc:1161:  Use int16/int64/etc, rather than the C type long  [runtime/int] [4]
 src/chrome_content_renderer_client.cc:5:  samples/chromium-sample/src/chrome_content_renderer_client.cc should include its header file samples/chromium-sample/src/chrome_content_renderer_client.h  [build/include] [5]
diff --git a/samples/codelite-sample/simple.def b/samples/codelite-sample/simple.def
index 5b22f2b..4e45c6b 100644
--- a/samples/codelite-sample/simple.def
+++ b/samples/codelite-sample/simple.def
@@ -6,7 +6,7 @@ Done processing src/pptable.h
 Total errors found: 681
 
 src/pptable.cpp:0:  No copyright message found.  You should have a line: "Copyright [year] <Copyright Owner>"  [legal/copyright] [5]
-src/pptable.cpp:1:  Include the directory when naming .h files  [build/include_subdir] [4]
+src/pptable.cpp:1:  Include the directory when naming header files  [build/include_subdir] [4]
 src/pptable.cpp:6:  { should almost always be at the end of the previous line  [whitespace/braces] [4]
 src/pptable.cpp:7:  Tab found; better to use spaces  [whitespace/tab] [1]
 src/pptable.cpp:8:  Tab found; better to use spaces  [whitespace/tab] [1]
diff --git a/samples/vlc-sample/simple.def b/samples/vlc-sample/simple.def
index ac938d8..174819e 100644
--- a/samples/vlc-sample/simple.def
+++ b/samples/vlc-sample/simple.def
@@ -11,7 +11,7 @@ src/libvlc.c:47:  Found C system header after other header. Should be: libvlc.h,
 src/libvlc.c:48:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
 src/libvlc.c:49:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
 src/libvlc.c:50:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
-src/libvlc.c:71:  Include the directory when naming .h files  [build/include_subdir] [4]
+src/libvlc.c:71:  Include the directory when naming header files  [build/include_subdir] [4]
 src/libvlc.c:75:  Found C system header after other header. Should be: libvlc.h, c system, c++ system, other.  [build/include_order] [4]
 src/libvlc.c:86:  Extra space before [  [whitespace/braces] [5]
 src/libvlc.c:86:  Extra space after ( in function call  [whitespace/parens] [4]
diff --git a/setup.cfg b/setup.cfg
index b2cd135..6367539 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,7 +1,5 @@
 [aliases]
 test = pytest
-style = flake8
-ci = lint style test
 
 [tool:pytest]
 python_files = *test.py
diff --git a/tox.ini b/tox.ini
index 02fbbef..f5c1006 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,11 +1,19 @@
 [tox]
-envlist = py27, py36, py37, py38, pypy, pypy3
+envlist = py37, py38, py39, pypy3
+
+
+[gh-actions]
+python =
+    3.7: py37
+    3.8: py38
+    3.9: py39
+    pypy-3.7: pypy3
 
 [testenv]
 deps =
-  py38: flake8>=3.7.8
+  py38: flake8>=4.0.1
   py38: radon>=2.4.0
-  py38: pylint>=1.8.4
+  py38: pylint>=2.11.0
   py38: flake8-polyfill
   py35: importlib-metadata>=0.12
   py27: importlib-metadata>=0.12
@@ -14,4 +22,4 @@ deps =
 commands =
   {envpython} setup.py test
   py38: {envpython} setup.py lint
-  py38: {envpython} setup.py style
+  py38: {envpython} -m flake8