Skip to content

Commit

Permalink
feat: provide log-detective explain integration for failed builds
Browse files Browse the repository at this point in the history
  • Loading branch information
nikromen committed Jan 28, 2025
1 parent 348ef2f commit d51316c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 16 deletions.
12 changes: 12 additions & 0 deletions frontend/coprs_frontend/coprs/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,3 +800,15 @@ def being_server_admin(user, copr):
return False

return True

def get_log_with_failed_information(build):
"""
Get the log from the build, which contains the information about fail.
"""
suspicious_logs = ["builder-live.log", "backend.log", "import.log"]
for log in suspicious_logs:
log_path = build.log_variant(log)
if log_path is not None:
return log_path

return None
36 changes: 23 additions & 13 deletions frontend/coprs_frontend/coprs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1225,7 +1225,7 @@ def result_dir_url(self):
path = os.path.normpath(os.path.join(*path_parts))
return urljoin(app.config["BACKEND_BASE_URL"], path)

def _compressed_log_variant(self, basename, states_raw_log):
def log_variant(self, basename, states_raw_log):

Check warning

Code scanning / vcs-diff-lint

Build.log_variant: Missing function or method docstring Warning

Build.log_variant: Missing function or method docstring
if not self.result_dir:
return None
if self.source_state in states_raw_log:
Expand All @@ -1240,7 +1240,7 @@ def source_live_log_url(self):
"""
Full URL to the builder-live.log(.gz) for the source (SRPM) build.
"""
return self._compressed_log_variant(
return self.log_variant(
"builder-live.log", ["running"]
)

Expand All @@ -1249,7 +1249,7 @@ def source_backend_log_url(self):
"""
Full URL to the builder-live.log(.gz) for the source (SRPM) build.
"""
return self._compressed_log_variant(
return self.log_variant(
"backend.log", ["starting", "running"]
)

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

def _compressed_log_variant(self, basename, states_raw_log):
def log_variant(self, basename, states_raw_log, compressed):
"""
Return the full URL to the log file with the given basename.
Args:
basename: the basename of the log file (e.g. "builder-live.log")
states_raw_log: list of states in which the log file is not compressed
(e.g. ["running", "starting"])
compressed: whether the log file is compressed (.gz suffix)
Returns:
the full URL to the log file or None if the log file does not exist
"""
if not self.result_dir:
return None
if not self.build.package:
# no source build done, yet
return None
if self.state in states_raw_log:
return os.path.join(self.result_dir_url,
basename)
return os.path.join(self.result_dir_url, basename)
if self.state in ["failed", "succeeded", "canceled", "importing"]:
return os.path.join(self.result_dir_url,
basename + ".gz")
compressed_suffix = ".gz" if compressed else ""
return os.path.join(self.result_dir_url, f"{basename}{compressed_suffix}")

return None

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

@property
def rpm_backend_log_url(self):
""" Link to backend.log[.gz] related to RPM build. """
return self._compressed_log_variant("backend.log",
["starting", "running"])
return self.log_variant("backend.log", ["starting", "running"], True)

@property
def fedora_review(self):
Expand All @@ -2135,8 +2146,7 @@ def rpm_fedora_review_url(self):
"""
if not self.fedora_review:
return None
return self._compressed_log_variant("fedora-review/review.txt",
StatusEnum.vals.keys())
return self.log_variant("fedora-review/review.txt", StatusEnum.vals.keys(), False)

@property
def rpm_live_logs(self):
Expand Down
7 changes: 6 additions & 1 deletion frontend/coprs_frontend/coprs/templates/_helpers.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
{% endif %}
{% endmacro %}

{% macro build_state_text(state, reason=None) %}
{% macro build_state_text(state, reason=None, failed_build_log_url=None) %}
<span class="build-{{ state }}"
title="{{ reason or state | build_state_description }}">
{% if state == "importing" %}
Expand All @@ -157,6 +157,11 @@
<span class="pficon pficon-ok"></span> {{ state }}
{% elif state == "failed" %}
<span class="pficon pficon-error-circle-o"></span> {{ state }}
{% if failed_build_log_url and config.LOG_DETECTIVE_BUTTON %}
<a href="{{ failed_build_log_url }}" class="btn btn-xs btn-default">
<span class="pficon pficon-info"></span> Explain with Log Detective AI
</a>
{% endif %}
{% elif state == "canceled" %}
<span class="pficon pficon-close"></span> {{ state }}
{% elif state == "waiting" %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ <h3 class="panel-title">Results</h3>
{% endfor %}
</td>
<td>
{{ build_state_text(chroot.state, chroot.status_reason) }}
{{ build_state_text(chroot.state, chroot.status_reason, failed_build_log_url) }}
</td>
</tr>
{% endfor %}
Expand Down
11 changes: 10 additions & 1 deletion frontend/coprs_frontend/coprs/views/coprs_ns/coprs_builds.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,16 @@ def copr_build(copr, build_id):

def render_copr_build(build_id, copr):
build = ComplexLogic.get_build(build_id)
return render_template("coprs/detail/build.html", build=build, copr=copr)
failed_build_log_url = None
if build.status == StatusEnum("failed"):
failed_build_log_url = helpers.get_log_with_failed_information(build)

return render_template(
"coprs/detail/build.html",
build=build,
copr=copr,
failed_build_log_url=failed_build_log_url,
)


################################ Build table ################################
Expand Down

0 comments on commit d51316c

Please sign in to comment.