]> git.ipfire.org Git - pbs.git/commitdiff
jobs: Add controls to retry a job
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 29 Apr 2023 14:02:34 +0000 (14:02 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 29 Apr 2023 15:06:20 +0000 (15:06 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/buildservice/jobs.py
src/templates/jobs/modules/list.html
src/templates/jobs/retry.html [new file with mode: 0644]
src/web/__init__.py
src/web/jobs.py

index 2a988bb5b16a054b14c2c007a0995d7be9d60ce9..fcb7ea11fe460ac56d35b3215868f4fb99f8798e 100644 (file)
@@ -220,7 +220,8 @@ templates_events_modulesdir = $(templates_eventsdir)/modules
 
 dist_templates_jobs_DATA = \
        src/templates/jobs/abort.html \
-       src/templates/jobs/log-stream.html
+       src/templates/jobs/log-stream.html \
+       src/templates/jobs/retry.html
 
 templates_jobsdir = $(templatesdir)/jobs
 
index bf1ace63bbbc2d2bd8814936857fb513f745b8bb..9a5e058fa774d2f3bc0139608eb5b232fea41500 100644 (file)
@@ -570,6 +570,33 @@ class Job(base.DataObject):
 
                return job
 
+       # Retry
+
+       def can_be_retried(self):
+               # The job must have failed
+               if not self.has_failed():
+                       return False
+
+               # The job cannot have been superseeded by another job
+               if self.superseeded_by:
+                       return False
+
+               return True
+
+       async def retry(self, user=None):
+               """
+                       Creates a copy of a job
+               """
+               # Check
+               if not self.can_be_retried():
+                       raise RuntimeError("Job %s cannot be retried" % self)
+
+               # Clone the job
+               job = self.clone()
+
+               # Schedule a dependency check
+               self.backend.run_task(self.depcheck)
+
        # Log
 
        def has_log(self):
index 6bf9a6be1f221e53f463eda551d05c06620d4961..7b88df057f69e26b78cb744b6628dc94e886fc2f 100644 (file)
                                                        {{ _("View Log") }}
                                                </a>
 
-                                               {% if job.is_running() %}
+                                               {% if job.can_be_retried() %}
+                                                       <a class="button is-warning" href="/jobs/{{ job.uuid }}/retry">
+                                                               {{ _("Retry") }}
+                                                       </a>
+                                               {% elif job.is_running() %}
                                                        <a class="button is-dark" href="/jobs/{{ job.uuid }}/abort">
                                                                {{ _("Abort") }}
                                                        </a>
diff --git a/src/templates/jobs/retry.html b/src/templates/jobs/retry.html
new file mode 100644 (file)
index 0000000..a0406f8
--- /dev/null
@@ -0,0 +1,41 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Retry Job %s") % job }}{% end block %}
+
+{% block container %}
+       <nav class="breadcrumb" aria-label="breadcrumbs">
+               <ul>
+                       <li>
+                               <a href="/builds">{{ _("Builds") }}</a>
+                       </li>
+                       <li>
+                               <a href="/builds/{{ job.build.uuid }}">{{ job.build }}</a>
+                       </li>
+                       <li>
+                               <a href="#" disabled>{{ job.arch }}</a>
+                       </li>
+                       <li class="is-active">
+                               <a href="#" aria-current="page">{{ _("Retry") }}</a>
+                       </li>
+               </ul>
+       </nav>
+
+       <div class="columns is-centered">
+               <div class="column is-6">
+                       <form method="POST" action="">
+                               <div class="box">
+                                       {% raw xsrf_form_html() %}
+
+                                       <p class="title is-4">{{ _("Retry Job") }}</p>
+                                       <p class="subtitle is-5">
+                                               {{ _("Do you want to retry building %s?") % job }}
+                                       </p>
+
+                                       <button class="button is-fullwidth is-warning">
+                                               {{ _("Retry") }}
+                                       </button>
+                               </div>
+                       </form>
+               </div>
+       </div>
+{% end block %}
index 9e3e6499d0c1520f97d1f7554861db423bfc1b97..0e48b99abdc523284d2401ea1966c248888d2f82 100644 (file)
@@ -138,6 +138,7 @@ class Application(tornado.web.Application):
                        # Jobs
                        (r"/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/abort", jobs.AbortHandler),
                        (r"/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/log", jobs.LogHandler),
+                       (r"/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/retry", jobs.RetryHandler),
                        (r"/job/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/buildroot", jobs.JobBuildrootHandler),
                        (r"/api/v1/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})",
                                jobs.APIv1DetailHandler),
index 075ef673daeaaa767333bf51731fd5a8349d2a8a..5dece72113798ff88d388d671da32ad27ce7be46 100644 (file)
@@ -206,6 +206,32 @@ class AbortHandler(base.BaseHandler):
                self.redirect("/builds/%s" % job.build.uuid)
 
 
+class RetryHandler(base.BaseHandler):
+       @tornado.web.authenticated
+       def get(self, uuid):
+               job = self.backend.jobs.get_by_uuid(uuid)
+               if not job:
+                       raise tornado.web.HTTPError(404, "Could not find job %s" % uuid)
+
+               # Check for permissions
+               if not job.has_perm(self.current_user):
+                       raise tornado.web.HTTPError(403)
+
+               self.render("jobs/retry.html", job=job)
+
+       @tornado.web.authenticated
+       async def post(self, uuid):
+               job = self.backend.jobs.get_by_uuid(uuid)
+               if not job:
+                       raise tornado.web.HTTPError(404, "Could not find job %s" % uuid)
+
+               with self.db.transaction():
+                       await job.retry(self.current_user)
+
+               # Redirect back to the build page
+               self.redirect("/builds/%s" % job.build.uuid)
+
+
 class ListModule(ui_modules.UIModule):
        def render(self, jobs, show_arch_only=False, show_packages=False):
                return self.render_string("jobs/modules/list.html", jobs=jobs,