From: Michael Tremer Date: Sat, 29 Apr 2023 14:02:34 +0000 (+0000) Subject: jobs: Add controls to retry a job X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f66d485f7fb137e44a28ccd61a7b5ca72fc9cabb;p=pbs.git jobs: Add controls to retry a job Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 2a988bb5..fcb7ea11 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/src/buildservice/jobs.py b/src/buildservice/jobs.py index bf1ace63..9a5e058f 100644 --- a/src/buildservice/jobs.py +++ b/src/buildservice/jobs.py @@ -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): diff --git a/src/templates/jobs/modules/list.html b/src/templates/jobs/modules/list.html index 6bf9a6be..7b88df05 100644 --- a/src/templates/jobs/modules/list.html +++ b/src/templates/jobs/modules/list.html @@ -94,7 +94,11 @@ {{ _("View Log") }} - {% if job.is_running() %} + {% if job.can_be_retried() %} + + {{ _("Retry") }} + + {% elif job.is_running() %} {{ _("Abort") }} diff --git a/src/templates/jobs/retry.html b/src/templates/jobs/retry.html new file mode 100644 index 00000000..a0406f86 --- /dev/null +++ b/src/templates/jobs/retry.html @@ -0,0 +1,41 @@ +{% extends "../base.html" %} + +{% block title %}{{ _("Retry Job %s") % job }}{% end block %} + +{% block container %} + + +
+
+
+
+ {% raw xsrf_form_html() %} + +

{{ _("Retry Job") }}

+

+ {{ _("Do you want to retry building %s?") % job }} +

+ + +
+
+
+
+{% end block %} diff --git a/src/web/__init__.py b/src/web/__init__.py index 9e3e6499..0e48b99a 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -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), diff --git a/src/web/jobs.py b/src/web/jobs.py index 075ef673..5dece721 100644 --- a/src/web/jobs.py +++ b/src/web/jobs.py @@ -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,