From: Michael Tremer Date: Tue, 25 Oct 2022 11:40:30 +0000 (+0000) Subject: builds: Automatically deprecate previous builds X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=984b00dfba2e798e00bd296e9c46324b2006333c;p=pbs.git builds: Automatically deprecate previous builds Signed-off-by: Michael Tremer --- diff --git a/src/buildservice/builds.py b/src/buildservice/builds.py index dbc94d8c..8082f390 100644 --- a/src/buildservice/builds.py +++ b/src/buildservice/builds.py @@ -138,36 +138,6 @@ class Builds(base.Object): return list(builds) - def get_obsolete(self, repo=None): - """ - Get all obsoleted builds. - - If repo is True: which are in any repository. - If repo is some Repository object: which are in this repository. - """ - args = [] - - if repo is None: - query = "SELECT id FROM builds WHERE state = 'obsolete'" - - else: - query = "SELECT build_id AS id FROM repositories_builds \ - JOIN builds ON builds.id = repositories_builds.build_id \ - WHERE builds.state = 'obsolete'" - - if repo and not repo is True: - query += " AND repositories_builds.repo_id = %s" - args.append(repo.id) - - res = self.db.query(query, *args) - - builds = [] - for build in res: - build = Build(self.backend, build.id) - builds.append(build) - - return builds - def create(self, repo, package, owner=None, group=None): """ Creates a new build based on the given distribution and package @@ -203,7 +173,8 @@ class Builds(base.Object): # Create all jobs build._create_jobs() - # XXX obsolete other builds + # Deprecate previous builds + build._deprecate_others() # Add watchers build._add_watchers() @@ -339,22 +310,6 @@ class Build(base.DataObject): def is_broken(self): return self.state == "broken" - def obsolete_others(self): - if not self.type == "release": - return - - for build in self.backend.builds.get_by_name(self.pkg.name, type="release"): - # Don't modify ourself. - if self.id == build.id: - continue - - # Don't touch broken builds. - if build.state in ("obsolete", "broken"): - continue - - # Obsolete the build. - # XXX - def set_severity(self, severity): self._set_attribute("severity", severity) @@ -708,6 +663,111 @@ class Build(base.DataObject): for bug_id in self.get_bug_ids(): self._update_bug(bug_id, status=status, resolution=resolution, comment=comment) + # Deprecation + + def _deprecate_others(self): + """ + Called when this build is being created. + + This method will find similar builds and automatically deprecate them. + """ + builds = self.backend.builds._get_builds(""" + SELECT + builds.* + + -- Walk through all builds + FROM + builds + + -- Find all packages belonging to the builds + LEFT JOIN + packages ON builds.pkg_id = packages.id + + -- Find all packages that match the name + LEFT JOIN + packages other_packages ON + other_packages.name = packages.name + AND + other_packages.distro_id = packages.distro_id + + -- Find all other builds (excluding ourselves) + LEFT JOIN + builds other_builds ON + other_builds.id <> builds.id + AND + other_builds.pkg_id = other_packages.id + AND + other_builds.build_repo_id = builds.build_repo_id + + -- Start with this build + WHERE + other_builds.id = %s + + -- Exclude any deleted packages + AND + packages.deleted_at IS NULL + AND + other_packages.deleted_at IS NULL + + -- Exclude any deleted builds + AND + builds.deleted_at IS NULL + + -- Exclude everything that is already deprecated + AND + builds.deprecated_by IS NULL + """, self.id, + ) + + # Deprecate all builds + for build in builds: + build.deprecate(self) + + def deprecate(self, build): + """ + Called when a build needs to be deprecated + """ + log.debug("Deprecating %s by %s" % (self, build)) + + # Mark as deprecated + self.deprecated_by = build + + def is_deprecated(self): + if self.data.deprecated_by: + return True + + return False + + def get_deprecated_by(self): + if self.data.deprecated_by: + return self.backend.builds.get_by_id(self.data.deprecated_by) + + def set_deprecated_by(self, build): + self._set_attribute("deprecated_by", build) + + deprecated_by = lazy_property(get_deprecated_by, set_deprecated_by) + + @lazy_property + def deprecated_builds(self): + """ + Returns a list of builds that were deprecated by this build + """ + builds = self.backend.builds._get_builds(""" + SELECT + * + FROM + builds + WHERE + deleted_at IS NULL + AND + deprecated_by = %s + ORDER BY + created_at + """, self.id, + ) + + return list(builds) + class Groups(base.Object): """ diff --git a/src/database.sql b/src/database.sql index 848a4a67..5fc5172a 100644 --- a/src/database.sql +++ b/src/database.sql @@ -205,7 +205,8 @@ CREATE TABLE public.builds ( failed boolean DEFAULT false NOT NULL, deleted_at timestamp without time zone, deleted_by integer, - build_group_id integer + build_group_id integer, + deprecated_by integer ); @@ -1505,6 +1506,13 @@ CREATE INDEX builds_created_at ON public.builds USING btree (created_at DESC) WH CREATE INDEX builds_deleted ON public.builds USING btree (deleted_at) WHERE (deleted_at IS NOT NULL); +-- +-- Name: builds_deprecated_by; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX builds_deprecated_by ON public.builds USING btree (deprecated_by) WHERE (deleted_at IS NULL); + + -- -- Name: builds_pkg_id; Type: INDEX; Schema: public; Owner: - -- @@ -1814,6 +1822,14 @@ ALTER TABLE ONLY public.builds ADD CONSTRAINT builds_deleted_by FOREIGN KEY (deleted_by) REFERENCES public.users(id); +-- +-- Name: builds builds_deprecated_by; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.builds + ADD CONSTRAINT builds_deprecated_by FOREIGN KEY (deprecated_by) REFERENCES public.builds(id); + + -- -- Name: builds builds_owner_id; Type: FK CONSTRAINT; Schema: public; Owner: - -- diff --git a/src/templates/builds/show.html b/src/templates/builds/show.html index 82003892..042596c9 100644 --- a/src/templates/builds/show.html +++ b/src/templates/builds/show.html @@ -75,9 +75,16 @@ -
- X -
+ {# Deprecation #} + {% if build.is_deprecated() %} + + {% end %}
X