Skip to content

Commit d51316c

Browse files
committed
feat: provide log-detective explain integration for failed builds
1 parent 348ef2f commit d51316c

File tree

5 files changed

+52
-16
lines changed

5 files changed

+52
-16
lines changed

frontend/coprs_frontend/coprs/helpers.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,3 +800,15 @@ def being_server_admin(user, copr):
800800
return False
801801

802802
return True
803+
804+
def get_log_with_failed_information(build):
805+
"""
806+
Get the log from the build, which contains the information about fail.
807+
"""
808+
suspicious_logs = ["builder-live.log", "backend.log", "import.log"]
809+
for log in suspicious_logs:
810+
log_path = build.log_variant(log)
811+
if log_path is not None:
812+
return log_path
813+
814+
return None

frontend/coprs_frontend/coprs/models.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ def result_dir_url(self):
12251225
path = os.path.normpath(os.path.join(*path_parts))
12261226
return urljoin(app.config["BACKEND_BASE_URL"], path)
12271227

1228-
def _compressed_log_variant(self, basename, states_raw_log):
1228+
def log_variant(self, basename, states_raw_log):
12291229
if not self.result_dir:
12301230
return None
12311231
if self.source_state in states_raw_log:
@@ -1240,7 +1240,7 @@ def source_live_log_url(self):
12401240
"""
12411241
Full URL to the builder-live.log(.gz) for the source (SRPM) build.
12421242
"""
1243-
return self._compressed_log_variant(
1243+
return self.log_variant(
12441244
"builder-live.log", ["running"]
12451245
)
12461246

@@ -1249,7 +1249,7 @@ def source_backend_log_url(self):
12491249
"""
12501250
Full URL to the builder-live.log(.gz) for the source (SRPM) build.
12511251
"""
1252-
return self._compressed_log_variant(
1252+
return self.log_variant(
12531253
"backend.log", ["starting", "running"]
12541254
)
12551255

@@ -2090,30 +2090,41 @@ def result_dir_url(self):
20902090
return urljoin(app.config["BACKEND_BASE_URL"], os.path.join(
20912091
"results", self.build.copr_dir.full_name, self.name, self.result_dir, ""))
20922092

2093-
def _compressed_log_variant(self, basename, states_raw_log):
2093+
def log_variant(self, basename, states_raw_log, compressed):
2094+
"""
2095+
Return the full URL to the log file with the given basename.
2096+
2097+
Args:
2098+
basename: the basename of the log file (e.g. "builder-live.log")
2099+
states_raw_log: list of states in which the log file is not compressed
2100+
(e.g. ["running", "starting"])
2101+
compressed: whether the log file is compressed (.gz suffix)
2102+
2103+
Returns:
2104+
the full URL to the log file or None if the log file does not exist
2105+
"""
20942106
if not self.result_dir:
20952107
return None
20962108
if not self.build.package:
20972109
# no source build done, yet
20982110
return None
20992111
if self.state in states_raw_log:
2100-
return os.path.join(self.result_dir_url,
2101-
basename)
2112+
return os.path.join(self.result_dir_url, basename)
21022113
if self.state in ["failed", "succeeded", "canceled", "importing"]:
2103-
return os.path.join(self.result_dir_url,
2104-
basename + ".gz")
2114+
compressed_suffix = ".gz" if compressed else ""
2115+
return os.path.join(self.result_dir_url, f"{basename}{compressed_suffix}")
2116+
21052117
return None
21062118

21072119
@property
21082120
def rpm_live_log_url(self):
21092121
""" Full URL to the builder-live.log.gz for RPM build. """
2110-
return self._compressed_log_variant("builder-live.log", ["running"])
2122+
return self.log_variant("builder-live.log", ["running"], True)
21112123

21122124
@property
21132125
def rpm_backend_log_url(self):
21142126
""" Link to backend.log[.gz] related to RPM build. """
2115-
return self._compressed_log_variant("backend.log",
2116-
["starting", "running"])
2127+
return self.log_variant("backend.log", ["starting", "running"], True)
21172128

21182129
@property
21192130
def fedora_review(self):
@@ -2135,8 +2146,7 @@ def rpm_fedora_review_url(self):
21352146
"""
21362147
if not self.fedora_review:
21372148
return None
2138-
return self._compressed_log_variant("fedora-review/review.txt",
2139-
StatusEnum.vals.keys())
2149+
return self.log_variant("fedora-review/review.txt", StatusEnum.vals.keys(), False)
21402150

21412151
@property
21422152
def rpm_live_logs(self):

frontend/coprs_frontend/coprs/templates/_helpers.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@
138138
{% endif %}
139139
{% endmacro %}
140140

141-
{% macro build_state_text(state, reason=None) %}
141+
{% macro build_state_text(state, reason=None, failed_build_log_url=None) %}
142142
<span class="build-{{ state }}"
143143
title="{{ reason or state | build_state_description }}">
144144
{% if state == "importing" %}
@@ -157,6 +157,11 @@
157157
<span class="pficon pficon-ok"></span> {{ state }}
158158
{% elif state == "failed" %}
159159
<span class="pficon pficon-error-circle-o"></span> {{ state }}
160+
{% if failed_build_log_url and config.LOG_DETECTIVE_BUTTON %}
161+
<a href="{{ failed_build_log_url }}" class="btn btn-xs btn-default">
162+
<span class="pficon pficon-info"></span> Explain with Log Detective AI
163+
</a>
164+
{% endif %}
160165
{% elif state == "canceled" %}
161166
<span class="pficon pficon-close"></span> {{ state }}
162167
{% elif state == "waiting" %}

frontend/coprs_frontend/coprs/templates/coprs/detail/build.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ <h3 class="panel-title">Results</h3>
283283
{% endfor %}
284284
</td>
285285
<td>
286-
{{ build_state_text(chroot.state, chroot.status_reason) }}
286+
{{ build_state_text(chroot.state, chroot.status_reason, failed_build_log_url) }}
287287
</td>
288288
</tr>
289289
{% endfor %}

frontend/coprs_frontend/coprs/views/coprs_ns/coprs_builds.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,16 @@ def copr_build(copr, build_id):
5454

5555
def render_copr_build(build_id, copr):
5656
build = ComplexLogic.get_build(build_id)
57-
return render_template("coprs/detail/build.html", build=build, copr=copr)
57+
failed_build_log_url = None
58+
if build.status == StatusEnum("failed"):
59+
failed_build_log_url = helpers.get_log_with_failed_information(build)
60+
61+
return render_template(
62+
"coprs/detail/build.html",
63+
build=build,
64+
copr=copr,
65+
failed_build_log_url=failed_build_log_url,
66+
)
5867

5968

6069
################################ Build table ################################

0 commit comments

Comments
 (0)