#5582 Extract jinja message formatter

Merged Povilas Kanapickas p12tic
Coverage Reach
master/buildbot/steps/source/git.py master/buildbot/steps/source/svn.py master/buildbot/steps/source/repo.py master/buildbot/steps/source/cvs.py master/buildbot/steps/source/mercurial.py master/buildbot/steps/source/mtn.py master/buildbot/steps/source/p4.py master/buildbot/steps/source/bzr.py master/buildbot/steps/source/darcs.py master/buildbot/steps/source/base.py master/buildbot/steps/source/gerrit.py master/buildbot/steps/source/gitlab.py master/buildbot/steps/source/github.py master/buildbot/steps/source/__init__.py master/buildbot/steps/package/rpm/mock.py master/buildbot/steps/package/rpm/rpmbuild.py master/buildbot/steps/package/rpm/rpmlint.py master/buildbot/steps/package/rpm/__init__.py master/buildbot/steps/package/deb/pbuilder.py master/buildbot/steps/package/deb/lintian.py master/buildbot/steps/package/util.py master/buildbot/steps/package/__init__.py master/buildbot/steps/shell_oldstyle.py master/buildbot/steps/shell.py master/buildbot/steps/vstudio.py master/buildbot/steps/transfer.py master/buildbot/steps/python.py master/buildbot/steps/python_twisted.py master/buildbot/steps/mtrlogobserver.py master/buildbot/steps/trigger.py master/buildbot/steps/worker.py master/buildbot/steps/master.py master/buildbot/steps/http_oldstyle.py master/buildbot/steps/http.py master/buildbot/steps/master_oldstyle.py master/buildbot/steps/subunit.py master/buildbot/steps/shellsequence.py master/buildbot/steps/cppcheck.py master/buildbot/steps/mswin.py master/buildbot/steps/download_secret_to_worker.py master/buildbot/steps/maxq.py master/buildbot/steps/cmake.py master/buildbot/process/buildstep.py master/buildbot/process/properties.py master/buildbot/process/build.py master/buildbot/process/metrics.py master/buildbot/process/buildrequestdistributor.py master/buildbot/process/builder.py master/buildbot/process/remotecommand.py master/buildbot/process/users/manual.py master/buildbot/process/users/users.py master/buildbot/process/users/manager.py master/buildbot/process/botmaster.py master/buildbot/process/buildrequest.py master/buildbot/process/factory.py master/buildbot/process/workerforbuilder.py master/buildbot/process/log.py master/buildbot/process/logobserver.py master/buildbot/process/remotetransfer.py master/buildbot/process/results.py master/buildbot/process/debug.py master/buildbot/process/cache.py master/buildbot/process/measured_service.py master/buildbot/process/subunitlogobserver.py master/buildbot/process/base.py master/buildbot/reporters/words.py master/buildbot/reporters/telegram.py master/buildbot/reporters/irc.py master/buildbot/reporters/gerrit.py master/buildbot/reporters/generators/utils.py master/buildbot/reporters/generators/worker.py master/buildbot/reporters/generators/build.py master/buildbot/reporters/generators/buildset.py master/buildbot/reporters/bitbucketserver.py master/buildbot/reporters/mail.py master/buildbot/reporters/message.py master/buildbot/reporters/utils.py master/buildbot/reporters/github.py master/buildbot/reporters/gitlab.py master/buildbot/reporters/gerrit_verify_status.py master/buildbot/reporters/notifier.py master/buildbot/reporters/http.py master/buildbot/reporters/hipchat.py master/buildbot/reporters/bitbucket.py master/buildbot/reporters/pushover.py master/buildbot/reporters/pushjet.py master/buildbot/reporters/zulip.py master/buildbot/db/migrate/versions/045_worker_transition.py master/buildbot/db/migrate/versions/046_mysql_innodb_compatibility.py master/buildbot/db/migrate/versions/052_cascading_set_null.py master/buildbot/db/migrate/versions/047_cascading_deletes.py master/buildbot/db/migrate/versions/050_cascading_deletes_all.py master/buildbot/db/migrate/versions/056_add_test_result_tables.py master/buildbot/db/migrate/versions/041_add_N_N_tagsbuilders.py master/buildbot/db/migrate/versions/057_add_build_data_tables.py master/buildbot/db/migrate/versions/042_add_build_properties_table.py master/buildbot/db/migrate/versions/051_add_worker_status.py master/buildbot/db/migrate/versions/044_add_step_hidden.py master/buildbot/db/migrate/versions/053_add_changes_committer.py master/buildbot/db/migrate/versions/048_change_properties_to_text.py master/buildbot/db/migrate/versions/054_add_index_to_steps.py master/buildbot/db/migrate/versions/049_add_schedulers_enabled.py master/buildbot/db/migrate/versions/058_add_build_data_length.py master/buildbot/db/migrate/versions/043_changes_parent.py master/buildbot/db/migrate/versions/040_add_builder_tags.py master/buildbot/db/migrate/versions/055_fix_changes_committer.py master/buildbot/db/logs.py master/buildbot/db/changes.py master/buildbot/db/model.py master/buildbot/db/test_results.py master/buildbot/db/enginestrategy.py master/buildbot/db/workers.py master/buildbot/db/builds.py master/buildbot/db/pool.py master/buildbot/db/buildrequests.py master/buildbot/db/users.py master/buildbot/db/buildsets.py master/buildbot/db/schedulers.py master/buildbot/db/steps.py master/buildbot/db/state.py master/buildbot/db/sourcestamps.py master/buildbot/db/build_data.py master/buildbot/db/base.py master/buildbot/db/connector.py master/buildbot/db/builders.py master/buildbot/db/test_result_sets.py master/buildbot/db/masters.py master/buildbot/db/dbconfig.py master/buildbot/db/changesources.py master/buildbot/db/migrate_utils.py master/buildbot/db/types/json.py master/buildbot/db/tags.py master/buildbot/db/exceptions.py master/buildbot/db/__init__.py master/buildbot/util/__init__.py master/buildbot/util/service.py master/buildbot/util/croniter.py master/buildbot/util/git.py master/buildbot/util/kubeclientservice.py master/buildbot/util/lru.py master/buildbot/util/httpclientservice.py master/buildbot/util/test_result_submitter.py master/buildbot/util/maildir.py master/buildbot/util/poll.py master/buildbot/util/raml.py master/buildbot/util/debounce.py master/buildbot/util/deferwaiter.py master/buildbot/util/subscription.py master/buildbot/util/eventual.py master/buildbot/util/pathmatch.py master/buildbot/util/config.py master/buildbot/util/lineboundaries.py master/buildbot/util/sautils.py master/buildbot/util/identifiers.py master/buildbot/util/protocol.py master/buildbot/util/netstrings.py master/buildbot/util/bbcollections.py master/buildbot/util/misc.py master/buildbot/util/latent.py master/buildbot/util/giturlparse.py master/buildbot/util/codebase.py master/buildbot/util/private_tempdir.py master/buildbot/util/ssl.py master/buildbot/util/logger.py master/buildbot/util/state.py master/buildbot/util/_notifier.py master/buildbot/util/tuplematch.py master/buildbot/www/hooks/github.py master/buildbot/www/hooks/gitlab.py master/buildbot/www/hooks/bitbucketserver.py master/buildbot/www/hooks/bitbucketcloud.py master/buildbot/www/hooks/base.py master/buildbot/www/hooks/poller.py master/buildbot/www/hooks/gitorious.py master/buildbot/www/hooks/bitbucket.py master/buildbot/www/rest.py master/buildbot/www/authz/endpointmatchers.py master/buildbot/www/authz/roles.py master/buildbot/www/authz/authz.py master/buildbot/www/authz/__init__.py master/buildbot/www/oauth2.py master/buildbot/www/service.py master/buildbot/www/auth.py master/buildbot/www/change_hook.py master/buildbot/www/sse.py master/buildbot/www/config.py master/buildbot/www/ldapuserinfo.py master/buildbot/www/ws.py master/buildbot/www/resource.py master/buildbot/www/avatar.py master/buildbot/www/plugin.py master/buildbot/worker/base.py master/buildbot/worker/ec2.py master/buildbot/worker/protocols/pb.py master/buildbot/worker/protocols/null.py master/buildbot/worker/protocols/base.py master/buildbot/worker/latent.py master/buildbot/worker/docker.py master/buildbot/worker/openstack.py master/buildbot/worker/libvirt.py master/buildbot/worker/upcloud.py master/buildbot/worker/manager.py master/buildbot/worker/kubernetes.py master/buildbot/worker/marathon.py master/buildbot/worker/local.py master/buildbot/worker/__init__.py master/buildbot/data/resultspec.py master/buildbot/data/types.py master/buildbot/data/buildrequests.py master/buildbot/data/buildsets.py master/buildbot/data/builds.py master/buildbot/data/changes.py master/buildbot/data/base.py master/buildbot/data/masters.py master/buildbot/data/workers.py master/buildbot/data/steps.py master/buildbot/data/logs.py master/buildbot/data/schedulers.py master/buildbot/data/connector.py master/buildbot/data/builders.py master/buildbot/data/logchunks.py master/buildbot/data/test_result_sets.py master/buildbot/data/forceschedulers.py master/buildbot/data/changesources.py master/buildbot/data/build_data.py master/buildbot/data/properties.py master/buildbot/data/test_results.py master/buildbot/data/sourcestamps.py master/buildbot/data/root.py master/buildbot/data/patches.py master/buildbot/data/exceptions.py master/buildbot/changes/mail.py master/buildbot/changes/gitpoller.py master/buildbot/changes/gerritchangesource.py master/buildbot/changes/svnpoller.py master/buildbot/changes/p4poller.py master/buildbot/changes/hgpoller.py master/buildbot/changes/github.py master/buildbot/changes/changes.py master/buildbot/changes/pb.py master/buildbot/changes/bitbucket.py master/buildbot/changes/base.py master/buildbot/changes/filter.py master/buildbot/changes/manager.py master/buildbot/schedulers/forcesched.py master/buildbot/schedulers/trysched.py master/buildbot/schedulers/timed.py master/buildbot/schedulers/base.py master/buildbot/schedulers/basic.py master/buildbot/schedulers/dependent.py master/buildbot/schedulers/triggerable.py master/buildbot/schedulers/manager.py master/buildbot/schedulers/filter.py master/buildbot/scripts/runner.py master/buildbot/scripts/base.py master/buildbot/scripts/logwatcher.py master/buildbot/scripts/upgrade_master.py master/buildbot/scripts/start.py master/buildbot/scripts/create_master.py master/buildbot/scripts/stop.py master/buildbot/scripts/cleanupdb.py master/buildbot/scripts/reconfig.py master/buildbot/scripts/sendchange.py master/buildbot/scripts/checkconfig.py master/buildbot/scripts/user.py master/buildbot/scripts/tryserver.py master/buildbot/scripts/sample.cfg master/buildbot/scripts/restart.py master/buildbot/scripts/trycmd.py master/buildbot/status/master.py master/buildbot/status/builder.py master/buildbot/status/build.py master/buildbot/status/buildrequest.py master/buildbot/status/worker.py master/buildbot/status/buildset.py master/buildbot/status/base.py master/buildbot/status/event.py master/buildbot/status/__init__.py master/buildbot/status/client.py master/buildbot/clients/tryclient.py master/buildbot/clients/base.py master/buildbot/clients/sendchange.py master/buildbot/clients/usersclient.py master/buildbot/config.py master/buildbot/master.py master/buildbot/statistics/capture.py master/buildbot/statistics/stats_service.py master/buildbot/statistics/storage_backends/influxdb_client.py master/buildbot/statistics/storage_backends/base.py master/buildbot/statistics/__init__.py master/buildbot/machine/generic.py master/buildbot/machine/latent.py master/buildbot/machine/base.py master/buildbot/machine/manager.py master/buildbot/plugins/db.py master/buildbot/plugins/__init__.py master/buildbot/locks.py master/buildbot/mq/wamp.py master/buildbot/mq/simple.py master/buildbot/mq/base.py master/buildbot/mq/connector.py master/buildbot/interfaces.py master/buildbot/secrets/providers/vault.py master/buildbot/secrets/providers/file.py master/buildbot/secrets/providers/passwordstore.py master/buildbot/secrets/providers/base.py master/buildbot/secrets/secret.py master/buildbot/secrets/manager.py master/buildbot/buildbot_net_usage_data.py master/buildbot/pbmanager.py master/buildbot/wamp/connector.py master/buildbot/configurators/janitor.py master/buildbot/configurators/__init__.py master/buildbot/monkeypatches/__init__.py master/buildbot/monkeypatches/servicechecks.py master/buildbot/monkeypatches/decorators.py master/buildbot/pbutil.py master/buildbot/__init__.py master/buildbot/revlinks.py master/buildbot/scheduler.py master/buildbot/warnings.py master/buildbot/errors.py master/buildbot/buildrequest.py worker/buildbot_worker/runprocess.py worker/buildbot_worker/commands/transfer.py worker/buildbot_worker/commands/fs.py worker/buildbot_worker/commands/base.py worker/buildbot_worker/commands/shell.py worker/buildbot_worker/commands/utils.py worker/buildbot_worker/commands/registry.py worker/buildbot_worker/scripts/runner.py worker/buildbot_worker/scripts/create_worker.py worker/buildbot_worker/scripts/logwatcher.py worker/buildbot_worker/scripts/start.py worker/buildbot_worker/scripts/stop.py worker/buildbot_worker/scripts/restart.py worker/buildbot_worker/scripts/base.py worker/buildbot_worker/base.py worker/buildbot_worker/pb.py worker/buildbot_worker/util/__init__.py worker/buildbot_worker/util/_hangcheck.py worker/buildbot_worker/util/_notifier.py worker/buildbot_worker/__init__.py worker/buildbot_worker/pbutil.py worker/buildbot_worker/monkeypatches/testcase_assert.py worker/buildbot_worker/monkeypatches/__init__.py worker/buildbot_worker/compat.py worker/buildbot_worker/null.py worker/buildbot_worker/interfaces.py worker/buildbot_worker/bot.py worker/buildbot_worker/backports/__init__.py worker/buildbot_worker/exceptions.py

