From 821c4aff496391215445d28a0d1d70a3445450e3 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Fri, 24 Jul 2020 11:54:12 +0200 Subject: [PATCH] TT#86350 release_dashboard: fix release parameter when building mrX.Y * release has to be 'release-mrX.Y-update' when the build is not the first * add check in model, already in view, to don't allow to build more than one mrX.Y.Z release * don't trigger copy_debs on release '*-update' builds * fix BuildRelease.done property, now we can have no BUILD_RELEASE_JOBS in the list * BuildReleaseManager.release() in order to get all the BuildRelease related to the same version now that we have 'release-mrX.Y-update' Change-Id: I610a246c2f5fc3574153fd226837a060185c379d --- build/exceptions.py | 6 +++ build/models/__init__.py | 10 ++-- build/models/br.py | 42 +++++++++++++++-- build/test/test_models.py | 62 ++++++++++++++++++++++++- build/test/test_utils.py | 4 ++ build/utils.py | 4 +- panel/templates/panel/release_uuid.html | 4 +- release_dashboard/views/build.py | 6 +-- 8 files changed, 124 insertions(+), 14 deletions(-) diff --git a/build/exceptions.py b/build/exceptions.py index 71c3de3..ad20110 100644 --- a/build/exceptions.py +++ b/build/exceptions.py @@ -36,3 +36,9 @@ class NoReleaseInfo(Error): class NoDistrisInfo(Error): pass + + +class BuildReleaseUnique(Error): + """ mrX.Y.Z release should be built just once """ + + pass diff --git a/build/models/__init__.py b/build/models/__init__.py index 5a40221..17e6748 100644 --- a/build/models/__init__.py +++ b/build/models/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 The Sipwise Team - http://sipwise.com +# Copyright (C) 2017-2020 The Sipwise Team - http://sipwise.com # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free @@ -28,8 +28,12 @@ logger = logging.getLogger(__name__) def br_manage(sender, **kwargs): if kwargs["created"]: instance = kwargs["instance"] - build_release.delay(instance.pk) - logger.debug("BuildRelease:%s triggered", instance) + if instance.release.endswith("-update"): + build_resume.delay(instance.pk) + logger.debug("BuildRelease:%s triggered", instance) + else: + build_release.delay(instance.pk) + logger.debug("BuildRelease:%s triggered", instance) def jbi_manage(sender, **kwargs): diff --git a/build/models/br.py b/build/models/br.py index 6795986..3e696d7 100644 --- a/build/models/br.py +++ b/build/models/br.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 The Sipwise Team - http://sipwise.com +# Copyright (C) 2017-2020 The Sipwise Team - http://sipwise.com # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free @@ -13,28 +13,55 @@ # You should have received a copy of the GNU General Public License along # with this program. If not, see . import logging +import re from django.db import models +from django.db.models import Q from django.forms.models import model_to_dict from ..conf import settings +from build.exceptions import BuildReleaseUnique from build.utils import get_simple_release from build.utils import ReleaseConfig from repoapi.models import JenkinsBuildInfo logger = logging.getLogger(__name__) +regex_mrXXX = re.compile(r"^mr[0-9]+\.[0-9]+\.[0-9]+$") +regex_mrXX = re.compile(r"^mr[0-9]+\.[0-9]+$") +regex_mrXX_up = re.compile(r"^release-mr[0-9]+\.[0-9]+-update$") + class BuildReleaseManager(models.Manager): _jbi = JenkinsBuildInfo.objects + def release(self, version): + qs = self.get_queryset() + return qs.filter( + Q(release=version) | Q(release="{}-update".format(version)) + ) + def create_build_release(self, uuid, release): config = ReleaseConfig(release) + qs = self.get_queryset() + br = qs.filter(release=config.release) + release_ok = config.release + if br.exists(): + if regex_mrXXX.match(config.branch): + msg = "release[mrX.Y.Z]:{} has already a build" + raise BuildReleaseUnique(msg.format(release)) + elif regex_mrXX.match(config.branch): + release_ok = "{}-update".format(config.release) + msg = ( + "release[mrX.Y]:{} has already a build, " + "set {} as release" + ) + logger.info(msg.format(config.branch, release_ok)) return self.create( uuid=uuid, tag=config.tag, branch=config.branch, - release=config.release, + release=release_ok, distribution=config.debian_release, projects=",".join(config.projects), ) @@ -97,7 +124,7 @@ class BuildRelease(models.Model): failed_projects = models.TextField(null=True, editable=False) pool_size = models.SmallIntegerField(default=0, editable=False) objects = BuildReleaseManager() - release_jobs_len = len(",".join(settings.BUILD_RELEASE_JOBS)) + release_jobs_len = len(",".join(settings.BUILD_RELEASE_JOBS)) + 1 def __str__(self): return "%s[%s]" % (self.release, self.uuid) @@ -118,12 +145,19 @@ class BuildRelease(models.Model): if job: return job.date + @property + def is_update(self): + return regex_mrXX_up.match(self.release) is not None + @property def done(self): if self.built_projects is None: return False built_len = len(self.built_projects) - return built_len == self.release_jobs_len + 1 + len(self.projects) + if self.is_update: + return built_len == len(self.projects) + else: + return built_len == self.release_jobs_len + len(self.projects) @property def projects_list(self): diff --git a/build/test/test_models.py b/build/test/test_models.py index 33410ca..a200140 100644 --- a/build/test/test_models.py +++ b/build/test/test_models.py @@ -17,6 +17,7 @@ from unittest.mock import patch from django.test import override_settings +from build.exceptions import BuildReleaseUnique from build.models import BuildRelease from repoapi.models import JenkinsBuildInfo from repoapi.test.base import BaseTest @@ -38,6 +39,23 @@ class BuildReleaseManagerTestCase(BaseTest): self.assertNotEqual(len(br.projects), 0) self.assertIn("sipwise-base", br.projects) + def test_create_mrXX(self, dlf): + BuildRelease.objects.filter(release="release-mr8.1").delete() + self.assertFalse( + BuildRelease.objects.filter(release="release-mr8.1").exists() + ) + br = BuildRelease.objects.create_build_release("AAA", "mr8.1") + self.assertEqual(br.release, "release-mr8.1") + + def test_create_mrXX_update(self, dlf): + br = BuildRelease.objects.create_build_release("AAA", "mr8.1") + self.assertEqual(br.release, "release-mr8.1-update") + + def test_create_mrXXX_fail(self, dlf): + BuildRelease.objects.create_build_release("AAA", "mr7.5.3") + with self.assertRaises(BuildReleaseUnique): + BuildRelease.objects.create_build_release("BBB", "mr7.5.3") + def test_release_jobs(self, dlf): jobs = BuildRelease.objects.release_jobs(self.release_uuid) self.assertListEqual(list(jobs.all()), ["release-copy-debs-yml"]) @@ -64,6 +82,13 @@ class BuildReleaseManagerTestCase(BaseTest): job = JenkinsBuildInfo.objects.get(id=4) self.assertEqual(br.last_update, job.date) + def test_release(self, dlf): + prev = BuildRelease.objects.filter(release="release-mr8.1") + br = BuildRelease.objects.create_build_release("BBB", "mr8.1") + self.assertEqual(br.release, "release-mr8.1-update") + qs = BuildRelease.objects.release("release-mr8.1") + self.assertEqual(qs.count(), prev.count() + 1) + class BuildReleaseTestCase(BaseTest): fixtures = [ @@ -103,14 +128,38 @@ class BuildReleaseTestCase(BaseTest): def test_branch_or_tag_trunk(self): build = BuildRelease.objects.create_build_release("AAA", "trunk") self.assertEqual(build.branch_or_tag, "branch/master") + self.assertFalse(build.is_update) def test_branch_or_tag_mrXX(self): build = BuildRelease.objects.get(uuid=self.release_uuid) self.assertEqual(build.branch_or_tag, "branch/mr8.1") + self.assertEqual(build.release, "release-mr8.1") + self.assertFalse(build.is_update) def test_branch_or_tag_mrXXX(self): build = BuildRelease.objects.create_build_release("AAA", "mr7.5.2") self.assertEqual(build.branch_or_tag, "tag/mr7.5.2.1") + self.assertFalse(build.is_update) + + def test_is_update_ok(self): + build = BuildRelease.objects.create_build_release("AAA", "mr8.1") + self.assertEqual(build.branch_or_tag, "branch/mr8.1") + self.assertEqual(build.release, "release-mr8.1-update") + self.assertTrue(build.is_update) + + def test_done_update(self): + build = BuildRelease.objects.create_build_release("AAA", "mr8.1") + build.built_projects = build.projects + self.assertTrue(build.done) + + @override_settings(BUILD_RELEASE_JOBS=["release-copy-debs-yml", "other"]) + def test_done(self): + br = BuildRelease.objects.get(uuid=self.release_uuid) + br.built_projects = br.projects + self.assertFalse(br.done) + br.built_projects = "release-copy-debs-yml,other,{}".format( + br.projects + ) def test_build_deps(self): build_deps = [ @@ -401,15 +450,26 @@ class JBIManageTest(BaseTest): class BRManageTest(BaseTest): + fixtures = [ + "test_models", + ] + @patch("build.tasks.trigger_copy_deps") @patch("build.models.build_resume") def test_br_manage(self, build_resume, trigger_copy_deps): - br = BuildRelease.objects.create_build_release("UUID_mr8.1", "mr8.1") + br = BuildRelease.objects.create_build_release("UUID", "mr7.5") build_resume.delay.assert_not_called() trigger_copy_deps.assert_called_once_with( internal=True, release=br.release, release_uuid=br.uuid ) + @patch("build.tasks.trigger_copy_deps") + @patch("build.models.build_resume") + def test_br_manage_ko(self, build_resume, trigger_copy_deps): + br = BuildRelease.objects.create_build_release("UUID1", "mr8.1") + build_resume.delay.assert_called_once_with(br.id) + trigger_copy_deps.assert_not_called() + class BuildReleaseRetriggerTest(BaseTest): fixtures = [ diff --git a/build/test/test_utils.py b/build/test/test_utils.py index bee83dd..810c1d8 100644 --- a/build/test/test_utils.py +++ b/build/test/test_utils.py @@ -40,6 +40,10 @@ class SimpleReleaseTest(SimpleTestCase): val = get_simple_release("release-mr8.1.1") self.assertEqual(val, "mr8.1.1") + def test_release_update_ok(self): + val = get_simple_release("release-mr8.1-update") + self.assertEqual(val, "mr8.1") + def test_release_ko(self): val = get_simple_release("mr8.1.1") self.assertIsNone(val) diff --git a/build/utils.py b/build/utils.py index 198a564..1bd2378 100644 --- a/build/utils.py +++ b/build/utils.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 The Sipwise Team - http://sipwise.com +# Copyright (C) 2017-2020 The Sipwise Team - http://sipwise.com # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free @@ -43,7 +43,7 @@ re_release_common = re.compile(r"^(release-)?(mr[0-9]+\.[0-9]+)(\.[0-9]+)?$") def get_simple_release(version): - match = re_release.search(version) + match = re_release.search(version.replace("-update", "")) if match: return match.group(1) if version.startswith("release-trunk-"): diff --git a/panel/templates/panel/release_uuid.html b/panel/templates/panel/release_uuid.html index b91e064..98ea89e 100644 --- a/panel/templates/panel/release_uuid.html +++ b/panel/templates/panel/release_uuid.html @@ -14,7 +14,9 @@
- {% include "panel/base_release_job.html" %} + {% if not build_release.is_update %} + {% include "panel/base_release_job.html" %} + {% endif %}
diff --git a/release_dashboard/views/build.py b/release_dashboard/views/build.py index 5e1cfec..42e60b6 100644 --- a/release_dashboard/views/build.py +++ b/release_dashboard/views/build.py @@ -68,9 +68,9 @@ def build_release(request, release): reverse("panel:release-uuid", args=(release_uuid,)) ) else: - build_releases = BuildRelease.objects.filter( - release=release_config.release - ).order_by('-start_date') + build_releases = BuildRelease.objects.release( + release_config.release + ).order_by("-start_date") if build_releases.count() == 0: done = True else: