]> git.ipfire.org Git - pbs.git/blobdiff - src/web/builds.py
builds: Show scratch builds for packages and enhance search
[pbs.git] / src / web / builds.py
index 407608f0022a3018f1312553883dd925f9ea4855..070594cd479cc6c054f3963b4afdeda5f8d302d8 100644 (file)
@@ -68,21 +68,27 @@ class IndexHandler(base.BaseHandler):
                limit  = self.get_argument_int("limit", None) or 25
 
                # Filters
+               name = self.get_argument("name", None)
                user = self.get_argument_user("user", None)
 
                # Fetch the most recent builds
                if user:
-                       builds = self.backend.builds.get_by_user(user, limit=limit, offset=offset)
+                       builds = user.get_builds(name, limit=limit, offset=offset)
                else:
-                       builds = self.backend.builds.get_recent(limit=limit, offset=offset)
+                       builds = self.backend.builds.get_recent(name=name, limit=limit, offset=offset)
 
                # Group builds by date
                builds = misc.group(builds, lambda build: build.created_at.date())
 
-               self.render("builds/index.html", builds=builds, user=user,
+               self.render("builds/index.html", builds=builds, name=name, user=user,
                        limit=limit, offset=offset)
 
 
+class QueueHandler(base.BaseHandler):
+       def get(self):
+               self.render("builds/queue.html", queue=self.backend.jobs.queue)
+
+
 class ShowHandler(base.BaseHandler):
        async def get(self, uuid):
                build = self.backend.builds.get_by_uuid(uuid)
@@ -96,6 +102,42 @@ class ShowHandler(base.BaseHandler):
                        distro=build.distro, bugs=bugs)
 
 
+class CloneHandler(base.BaseHandler):
+       @tornado.web.authenticated
+       def get(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               # Fetch repositories
+               try:
+                       repos = self.current_user.repos[build.distro]
+               except KeyError:
+                       repos = []
+
+               self.render("builds/clone.html", build=build, repos=repos)
+
+       @tornado.web.authenticated
+       async def post(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               # Fetch the repository
+               repo = self.current_user.get_repo(build.distro, self.get_argument("repo"))
+
+               # Clone the build
+               with self.db.transaction():
+                       clone = await self.backend.builds.create(
+                               repo=repo, package=build.pkg, owner=self.current_user,
+                       )
+
+               # Launch all jobs (in the background)
+               self.backend.run_task(self.backend.builds.launch, [clone])
+
+               self.redirect("/builds/%s" % clone.uuid)
+
+
 class DeleteHandler(base.BaseHandler):
        @tornado.web.authenticated
        def get(self, uuid):
@@ -156,7 +198,7 @@ class UnwatchHandler(base.BaseHandler):
 
 class CommentHandler(base.BaseHandler):
        @tornado.web.authenticated
-       def post(self, uuid):
+       async def post(self, uuid):
                build = self.backend.builds.get_by_uuid(uuid)
                if not build:
                        raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
@@ -165,12 +207,135 @@ class CommentHandler(base.BaseHandler):
 
                # Add a new comment to the build
                with self.db.transaction():
-                       build.comment(self.current_user, text)
+                       await build.comment(self.current_user, text)
 
                # Redirect to the build
                self.redirect("/builds/%s" % build.uuid)
 
 
+class BugHandler(base.BaseHandler):
+       @tornado.web.authenticated
+       async def get(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               # Fetch fields
+               fields = await self.backend.bugzilla.fields
+
+               self.render("builds/bug.html", build=build, fields=fields)
+
+       @tornado.web.authenticated
+       async def post(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               # Is the user connected to Bugzilla?
+               if not self.current_user.bugzilla:
+                       raise tornado.web.HTTPError(400, "%s is not connected to Bugzilla" \
+                               % self.current_user)
+
+               kwargs = {
+                       # Summary & Description
+                       "summary"     : self.get_argument("summary"),
+                       "description" : self.get_argument("description", None),
+               } | build.bugzilla_fields
+
+               # Create the bug
+               bug = await self.current_user.bugzilla.create_bug(**kwargs)
+
+               # Send the attachments
+               for job in build.jobs:
+                       if not self.get_argument_bool("attach_log_%s" % job.uuid):
+                               continue
+
+                       # Open the logfile
+                       try:
+                               log = await job.open_log()
+                       except FileNotFoundError as e:
+                               log.warning("Could not open log file for %s" % job)
+                               continue
+
+                       # Attach it to the bug
+                       await bug.attach(summary="Log file for %s" % job, filename="%s.log" % job,
+                               data=log, content_type="text/plain")
+
+               self.render("builds/bug-created.html", build=build, bug=bug)
+
+
+class ReposAddHandler(base.BaseHandler):
+       @tornado.web.authenticated
+       def get(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               # Fetch all available repositories
+               try:
+                       repos = self.current_user.repos[build.distro]
+               except KeyError:
+                       repos = None
+
+               self.render("builds/repos/add.html", build=build, repos=repos)
+
+       @tornado.web.authenticated
+       async def post(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               slug = self.get_argument("repo")
+
+               # Fetch the repository
+               repo = self.current_user.get_repo(build.distro, slug)
+               if not repo:
+                       raise tornado.web.HTTPError(400, "Could not find repository '%s'" % slug)
+
+               # Add the build to the repository
+               with self.db.transaction():
+                       await repo.add_build(build, user=self.current_user)
+
+               self.redirect("/builds/%s" % build.uuid)
+
+
+class ReposRemoveHandler(base.BaseHandler):
+       @tornado.web.authenticated
+       def get(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               # Raise error when the build is in to repositories
+               if not build.repos:
+                       raise tornado.web.HTTPError(400)
+
+               self.render("builds/repos/remove.html", build=build)
+
+       @tornado.web.authenticated
+       async def post(self, uuid):
+               build = self.backend.builds.get_by_uuid(uuid)
+               if not build:
+                       raise tornado.web.HTTPError(404, "Could not find build %s" % uuid)
+
+               # Fetch all selected repos
+               repos = self.get_arguments("repo")
+
+               # Raise an error if nothing has been selected
+               if not repos:
+                       raise tornado.web.HTTPError(400, "No repositories selected")
+
+               # Find all selected repositories
+               repos = [repo for repo in build.repos if repo.slug in repos]
+
+               # Remove build from all repositories
+               with self.db.transaction():
+                       for repo in repos:
+                               await repo.remove_build(build, user=self.current_user)
+
+               self.redirect("/builds/%s" % build.uuid)
+
+
 class GroupShowHandler(base.BaseHandler):
        def get(self, uuid):
                group = self.backend.builds.groups.get_by_uuid(uuid)
@@ -181,8 +346,15 @@ class GroupShowHandler(base.BaseHandler):
 
 
 class ListModule(ui_modules.UIModule):
-       def render(self, builds):
-               return self.render_string("builds/modules/list.html", builds=builds)
+       def render(self, builds, limit=None, more_url=None):
+               rest = None
+
+               # Limit builds
+               if limit:
+                       builds, rest = builds[:limit], builds[limit:]
+
+               return self.render_string("builds/modules/list.html", builds=builds,
+                       rest=rest, more_url=more_url)
 
 
 class GroupListModule(ui_modules.UIModule):