]> git.ipfire.org Git - pbs.git/commitdiff
builds: Fix cloning a build
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 24 Jan 2025 10:56:08 +0000 (10:56 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 24 Jan 2025 10:56:08 +0000 (10:56 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/builds.py
src/buildservice/users.py
src/templates/builds/clone.html
src/web/base.py
src/web/builds.py

index 562dd96e315d1c4b4de1a4c99e7b43d04427e229..67eec6f7bf45f39cc273bbe9d3297e9cc087edf7 100644 (file)
@@ -270,7 +270,7 @@ class Builds(base.Object):
                        build_repo          = repo,
                        pkg                 = package,
                        owner               = owner,
-                       group               = group,
+                       build_group_id      = group.id if group else None,
                        test                = test,
                        disable_test_builds = disable_test_builds,
                )
@@ -1182,6 +1182,28 @@ class Build(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
                return await self.db.fetch_one(stmt)
 
+       # Clone!
+
+       async def clone(self, owner, repo=None):
+               """
+                       Creates a clone of this build
+               """
+               # Create a new build from the same package
+               clone = await self.backend.builds.create(
+                       # Build the same package
+                       package = self.pkg,
+
+                       # Owner
+                       owner   = owner,
+
+                       # Repository
+                       repo    = repo or self.build_repo,
+               )
+
+               log.info("Cloned %s as %s" % (self, clone))
+
+               return clone
+
 
 class BuildGroup(database.Base, database.SoftDeleteMixin):
        __tablename__ = "build_groups"
index b26bcb49bb9513e0fa39fed4413eee0b313d0e11..8a8154faf06e0c7b66a5ffb5a49c79869cc2d04d 100644 (file)
@@ -845,7 +845,7 @@ class User(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Custom repositories
 
-       async def get_repos(self):
+       async def get_repos(self, distro=None):
                """
                        Returns all custom repositories
                """
@@ -861,6 +861,12 @@ class User(database.Base, database.BackendMixin, database.SoftDeleteMixin):
                        )
                )
 
+               # Filter by distribution
+               if distro:
+                       stmt = stmt.where(
+                               repos.Repo.distro == distro,
+                       )
+
                return await self.db.fetch_as_list(stmt)
 
        async def get_repo(self, distro, slug=None):
index fe3e63937a9c9d831d049a58107068fcf4298e53..557425bf0a1f2d8b040e0b4244486c50616bc669 100644 (file)
@@ -1,6 +1,6 @@
-{% extends "../modal.html" %}
+{% extends "modal.html" %}
 
-{% block title %}{{ build }} - {{ _("Clone") }}{% end block %}
+{% block title %}{{ build }} - {{ _("Clone") }}{% endblock %}
 
 {% block breadcrumbs %}
        <nav class="breadcrumb" aria-label="breadcrumbs">
                        </li>
                </ul>
        </nav>
-{% end block %}
+{% endblock %}
 
 {% block modal_title %}
        <h4 class="title is-4">{{ _("Clone Build") }}</h4>
        <h6 class="subtitle is-6">{{ build }}</h6>
-{% end block %}
+{% endblock %}
 
 {% block modal %}
        <form method="POST" action="">
-               {% raw xsrf_form_html() %}
+               {{ xsrf_form_html() | safe }}
 
                {# Repositories #}
+               {% set repos = current_user.get_repos(distro=build.distro) %}
+
                <div class="field">
                        <label class="label">{{ _("Repository") }}</label>
                        <div class="control">
@@ -38,9 +40,9 @@
                                        <select name="repo" required>
                                                <option value="">{{ _("- Select One -") }}</option>
 
-                                               {% for repo in sorted(repos) %}
+                                               {% for repo in repos | sort %}
                                                        <option value="{{ repo.slug }}">{{ repo }}</option>
-                                               {% end %}
+                                               {% endfor %}
                                        </select>
                                </div>
                        </div>
@@ -53,4 +55,4 @@
                        </button>
                </div>
        </form>
-{% end block %}
+{% endblock %}
index 1cc9bc538906a230e44ae859fdfcb2eb9764c5cc..8b9104c498a79e83d8103e1e4ee012762ee691eb 100644 (file)
@@ -599,6 +599,20 @@ class BaseHandler(tornado.web.RequestHandler):
                if slug:
                        return await self.backend.distros.get_by_slug(slug)
 
+       async def get_argument_repo(self, *args, distro=None, user=None, **kwargs):
+               if distro is None:
+                       raise ValueError("Distro required")
+
+               # Fetch the slug of the repository
+               slug = self.get_argument(*args, **kwargs)
+
+               # Fetch the user repository
+               if user:
+                       return await user.get_repo(slug=slug, distro=distro)
+
+               # Or fetch it from the distribution
+               return await distro.get_repo(slug=slug)
+
        # Uploads
 
        async def _get_upload(self, uuid):
index e8c0822f1a765b1b7324abc764faac6094561d7c..87afc205c28478c3690a69e0d253c453c87a6f9a 100644 (file)
@@ -135,33 +135,31 @@ class ApproveHandler(base.BaseHandler):
 
 class CloneHandler(base.BaseHandler):
        @base.authenticated
-       def get(self, uuid):
-               build = self.backend.builds.get_by_uuid(uuid)
+       async def get(self, uuid):
+               build = await 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)
+               await self.render("builds/clone.html", build=build)
 
        @base.authenticated
        async def post(self, uuid):
-               build = self.backend.builds.get_by_uuid(uuid)
+               build = await 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"))
+               repo = await self.get_argument_repo(
+                       "repo",
+                       user   = self.current_user,
+                       distro = build.distro,
+               )
 
                # Clone the build
-               with self.db.transaction():
-                       clone = await self.backend.builds.create(
-                               repo=repo, package=build.pkg, owner=self.current_user,
-                       )
+               clone = await build.clone(
+                       owner = self.current_user,
+                       repo  = repo,
+               )
 
                # Launch all jobs (in the background)
                self.backend.run_task(self.backend.builds.launch, [clone])