No flags found

Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.

e.g., #unittest #integration

#production #enterprise

#frontend #backend

Learn more about Codecov Flags here.


@@ -32,17 +32,166 @@
Loading
32 32
from buildbot.warnings import warn_deprecated
33 33
34 34
35 +
def get_detected_status_text(mode, results, previous_results):
36 +
    if results == FAILURE:
37 +
        if ('change' in mode or 'problem' in mode) and previous_results is not None \
38 +
                and previous_results != FAILURE:
39 +
            text = "new failure"
40 +
        else:
41 +
            text = "failed build"
42 +
    elif results == WARNINGS:
43 +
        text = "problem in the build"
44 +
    elif results == SUCCESS:
45 +
        if "change" in mode and previous_results is not None and previous_results != results:
46 +
            text = "restored build"
47 +
        else:
48 +
            text = "passing build"
49 +
    elif results == EXCEPTION:
50 +
        text = "build exception"
51 +
    else:
52 +
        text = "{} build".format(statusToString(results))
53 +
54 +
    return text
55 +
56 +
57 +
def get_message_summary_text(build, results):
58 +
    t = build['state_string']
59 +
    if t:
60 +
        t = ": " + t
61 +
    else:
62 +
        t = ""
63 +
64 +
    if results == SUCCESS:
