summaryrefslogtreecommitdiff
path: root/zuul/driver/sql/sqlreporter.py
blob: c018a01f3e7b3a28d8fdad3622bed8699205e2bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# Copyright 2015 Rackspace Australia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import datetime
import json
import logging
import time
import voluptuous as v

from zuul.lib.logutil import get_annotated_logger
from zuul.reporter import BaseReporter
from zuul.lib.artifacts import get_artifacts_from_result_data


class SQLReporter(BaseReporter):
    """Sends off reports to a database."""

    name = 'sql'
    log = logging.getLogger("zuul.SQLReporter")

    def report(self, item):
        """Create an entry into a database."""
        log = get_annotated_logger(self.log, item.event)

        if not self.connection.tables_established:
            log.warning("SQL reporter (%s) is disabled ", self)
            return

        with self.connection.getSession() as db:
            db_buildset = db.createBuildSet(
                uuid=item.current_build_set.uuid,
                tenant=item.pipeline.tenant.name,
                pipeline=item.pipeline.name,
                project=item.change.project.name,
                change=getattr(item.change, 'number', None),
                patchset=getattr(item.change, 'patchset', None),
                ref=getattr(item.change, 'ref', ''),
                oldrev=getattr(item.change, 'oldrev', ''),
                newrev=getattr(item.change, 'newrev', ''),
                branch=getattr(item.change, 'branch', ''),
                zuul_ref=item.current_build_set.ref,
                ref_url=item.change.url,
                result=item.current_build_set.result,
                message=self._formatItemReport(item, with_jobs=False),
            )
            for job in item.getJobs():
                build = item.current_build_set.getBuild(job.name)
                if not build:
                    # build hasn't begun. The sql reporter can only send back
                    # stats about builds. It doesn't understand how to store
                    # information about the change.
                    continue
                # Ensure end_time is defined
                if not build.end_time:
                    build.end_time = time.time()

                (result, url) = item.formatJobResult(job)
                log_url = build.result_data.get('zuul', {}).get('log_url')
                if log_url and log_url[-1] != '/':
                    log_url = log_url + '/'
                start = end = None
                if build.start_time:
                    start = datetime.datetime.fromtimestamp(
                        build.start_time,
                        tz=datetime.timezone.utc)
                if build.end_time:
                    end = datetime.datetime.fromtimestamp(
                        build.end_time,
                        tz=datetime.timezone.utc)

                db_build = db_buildset.createBuild(
                    uuid=build.uuid,
                    job_name=build.job.name,
                    result=result,
                    start_time=start,
                    end_time=end,
                    voting=build.job.voting,
                    log_url=log_url,
                    node_name=build.node_name,
                )

                for provides in job.provides:
                    db_build.createProvides(name=provides)

                for artifact in get_artifacts_from_result_data(
                    build.result_data,
                    logger=self.log):
                    if 'metadata' in artifact:
                        artifact['metadata'] = json.dumps(artifact['metadata'])
                    db_build.createArtifact(**artifact)


def getSchema():
    sql_reporter = v.Schema(None)
    return sql_reporter