diff mbox series

[swat-tools] Display the duration of builds

Message ID 20260115-build-duration-v1-1-4ae71508e060@bootlin.com
State New
Headers show
Series [swat-tools] Display the duration of builds | expand

Commit Message

Antonin Godard Jan. 15, 2026, 12:50 p.m. UTC
It can sometimes be useful to know how long a build took, especially for
hanging builds that were canceled after a while.

Add the start timestamp as data stored in the database, and use it with
completed to display the duration. The start timestamp is not displayed,
only the duration.

Signed-off-by: Antonin Godard <antonin.godard@bootlin.com>
---
 README.md               |  1 +
 swattool/database.py    |  4 +++-
 swattool/initmanager.py |  1 +
 swattool/swatbuild.py   | 11 +++++++++++
 4 files changed, 16 insertions(+), 1 deletion(-)


---
base-commit: 8b38da2933736cbb589a9837e3f1940e925fb842
change-id: 20260113-build-duration-5bcf344132dd
diff mbox series

Patch

diff --git a/README.md b/README.md
index 7f44a87..47359e9 100644
--- a/README.md
+++ b/README.md
@@ -237,6 +237,7 @@  Available field names for the `sort` configuration option:
 - `Test` - Test name
 - `Owner` - Assigned owner
 - `Worker` - Worker machine name
+- `Started` - Start timestamp
 - `Completed` - Completion timestamp
 - `SWAT URL` - SWAT interface URL
 - `Autobuilder URL` - Autobuilder URL
diff --git a/swattool/database.py b/swattool/database.py
index 82108dd..d50fbc1 100644
--- a/swattool/database.py
+++ b/swattool/database.py
@@ -28,6 +28,7 @@  SCHEMA = {
         "status",
         "test",
         "worker",
+        "started",
         "completed",
         "collection_id",
         "ab_url",
@@ -280,7 +281,8 @@  class Database:
             cur.execute(
                 "INSERT INTO build VALUES(:build_id, "
                 ":buildbot_build_id, :status, :test, :worker, "
-                ":completed, :collection_id, :ab_url, :parent_id);",
+                ":started, :completed, :collection_id, "
+                ":ab_url, :parent_id);",
                 data,
             )
 
diff --git a/swattool/initmanager.py b/swattool/initmanager.py
index 74932db..526946c 100644
--- a/swattool/initmanager.py
+++ b/swattool/initmanager.py
@@ -326,6 +326,7 @@  class InitManager:
         data["status"] = int(attributes["status"])
         data["test"] = attributes["targetname"]
         data["worker"] = attributes["workername"]
+        data["started"] = attributes["started"]
         data["completed"] = attributes["completed"]
         data["collection_id"] = int(collectionid)
         data["ab_url"] = attributes["url"]
diff --git a/swattool/swatbuild.py b/swattool/swatbuild.py
index edc1ea8..a53fbf5 100644
--- a/swattool/swatbuild.py
+++ b/swattool/swatbuild.py
@@ -102,7 +102,9 @@  class Field(enum.StrEnum):
     TEST = "Test"
     OWNER = "Owner"
     WORKER = "Worker"
+    STARTED = "Started"
     COMPLETED = "Completed"
+    DURATION = "Duration"
     SWAT_URL = "SWAT URL"
     AUTOBUILDER_URL = "Autobuilder URL"
     FAILURES = "Failures"
@@ -123,7 +125,9 @@  class Field(enum.StrEnum):
             cls.TEST,
             cls.OWNER,
             cls.WORKER,
+            cls.STARTED,
             cls.COMPLETED,
+            cls.DURATION,
         ]
 
 
@@ -267,7 +271,9 @@  class Build:
         self.status = Status.from_int(sql_rows[0]["status"])
         self.test = sql_rows[0]["test"]
         self.worker = sql_rows[0]["worker"]
+        self.started = datetime.fromisoformat(sql_rows[0]["started"])
         self.completed = datetime.fromisoformat(sql_rows[0]["completed"])
+        self.duration = self.completed - self.started
         self.swat_url = swat_url
         self.autobuilder_url = sql_rows[0]["ab_url"]
         self.owner = sql_rows[0]["owner"]
@@ -492,8 +498,12 @@  class Build:
         """
         if field == Field.BUILD:
             return self.id
+        if field == Field.STARTED:
+            return self.completed.astimezone().isoformat(timespec="minutes")
         if field == Field.COMPLETED:
             return self.completed.astimezone().isoformat(timespec="minutes")
+        if field == Field.DURATION:
+            return self.duration
         if field == Field.BRANCHES:
             return "&".join(self._get_branches())
         if field.name.lower() in self.__dict__:
@@ -634,6 +644,7 @@  class Build:
             Field.BRANCHES,
             Field.WORKER,
             Field.COMPLETED,
+            Field.DURATION,
             Field.SWAT_URL,
             Field.AUTOBUILDER_URL,
         ]