]> git.ipfire.org Git - pbs.git/commitdiff
events: Build scaffolding to read events
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 5 Jul 2022 16:33:13 +0000 (16:33 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 5 Jul 2022 16:33:13 +0000 (16:33 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/buildservice/__init__.py
src/buildservice/builds.py
src/buildservice/events.py [new file with mode: 0644]

index 4472f3e28d0b582bf93411f2cfa04128c0f9f0b6..787e3f8e8ae10f30c577565a1e79d1a9430e0fe1 100644 (file)
@@ -86,6 +86,7 @@ buildservice_PYTHON = \
        src/buildservice/database.py \
        src/buildservice/decorators.py \
        src/buildservice/distribution.py \
+       src/buildservice/events.py \
        src/buildservice/git.py \
        src/buildservice/jobqueue.py \
        src/buildservice/jobs.py \
index 48ddb030f4ac708cb9921f10217a6f5fd8eda015..35cd4d239abcd05412f6cd2ef36530ff49fa2301 100644 (file)
@@ -14,6 +14,7 @@ from . import builds
 from . import cache
 from . import database
 from . import distribution
+from . import events
 from . import jobqueue
 from . import jobs
 from . import keys
@@ -54,6 +55,7 @@ class Backend(object):
                self.jobs        = jobs.Jobs(self)
                self.builders    = builders.Builders(self)
                self.distros     = distribution.Distributions(self)
+               self.events      = events.Events(self)
                self.jobqueue    = jobqueue.JobQueue(self)
                self.keys        = keys.Keys(self)
                self.messages    = messages.Messages(self)
index a2b3e7a40179e74b0332a9b078c707fc62d48487..b9eb58c8d0176c9124e2bf88ea45ebbd475dad27 100644 (file)
@@ -597,15 +597,16 @@ class Build(base.DataObject):
 
        ## Logging stuff
 
-       def get_log(self, limit=None):
+       @property
+       def events(self):
                res = self.db.query("""
                        WITH events AS (
                                -- Build creation times
                                SELECT
-                                       builds.id AS build_id,
+                                       builds.id AS build,
                                        builds.created_at AS t,
-                                       'created'::text AS event,
-                                       builds.owner_id AS by_user_id
+                                       'build-created'::text AS type,
+                                       builds.owner_id AS by_user
                                FROM
                                        builds
 
@@ -613,14 +614,14 @@ class Build(base.DataObject):
                                UNION ALL
 
                                SELECT
-                                       builds.id AS build_id,
+                                       builds.id AS build,
                                        builds.finished_at AS t,
                                        CASE
                                                WHEN builds.failed IS TRUE
-                                               THEN 'failed'::text
-                                               ELSE 'finished'::text
-                                       END AS event,
-                                       NULL AS by_user_id
+                                               THEN 'build-failed'::text
+                                               ELSE 'build-finished'::text
+                                       END AS type,
+                                       NULL AS by_user
                                FROM
                                        builds
                                WHERE
@@ -633,13 +634,13 @@ class Build(base.DataObject):
                        FROM
                                events
                        WHERE
-                               build_id = %s
+                               build = %s
                        ORDER BY
                                t DESC""",
                        self.id,
                )
 
-               return res # XXX automatically expand all those IDs
+               return self.backend.events.expand(res)
 
        def get_log(self, comments=True, repo=True, limit=None):
                entries = []
diff --git a/src/buildservice/events.py b/src/buildservice/events.py
new file mode 100644 (file)
index 0000000..16bea54
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/python3
+###############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2022 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+import logging
+
+from . import base
+
+log = logging.getLogger("pakfire.events")
+
+from .decorators import *
+
+class Events(base.Object):
+       @lazy_property
+       def map(self):
+               return {
+                       # Builds
+                       "build"   : self.backend.builds.get_by_id,
+
+                       # Users
+                       "by_user" : self.backend.users.get_by_id,
+               }
+
+       def expand(self, events):
+               """
+                       Expands any log events
+               """
+               cache = {}
+
+               for event in events:
+                       # Replace any mappable attributes
+                       for attribute in event:
+                               # Check if we are dealing with a mapped attribute
+                               try:
+                                       expand = self.map[attribute]
+                               except KeyError as e:
+                                       log.debug("Could not map attribute '%s'" % attribute)
+                                       continue
+
+                               # Fetch attribute value
+                               key = event[attribute]
+
+                               # Skip everything that is None
+                               if key is None:
+                                       continue
+
+                               # Lookup the cache
+                               try:
+                                       value = cache[attribute][key]
+
+                               # Call the expand function on cache miss
+                               except KeyError:
+                                       value = expand(key)
+
+                                       # Store the expanded value
+                                       try:
+                                               cache[attribute][key] = value
+                                       except KeyError:
+                                               cache[attribute] = { key : value }
+
+                               # Replace original value with the expanded one
+                               event[attribute] = value
+
+                       yield Event(self.backend, event)
+
+
+class Event(base.Object):
+       def init(self, data):
+               self.data = data
+
+               # Read some useful attributes
+               try:
+                       self.type = self.data.type
+                       self.t    = self.data.t
+               except AttributeError as e:
+                       log.error("Could not read event: %s" % e)
+                       raise e
+
+       def __repr__(self):
+               return "<%s %s>" % (self.__class__.__name__, self.type)