65 +
        text = "Build succeeded!"
66 +
    elif results == WARNINGS:
67 +
        text = "Build Had Warnings{}".format(t)
68 +
    elif results == CANCELLED:
69 +
        text = "Build was cancelled"
70 +
    else:
71 +
        text = "BUILD FAILED{}".format(t)
72 +
73 +
    return text
74 +
75 +
76 +
def get_message_source_stamp_text(source_stamps):
77 +
    text = ""
78 +
79 +
    for ss in source_stamps:
80 +
        source = ""
81 +
82 +
        if ss['branch']:
83 +
            source += "[branch {}] ".format(ss['branch'])
84 +
85 +
        if ss['revision']:
86 +
            source += str(ss['revision'])
87 +
        else:
88 +
            source += "HEAD"
89 +
90 +
        if ss['patch'] is not None:
91 +
            source += " (plus patch)"
92 +
93 +
        discriminator = ""
94 +
        if ss['codebase']:
95 +
            discriminator = " '{}'".format(ss['codebase'])
96 +
97 +
        text += "Build Source Stamp{}: {}\n".format(discriminator, source)
98 +
99 +
    return text
100 +
101 +
102 +
def get_projects_text(source_stamps, master):
103 +
    projects = set()
104 +
105 +
    for ss in source_stamps:
