We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
_matches_any_tag missing from BuildStartEndStatusGenerator
The [_matches_any_tag function](https://github.com/buildbot/buildbot/blob/e630745771a8bd03a2084d03ea8e43547d3dff4b/master/buildbot/reporters/generators/build.py#L82) is missing from the BuildStartEndStatusGenerator. This causes failures when you try to filter the builders using the tag with GitHubStatusPush and this generator.

```
buildbot_1           | 2021-01-21 13:51:23+0000 [-] Got exception when handling reporter events
buildbot_1           | 	Traceback (most recent call last):
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/twisted/internet/defer.py", line 1475, in gotResult
buildbot_1           | 	    _inlineCallbacks(r, g, status)
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
buildbot_1           | 	    result = result.throwExceptionIntoGenerator(g)
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
buildbot_1           | 	    return g.throw(self.type, self.value, self.tb)
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/buildbot/reporters/base.py", line 183, in _got_event
buildbot_1           | 	    log.err(e, 'Got exception when handling reporter events')
buildbot_1           | 	--- <exception caught here> ---
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/buildbot/reporters/base.py", line 176, in _got_event
buildbot_1           | 	    report = yield g.generate(self.master, self, key, msg)
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
buildbot_1           | 	    result = g.send(result)
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/buildbot/reporters/generators/build.py", line 119, in generate
buildbot_1           | 	    if not self.is_message_needed_by_props(build):
buildbot_1           | 	  File "/usr/lib/python3.8/site-packages/buildbot/reporters/generators/utils.py", line 104, in is_message_needed_by_props
buildbot_1           | 	    if self.tags is not None and not self._matches_any_tag(builder['tags']):
buildbot_1           | 	builtins.AttributeError: 'BuildStartEndStatusGenerator' object has no attribute '_matches_any_tag'

```

This output is from the official docker v2.10

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `master/buildbot/reporters/generators/build.py`
Content:
```
1 # This file is part of Buildbot.  Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2.
4 #
5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
8 # details.
9 #
10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 #
14 # Copyright Buildbot Team Members
15 
16 from twisted.internet import defer
17 from zope.interface import implementer
18 
19 from buildbot import interfaces
20 from buildbot.reporters import utils
21 from buildbot.reporters.message import MessageFormatter
22 from buildbot.reporters.message import MessageFormatterRenderable
23 
24 from .utils import BuildStatusGeneratorMixin
25 
26 
27 @implementer(interfaces.IReportGenerator)
28 class BuildStatusGenerator(BuildStatusGeneratorMixin):
29 
30     wanted_event_keys = [
31         ('builds', None, 'finished'),
32     ]
33 
34     compare_attrs = ['formatter']
35 
36     def __init__(self, mode=("failing", "passing", "warnings"),
37                  tags=None, builders=None, schedulers=None, branches=None,
38                  subject="Buildbot %(result)s in %(title)s on %(builder)s",
39                  add_logs=False, add_patch=False, report_new=False, message_formatter=None,
40                  _want_previous_build=None):
41         super().__init__(mode, tags, builders, schedulers, branches, subject, add_logs, add_patch)
42         self.formatter = message_formatter
43         if self.formatter is None:
44             self.formatter = MessageFormatter()
45 
46         # TODO: private and deprecated, included only to support HttpStatusPushBase
47         self._want_previous_build_override = _want_previous_build
48 
49         if report_new:
50             self.wanted_event_keys = [
51                 ('builds', None, 'finished'),
52                 ('builds', None, 'new'),
53             ]
54 
55     @defer.inlineCallbacks
56     def generate(self, master, reporter, key, build):
57         _, _, event = key
58         is_new = event == 'new'
59         want_previous_build = False if is_new else self._want_previous_build()
60         if self._want_previous_build_override is not None:
61             want_previous_build = self._want_previous_build_override
62 
63         yield utils.getDetailsForBuild(master, build,
64                                        wantProperties=self.formatter.wantProperties,
65                                        wantSteps=self.formatter.wantSteps,
66                                        wantPreviousBuild=want_previous_build,
67                                        wantLogs=self.formatter.wantLogs)
68 
69         if not self.is_message_needed_by_props(build):
70             return None
71         if not is_new and not self.is_message_needed_by_results(build):
72             return None
73 
74         report = yield self.build_message(self.formatter, master, reporter,
75                                           build['builder']['name'], [build],
76                                           build['results'])
77         return report
78 
79     def _want_previous_build(self):
80         return "change" in self.mode or "problem" in self.mode
81 
82     def _matches_any_tag(self, tags):
83         return self.tags and any(tag for tag in self.tags if tag in tags)
84 
85 
86 @implementer(interfaces.IReportGenerator)
87 class BuildStartEndStatusGenerator(BuildStatusGeneratorMixin):
88 
89     wanted_event_keys = [
90         ('builds', None, 'new'),
91         ('builds', None, 'finished'),
92     ]
93 
94     compare_attrs = ['start_formatter', 'end_formatter']
95 
96     def __init__(self, tags=None, builders=None, schedulers=None, branches=None, add_logs=False,
97                  add_patch=False, start_formatter=None, end_formatter=None):
98 
99         super().__init__('all', tags, builders, schedulers, branches, None, add_logs, add_patch)
100         self.start_formatter = start_formatter
101         if self.start_formatter is None:
102             self.start_formatter = MessageFormatterRenderable('Build started.')
103         self.end_formatter = end_formatter
104         if self.end_formatter is None:
105             self.end_formatter = MessageFormatterRenderable('Build done.')
106 
107     @defer.inlineCallbacks
108     def generate(self, master, reporter, key, build):
109         _, _, event = key
110         is_new = event == 'new'
111 
112         formatter = self.start_formatter if is_new else self.end_formatter
113 
114         yield utils.getDetailsForBuild(master, build,
115                                        wantProperties=formatter.wantProperties,
116                                        wantSteps=formatter.wantSteps,
117                                        wantLogs=formatter.wantLogs)
118 
119         if not self.is_message_needed_by_props(build):
120             return None
121 
122         report = yield self.build_message(formatter, master, reporter, build['builder']['name'],
123                                           [build], build['results'])
124         return report
125
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/master/buildbot/reporters/generators/build.py b/master/buildbot/reporters/generators/build.py
--- a/master/buildbot/reporters/generators/build.py
+++ b/master/buildbot/reporters/generators/build.py
@@ -122,3 +122,6 @@
         report = yield self.build_message(formatter, master, reporter, build['builder']['name'],
                                           [build], build['results'])
         return report
+
+    def _matches_any_tag(self, tags):
+        return self.tags and any(tag for tag in self.tags if tag in tags)

{"golden_diff": "diff --git a/master/buildbot/reporters/generators/build.py b/master/buildbot/reporters/generators/build.py\n--- a/master/buildbot/reporters/generators/build.py\n+++ b/master/buildbot/reporters/generators/build.py\n@@ -122,3 +122,6 @@\n         report = yield self.build_message(formatter, master, reporter, build['builder']['name'],\n                                           [build], build['results'])\n         return report\n+\n+    def _matches_any_tag(self, tags):\n+        return self.tags and any(tag for tag in self.tags if tag in tags)\n", "issue": "_matches_any_tag missing from BuildStartEndStatusGenerator\nThe [_matches_any_tag function](https://github.com/buildbot/buildbot/blob/e630745771a8bd03a2084d03ea8e43547d3dff4b/master/buildbot/reporters/generators/build.py#L82) is missing from the BuildStartEndStatusGenerator. This causes failures when you try to filter the builders using the tag with GitHubStatusPush and this generator.\r\n\r\n```\r\nbuildbot_1           | 2021-01-21 13:51:23+0000 [-] Got exception when handling reporter events\r\nbuildbot_1           | \tTraceback (most recent call last):\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/twisted/internet/defer.py\", line 1475, in gotResult\r\nbuildbot_1           | \t    _inlineCallbacks(r, g, status)\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/twisted/internet/defer.py\", line 1416, in _inlineCallbacks\r\nbuildbot_1           | \t    result = result.throwExceptionIntoGenerator(g)\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/twisted/python/failure.py\", line 512, in throwExceptionIntoGenerator\r\nbuildbot_1           | \t    return g.throw(self.type, self.value, self.tb)\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/buildbot/reporters/base.py\", line 183, in _got_event\r\nbuildbot_1           | \t    log.err(e, 'Got exception when handling reporter events')\r\nbuildbot_1           | \t--- <exception caught here> ---\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/buildbot/reporters/base.py\", line 176, in _got_event\r\nbuildbot_1           | \t    report = yield g.generate(self.master, self, key, msg)\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/twisted/internet/defer.py\", line 1418, in _inlineCallbacks\r\nbuildbot_1           | \t    result = g.send(result)\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/buildbot/reporters/generators/build.py\", line 119, in generate\r\nbuildbot_1           | \t    if not self.is_message_needed_by_props(build):\r\nbuildbot_1           | \t  File \"/usr/lib/python3.8/site-packages/buildbot/reporters/generators/utils.py\", line 104, in is_message_needed_by_props\r\nbuildbot_1           | \t    if self.tags is not None and not self._matches_any_tag(builder['tags']):\r\nbuildbot_1           | \tbuiltins.AttributeError: 'BuildStartEndStatusGenerator' object has no attribute '_matches_any_tag'\r\n\r\n```\r\n\r\nThis output is from the official docker v2.10\n", "before_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom twisted.internet import defer\nfrom zope.interface import implementer\n\nfrom buildbot import interfaces\nfrom buildbot.reporters import utils\nfrom buildbot.reporters.message import MessageFormatter\nfrom buildbot.reporters.message import MessageFormatterRenderable\n\nfrom .utils import BuildStatusGeneratorMixin\n\n\n@implementer(interfaces.IReportGenerator)\nclass BuildStatusGenerator(BuildStatusGeneratorMixin):\n\n    wanted_event_keys = [\n        ('builds', None, 'finished'),\n    ]\n\n    compare_attrs = ['formatter']\n\n    def __init__(self, mode=(\"failing\", \"passing\", \"warnings\"),\n                 tags=None, builders=None, schedulers=None, branches=None,\n                 subject=\"Buildbot %(result)s in %(title)s on %(builder)s\",\n                 add_logs=False, add_patch=False, report_new=False, message_formatter=None,\n                 _want_previous_build=None):\n        super().__init__(mode, tags, builders, schedulers, branches, subject, add_logs, add_patch)\n        self.formatter = message_formatter\n        if self.formatter is None:\n            self.formatter = MessageFormatter()\n\n        # TODO: private and deprecated, included only to support HttpStatusPushBase\n        self._want_previous_build_override = _want_previous_build\n\n        if report_new:\n            self.wanted_event_keys = [\n                ('builds', None, 'finished'),\n                ('builds', None, 'new'),\n            ]\n\n    @defer.inlineCallbacks\n    def generate(self, master, reporter, key, build):\n        _, _, event = key\n        is_new = event == 'new'\n        want_previous_build = False if is_new else self._want_previous_build()\n        if self._want_previous_build_override is not None:\n            want_previous_build = self._want_previous_build_override\n\n        yield utils.getDetailsForBuild(master, build,\n                                       wantProperties=self.formatter.wantProperties,\n                                       wantSteps=self.formatter.wantSteps,\n                                       wantPreviousBuild=want_previous_build,\n                                       wantLogs=self.formatter.wantLogs)\n\n        if not self.is_message_needed_by_props(build):\n            return None\n        if not is_new and not self.is_message_needed_by_results(build):\n            return None\n\n        report = yield self.build_message(self.formatter, master, reporter,\n                                          build['builder']['name'], [build],\n                                          build['results'])\n        return report\n\n    def _want_previous_build(self):\n        return \"change\" in self.mode or \"problem\" in self.mode\n\n    def _matches_any_tag(self, tags):\n        return self.tags and any(tag for tag in self.tags if tag in tags)\n\n\n@implementer(interfaces.IReportGenerator)\nclass BuildStartEndStatusGenerator(BuildStatusGeneratorMixin):\n\n    wanted_event_keys = [\n        ('builds', None, 'new'),\n        ('builds', None, 'finished'),\n    ]\n\n    compare_attrs = ['start_formatter', 'end_formatter']\n\n    def __init__(self, tags=None, builders=None, schedulers=None, branches=None, add_logs=False,\n                 add_patch=False, start_formatter=None, end_formatter=None):\n\n        super().__init__('all', tags, builders, schedulers, branches, None, add_logs, add_patch)\n        self.start_formatter = start_formatter\n        if self.start_formatter is None:\n            self.start_formatter = MessageFormatterRenderable('Build started.')\n        self.end_formatter = end_formatter\n        if self.end_formatter is None:\n            self.end_formatter = MessageFormatterRenderable('Build done.')\n\n    @defer.inlineCallbacks\n    def generate(self, master, reporter, key, build):\n        _, _, event = key\n        is_new = event == 'new'\n\n        formatter = self.start_formatter if is_new else self.end_formatter\n\n        yield utils.getDetailsForBuild(master, build,\n                                       wantProperties=formatter.wantProperties,\n                                       wantSteps=formatter.wantSteps,\n                                       wantLogs=formatter.wantLogs)\n\n        if not self.is_message_needed_by_props(build):\n            return None\n\n        report = yield self.build_message(formatter, master, reporter, build['builder']['name'],\n                                          [build], build['results'])\n        return report\n", "path": "master/buildbot/reporters/generators/build.py"}], "after_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom twisted.internet import defer\nfrom zope.interface import implementer\n\nfrom buildbot import interfaces\nfrom buildbot.reporters import utils\nfrom buildbot.reporters.message import MessageFormatter\nfrom buildbot.reporters.message import MessageFormatterRenderable\n\nfrom .utils import BuildStatusGeneratorMixin\n\n\n@implementer(interfaces.IReportGenerator)\nclass BuildStatusGenerator(BuildStatusGeneratorMixin):\n\n    wanted_event_keys = [\n        ('builds', None, 'finished'),\n    ]\n\n    compare_attrs = ['formatter']\n\n    def __init__(self, mode=(\"failing\", \"passing\", \"warnings\"),\n                 tags=None, builders=None, schedulers=None, branches=None,\n                 subject=\"Buildbot %(result)s in %(title)s on %(builder)s\",\n                 add_logs=False, add_patch=False, report_new=False, message_formatter=None,\n                 _want_previous_build=None):\n        super().__init__(mode, tags, builders, schedulers, branches, subject, add_logs, add_patch)\n        self.formatter = message_formatter\n        if self.formatter is None:\n            self.formatter = MessageFormatter()\n\n        # TODO: private and deprecated, included only to support HttpStatusPushBase\n        self._want_previous_build_override = _want_previous_build\n\n        if report_new:\n            self.wanted_event_keys = [\n                ('builds', None, 'finished'),\n                ('builds', None, 'new'),\n            ]\n\n    @defer.inlineCallbacks\n    def generate(self, master, reporter, key, build):\n        _, _, event = key\n        is_new = event == 'new'\n        want_previous_build = False if is_new else self._want_previous_build()\n        if self._want_previous_build_override is not None:\n            want_previous_build = self._want_previous_build_override\n\n        yield utils.getDetailsForBuild(master, build,\n                                       wantProperties=self.formatter.wantProperties,\n                                       wantSteps=self.formatter.wantSteps,\n                                       wantPreviousBuild=want_previous_build,\n                                       wantLogs=self.formatter.wantLogs)\n\n        if not self.is_message_needed_by_props(build):\n            return None\n        if not is_new and not self.is_message_needed_by_results(build):\n            return None\n\n        report = yield self.build_message(self.formatter, master, reporter,\n                                          build['builder']['name'], [build],\n                                          build['results'])\n        return report\n\n    def _want_previous_build(self):\n        return \"change\" in self.mode or \"problem\" in self.mode\n\n    def _matches_any_tag(self, tags):\n        return self.tags and any(tag for tag in self.tags if tag in tags)\n\n\n@implementer(interfaces.IReportGenerator)\nclass BuildStartEndStatusGenerator(BuildStatusGeneratorMixin):\n\n    wanted_event_keys = [\n        ('builds', None, 'new'),\n        ('builds', None, 'finished'),\n    ]\n\n    compare_attrs = ['start_formatter', 'end_formatter']\n\n    def __init__(self, tags=None, builders=None, schedulers=None, branches=None, add_logs=False,\n                 add_patch=False, start_formatter=None, end_formatter=None):\n\n        super().__init__('all', tags, builders, schedulers, branches, None, add_logs, add_patch)\n        self.start_formatter = start_formatter\n        if self.start_formatter is None:\n            self.start_formatter = MessageFormatterRenderable('Build started.')\n        self.end_formatter = end_formatter\n        if self.end_formatter is None:\n            self.end_formatter = MessageFormatterRenderable('Build done.')\n\n    @defer.inlineCallbacks\n    def generate(self, master, reporter, key, build):\n        _, _, event = key\n        is_new = event == 'new'\n\n        formatter = self.start_formatter if is_new else self.end_formatter\n\n        yield utils.getDetailsForBuild(master, build,\n                                       wantProperties=formatter.wantProperties,\n                                       wantSteps=formatter.wantSteps,\n                                       wantLogs=formatter.wantLogs)\n\n        if not self.is_message_needed_by_props(build):\n            return None\n\n        report = yield self.build_message(formatter, master, reporter, build['builder']['name'],\n                                          [build], build['results'])\n        return report\n\n    def _matches_any_tag(self, tags):\n        return self.tags and any(tag for tag in self.tags if tag in tags)\n", "path": "master/buildbot/reporters/generators/build.py"}]}