[fetch] Mark commits which touch .gitattributes as "interesting".

This check is a bit presumptuous; it assumes that all modifications to
.gitattributes files are interesting to recipes which is certainly not
true.

However, the alternatives are tricky:

   1. Modify the gitattr checker logic in the recipe engine to see if
      the set of 'recipe files' changes with and without the .gitattributes
      modification. This would require probing a lot more data from git
      than the engine does currently.
   2. Load the diff of .gitattributes to see if it mentions the
      'recipes' tag. This is less work than option 1, and more accurate
      than the current CL, but still not totally accurate (though likely
      very close to perfect).

I think, for now, the current CL is a "good enough" approximation of the
correct behavior :)

R=lannm@chromium.org, martiniss@chromium.org, nodir@chromium.org

Bug: 938601
Change-Id: Idb5dff09b0f707d6eeb716ffe3d86c5d0b8d3e56
Reviewed-on: https://chromium-review.googlesource.com/c/infra/luci/recipes-py/+/1544893
Auto-Submit: Robbie Iannucci <iannucci@chromium.org>
Commit-Queue: Stephen Martinis <martiniss@chromium.org>
Reviewed-by: Stephen Martinis <martiniss@chromium.org>
diff --git a/recipe_engine/internal/fetch.py b/recipe_engine/internal/fetch.py
index 8efc740..577dce3 100644
--- a/recipe_engine/internal/fetch.py
+++ b/recipe_engine/internal/fetch.py
@@ -383,6 +383,7 @@
     has_interesting_changes = (
         simple_cfg.RECIPES_CFG_LOCATION_REL in changed_files or
         any(f.startswith(recipes_path) for f in changed_files) or
+        any(f.split('/')[-1] == '.gitattributes' for f in changed_files) or
         self._gitattr_checker.check_files(revision, changed_files))
 
     return CommitMetadata(revision, meta[0],
diff --git a/unittests/fetch_test.py b/unittests/fetch_test.py
index df94115..2cd37aa 100755
--- a/unittests/fetch_test.py
+++ b/unittests/fetch_test.py
@@ -300,6 +300,50 @@
     self.assertMultiDone(git)
     attr_checker.assert_called_with('a'*40, set(['foo', 'bar']))
 
+  @mock.patch('os.path.isdir')
+  @mock.patch(fetch.__name__+'.GitBackend._execute')
+  def test_commit_metadata_only_gitattributes_file(self, git, isdir):
+    isdir.return_value = False
+    spec = attr.evolve(self.default_spec, recipes_path='recipes')
+
+    git.side_effect = multi(*([
+      self.g(['init', 'dir']),
+      self.g_ls_remote()
+    ] + self.g_metadata_calls(config=spec, diff=['.gitattributes'])))
+
+    result = fetch.GitBackend('dir', 'repo').commit_metadata('revision')
+    self.assertEqual(result, fetch.CommitMetadata(
+      revision = 'a'*40,
+      author_email = 'foo@example.com',
+      commit_timestamp = 1492131405,
+      message_lines = ('hello', 'world'),
+      spec = spec,
+      roll_candidate = True,
+    ))
+    self.assertMultiDone(git)
+
+  @mock.patch('os.path.isdir')
+  @mock.patch(fetch.__name__+'.GitBackend._execute')
+  def test_commit_metadata_only_gitattributes_file_2(self, git, isdir):
+    isdir.return_value = False
+    spec = attr.evolve(self.default_spec, recipes_path='recipes')
+
+    git.side_effect = multi(*([
+      self.g(['init', 'dir']),
+      self.g_ls_remote()
+    ] + self.g_metadata_calls(config=spec, diff=['subdir/.gitattributes'])))
+
+    result = fetch.GitBackend('dir', 'repo').commit_metadata('revision')
+    self.assertEqual(result, fetch.CommitMetadata(
+      revision = 'a'*40,
+      author_email = 'foo@example.com',
+      commit_timestamp = 1492131405,
+      message_lines = ('hello', 'world'),
+      spec = spec,
+      roll_candidate = True,
+    ))
+    self.assertMultiDone(git)
+
 
 if __name__ == '__main__':
   test_env.main()