106 +
        if ss['project']:
107 +
            projects.add(ss['project'])
108 +
109 +
    if not projects:
110 +
        projects = [master.config.title]
111 +
112 +
    return ', '.join(list(projects))
113 +
114 +
115 +
def create_context_for_build(mode, buildername, build, master, blamelist):
116 +
    buildset = build['buildset']
117 +
    ss_list = buildset['sourcestamps']
118 +
    results = build['results']
119 +
120 +
    if 'prev_build' in build and build['prev_build'] is not None:
121 +
        previous_results = build['prev_build']['results']
122 +
    else:
123 +
        previous_results = None
124 +
125 +
    return {
126 +
        'results': build['results'],
127 +
        'mode': mode,
128 +
        'buildername': buildername,
129 +
        'workername': build['properties'].get('workername', ["<unknown>"])[0],
130 +
        'buildset': buildset,
131 +
        'build': build,
132 +
        'projects': get_projects_text(ss_list, master),
133 +
        'previous_results': previous_results,
134 +
        'status_detected': get_detected_status_text(mode, results, previous_results),
135 +
        'build_url': utils.getURLForBuild(master, build['builder']['builderid'], build['number']),
136 +
        'buildbot_url': master.config.buildbotURL,
137 +
        'blamelist': blamelist,
138 +
        'summary': get_message_summary_text(build, results),
139 +
        'sourcestamps': get_message_source_stamp_text(ss_list)
140 +
    }
141 +
142 +
143 +
def create_context_for_worker(master, worker):
144 +
    return {
145 +
        'buildbot_title': master.config.title,
146 +
        'buildbot_url': master.config.buildbotURL,
147 +
        'worker': worker,
148 +
    }
149 +
150 +
35 151
class MessageFormatterBase(util.ComparableMixin):
36 -
    template_filename = 'default_mail.txt'
152 +
37 153
    template_type = 'plain'
38 154
155 +
    def __init__(self, ctx=None, wantProperties=True, wantSteps=False, wantLogs=False):
156 +
        if ctx is None:
157 +
            ctx = {}
158 +
        self.context = ctx
159 +
        self.wantProperties = wantProperties
160 +
        self.wantSteps = wantSteps
161 +
        self.wantLogs = wantLogs
162 +
163 +
    def buildAdditionalContext(self, master, ctx):
164 +
        pass
165 +
166 +
    @defer.inlineCallbacks
167 +
    def render_message_dict(self, master, context):
168 +
        """Generate a buildbot reporter message and return a dictionary
169 +
           containing the message body, type and subject."""
170 +
        yield self.buildAdditionalContext(master, context)
171 +
        context.update(self.context)
172 +
173 +
        return {
174 +
            'body': self.render_message_body(context),
175 +
            'type': self.template_type,
176 +
            'subject': self.render_message_subject(context)
177 +
        }
178 +
179 +
    def render_message_body(self, context):
180 +
        return None
181 +
182 +
    def render_message_subject(self, context):
183 +
        return None
184 +
185 +
186 +
class MessageFormatterBaseJinja(MessageFormatterBase):
187 +
    template_filename = 'default_mail.txt'
188 +
39 189
    compare_attrs = ['body_template', 'subject_template', 'template_type']
40 190
41 191
    def __init__(self, template_dir=None,
42 192
                 template_filename=None, template=None,
43 193
                 subject_filename=None, subject=None,
44 -
                 template_type=None, ctx=None,
45 -
                 ):
194 +
                 template_type=None, **kwargs):
46 195
        self.body_template = self.getTemplate(template_filename, template_dir, template)
47 196
        self.subject_template = None
48 197
        if subject_filename or subject:
@@ -51,10 +200,7 @@
Loading
51 200
        if template_type is not None:
52 201
            self.template_type = template_type
53 202
54 -
        if ctx is None:
55 -
            ctx = {}
56 -
57 -
        self.ctx = ctx
203 +
        super().__init__(**kwargs)
58 204
59 205
    def getTemplate(self, filename, dirname, content):
60 206
        if content and (filename or dirname):
@@ -78,158 +224,39 @@
Loading
78 224
    def buildAdditionalContext(self, master, ctx):
79 225
        pass
80 226
81 -
    def renderMessage(self, ctx):
82 -
        body = self.body_template.render(ctx)
83 -
        msgdict = {'body': body, 'type': self.template_type}
84 -
        if self.subject_template is not None:
85 -
            msgdict['subject'] = self.subject_template.render(ctx)
86 -
        return msgdict
227 +
    def render_message_body(self, context):
228 +
        return self.body_template.render(context)
87 229
230 +
    def render_message_subject(self, context):
231 +
        if self.subject_template is None:
232 +
            return None
233 +
        return self.subject_template.render(context)
88 234
89 -
class MessageFormatter(MessageFormatterBase):
235 +
236 +
class MessageFormatter(MessageFormatterBaseJinja):
90 237
    template_filename = 'default_mail.txt'
91 -
    template_type = 'plain'
92 238
93 239
    compare_attrs = ['wantProperties', 'wantSteps', 'wantLogs']
94 240
95 -
    def __init__(self, template_dir=None,
96 -
                 template_filename=None, template=None, template_name=None,
97 -
                 subject_filename=None, subject=None,
98 -
                 template_type=None, ctx=None,
99 -
                 wantProperties=True, wantSteps=False, wantLogs=False):
241 +
    def __init__(self, template_name=None, **kwargs):
100 242
101 243
        if template_name is not None:
102 244
            warn_deprecated('0.9.1', "template_name is deprecated, use template_filename")
103 -
            template_filename = template_name
104 -
        super().__init__(template_dir=template_dir,
105 -
                         template_filename=template_filename,
106 -
                         template=template,
107 -
                         subject_filename=subject_filename,
108 -
                         subject=subject,
109 -
                         template_type=template_type, ctx=ctx)
110 -
        self.wantProperties = wantProperties
111 -
        self.wantSteps = wantSteps
112 -
        self.wantLogs = wantLogs
113 -
114 -
    def getDetectedStatus(self, mode, results, previous_results):
115 -
116 -
        if results == FAILURE:
117 -
            if "change" in mode and previous_results is not None and previous_results != results:
118 -
                text = "new failure"
119 -
            elif "problem" in mode and previous_results and previous_results != FAILURE:
120 -
                text = "new failure"
121 -
            else:
122 -
                text = "failed build"
123 -
        elif results == WARNINGS:
124 -
            text = "problem in the build"
125 -
        elif results == SUCCESS:
126 -
            if "change" in mode and previous_results is not None and previous_results != results:
127 -
                text = "restored build"
128 -
            else:
129 -
                text = "passing build"
130 -
        elif results == EXCEPTION:
131 -
            text = "build exception"
132 -
        else:
133 -
            text = "{} build".format(statusToString(results))
134 -
135 -
        return text
136 -
137 -
    def getProjects(self, source_stamps, master):
138 -
        projects = set()
139 -
140 -
        for ss in source_stamps:
141 -
            if ss['project']:
142 -
                projects.add(ss['project'])
143 -
144 -
        if not projects:
145 -
            projects = [master.config.title]
146 -
147 -
        return ', '.join(list(projects))
148 -
149 -
    def messageSourceStamps(self, source_stamps):
150 -
        text = ""
151 -
152 -
        for ss in source_stamps:
153 -
            source = ""
154 -
155 -
            if ss['branch']:
156 -
                source += "[branch {}] ".format(ss['branch'])
157 -
158 -
            if ss['revision']:
159 -
                source += str(ss['revision'])
160 -
            else:
161 -
                source += "HEAD"
162 -
163 -
            if ss['patch'] is not None:
164 -
                source += " (plus patch)"
165 -
166 -
            discriminator = ""
167 -
            if ss['codebase']:
168 -
                discriminator = " '{}'".format(ss['codebase'])
169 -
170 -
            text += "Build Source Stamp{}: {}\n".format(discriminator, source)
171 -
172 -
        return text
173 -
174 -
    def messageSummary(self, build, results):
175 -
        t = build['state_string']
176 -
        if t:
177 -
            t = ": " + t
178 -
        else:
179 -
            t = ""
180 -
181 -
        if results == SUCCESS:
182 -
            text = "Build succeeded!"
183 -
        elif results == WARNINGS:
184 -
            text = "Build Had Warnings{}".format(t)
185 -
        elif results == CANCELLED:
186 -
            text = "Build was cancelled"
187 -
        else:
188 -
            text = "BUILD FAILED{}".format(t)
189 -
190 -
        return text
245 +
            kwargs['template_filename'] = template_name
246 +
        super().__init__(**kwargs)
191 247
192 248
    @defer.inlineCallbacks
193 -
    def formatMessageForBuildResults(self, mode, buildername, buildset, build, master,
194 -
                                     previous_results, blamelist):
195 -
        """Generate a buildbot mail message and return a dictionary
196 -
           containing the message body, type and subject."""
197 -
        ss_list = buildset['sourcestamps']
198 -
        results = build['results']
199 -
200 -
        ctx = dict(results=build['results'],
201 -
                   mode=mode,
202 -
                   buildername=buildername,
203 -
                   workername=build['properties'].get(
204 -
                       'workername', ["<unknown>"])[0],
205 -
                   buildset=buildset,
206 -
                   build=build,
207 -
                   projects=self.getProjects(ss_list, master),
208 -
                   previous_results=previous_results,
209 -
                   status_detected=self.getDetectedStatus(
210 -
                       mode, results, previous_results),
211 -
                   build_url=utils.getURLForBuild(
212 -
                       master, build['builder']['builderid'], build['number']),
213 -
                   buildbot_url=master.config.buildbotURL,
214 -
                   blamelist=blamelist,
215 -
                   summary=self.messageSummary(build, results),
216 -
                   sourcestamps=self.messageSourceStamps(ss_list)
217 -
                   )
218 -
        yield self.buildAdditionalContext(master, ctx)
219 -
        ctx.update(self.ctx)
220 -
        msgdict = self.renderMessage(ctx)
249 +
    def format_message_for_build(self, mode, buildername, build, master, blamelist):
250 +
        ctx = create_context_for_build(mode, buildername, build, master, blamelist)
251 +
        msgdict = yield self.render_message_dict(master, ctx)
221 252
        return msgdict
222 253
223 254
224 -
class MessageFormatterMissingWorker(MessageFormatterBase):
255 +
class MessageFormatterMissingWorker(MessageFormatterBaseJinja):
225 256
    template_filename = 'missing_mail.txt'
226 257
227 258
    @defer.inlineCallbacks
228 259
    def formatMessageForMissingWorker(self, master, worker):
229 -
        ctx = dict(buildbot_title=master.config.title,
230 -
                   buildbot_url=master.config.buildbotURL,
231 -
                   worker=worker)
232 -
        yield self.buildAdditionalContext(master, ctx)
233 -
        ctx.update(self.ctx)
234 -
        msgdict = self.renderMessage(ctx)
260 +
        ctx = create_context_for_worker(master, worker)
261 +
        msgdict = yield self.render_message_dict(master, ctx)
235 262
        return msgdict

@@ -135,6 +135,7 @@
Loading
135 135
136 136
    @defer.inlineCallbacks
137 137
    def build_message(self, master, reporter, name, builds, results):
138 +
        # The given builds must refer to builds from a single buildset
138 139
        patches = []
139 140
        logs = []
140 141
        body = ""
@@ -155,17 +156,13 @@
Loading
155 156
                    build_logs = [log for log in build_logs if self._should_attach_log(log)]
156 157
                logs.extend(build_logs)
157 158
158 -
            if 'prev_build' in build and build['prev_build'] is not None:
159 -
                previous_results = build['prev_build']['results']
160 -
            else:
161 -
                previous_results = None
162 159
            blamelist = yield reporter.getResponsibleUsersForBuild(master, build['buildid'])
163 -
            buildmsg = yield self.formatter.formatMessageForBuildResults(
164 -
                self.mode, name, build['buildset'], build, master, previous_results, blamelist)
160 +
            buildmsg = yield self.formatter.format_message_for_build(self.mode, name, build,
161 +
                                                                     master, blamelist)
165 162
            users.update(set(blamelist))
166 163
            msgtype = buildmsg['type']
167 164
            body += buildmsg['body']
168 -
            if 'subject' in buildmsg:
165 +
            if buildmsg['subject'] is not None:
169 166
                subject = buildmsg['subject']
170 167
171 168
        if subject is None:

@@ -50,9 +50,8 @@
Loading
50 50
51 51
        msg = yield self.formatter.formatMessageForMissingWorker(master, worker)
52 52
        body = msg['body'].encode(ENCODING)
53 -
        if 'subject' in msg:
54 -
            subject = msg['subject']
55 -
        else:
53 +
        subject = msg['subject']
54 +
        if subject is None:
56 55
            subject = "Buildbot worker {name} missing".format(**worker)
57 56
        assert msg['type'] in ('plain', 'html'), \
58 57
            "'{}' message type must be 'plain' or 'html'.".format(msg['type'])

Everything is accounted for!

No changes detected that need to be reviewed.
What changes does Codecov check for?
Lines, not adjusted in diff, that have changed coverage data.
Files that introduced coverage data that had none before.
Files that have missing coverage data that once were tracked.
Files Coverage
master/buildbot 0.03% 90.22%
worker/buildbot_worker 85.09%
Project Totals (352 files) 89.92%
Loading