From da389720151a38c910c571fee7f46ce04c2c633f Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Fri, 27 May 2022 01:29:41 +0200 Subject: [PATCH] TT#15305 build: don't allow trigger builds that have unfinished previous builds * don't allow to trigger more than one build for instance of release-trunk-* or mrX.Y * autoupdate pre-commit config Change-Id: I7183b8645155ca017e9796664d2570e88a29c44e --- .pre-commit-config.yaml | 8 ++++---- build/exceptions.py | 12 +++++++++--- build/models.py | 13 ++++++++++--- build/test/test_models.py | 23 ++++++++++++++++++++++- t/Dockerfile | 2 +- 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a77aead..7d66ccc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ default_language_version: python: python3 repos: - repo: https://github.com/asottile/reorder_python_imports - rev: v2.6.0 + rev: v3.1.0 hooks: - id: reorder-python-imports exclude: > @@ -13,7 +13,7 @@ repos: )$ args: ["--py37-plus"] - repo: https://github.com/psf/black - rev: 21.12b0 + rev: 22.3.0 hooks: - id: black - repo: https://gitlab.com/PyCQA/flake8 @@ -21,11 +21,11 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v4.2.0 hooks: - id: requirements-txt-fixer - repo: https://github.com/pre-commit/mirrors-eslint - rev: v8.6.0 + rev: v8.16.0 hooks: - id: eslint args: ['--fix'] diff --git a/build/exceptions.py b/build/exceptions.py index ad20110..b66db93 100644 --- a/build/exceptions.py +++ b/build/exceptions.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 The Sipwise Team - http://sipwise.com +# Copyright (C) 2017-2022 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 @@ -25,7 +25,7 @@ class NoConfigReleaseFile(Error): class NoJenkinsJobsInfo(Error): - """ release config.yml has no jenkins-jobs entry """ + """release config.yml has no jenkins-jobs entry""" pass @@ -39,6 +39,12 @@ class NoDistrisInfo(Error): class BuildReleaseUnique(Error): - """ mrX.Y.Z release should be built just once """ + """mrX.Y.Z release should be built just once""" + + pass + + +class PreviousBuildNotDone(Error): + """same release is building right now""" pass diff --git a/build/models.py b/build/models.py index 4cb057f..32e454e 100644 --- a/build/models.py +++ b/build/models.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2020 The Sipwise Team - http://sipwise.com +# Copyright (C) 2017-2022 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 @@ -23,6 +23,7 @@ from django.utils import timezone from .conf import settings from .exceptions import BuildReleaseUnique +from .exceptions import PreviousBuildNotDone from .utils import get_simple_release from .utils import ReleaseConfig from repoapi.models import JenkinsBuildInfo @@ -33,6 +34,9 @@ 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$") +build_release_jobs = ",".join(settings.BUILD_RELEASE_JOBS) +release_jobs_len = len(build_release_jobs) + 1 + class BuildReleaseManager(models.Manager): _jbi = JenkinsBuildInfo.objects @@ -63,6 +67,10 @@ class BuildReleaseManager(models.Manager): "set {} as release" ) log.info(msg.format(config.branch, release_ok)) + if not br.last().done: + msg = f"release:{release} is already building" + log.info(msg) + raise PreviousBuildNotDone(msg) projects = ",".join(config.projects) if fake: start_date = timezone.make_aware(datetime.datetime(1977, 1, 1)) @@ -143,7 +151,6 @@ 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)) + 1 def __str__(self): return "%s[%s]" % (self.release, self.uuid) @@ -176,7 +183,7 @@ class BuildRelease(models.Model): if self.is_update: return built_len == len(self.projects) else: - return built_len == self.release_jobs_len + len(self.projects) + return built_len == 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 e8fc8bc..cfe31b0 100644 --- a/build/test/test_models.py +++ b/build/test/test_models.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2020 The Sipwise Team - http://sipwise.com +# Copyright (C) 2017-2022 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 @@ -20,11 +20,22 @@ from django.test import override_settings from django.utils import timezone from build.exceptions import BuildReleaseUnique +from build.exceptions import PreviousBuildNotDone +from build.models import build_release_jobs from build.models import BuildRelease from repoapi.models import JenkinsBuildInfo from repoapi.test.base import BaseTest +def set_build_done(qs): + for br in qs: + if br.is_update: + br.built_projects = br.projects + else: + br.built_projects = build_release_jobs + "," + br.projects + br.save() + + @override_settings(JBI_ALLOWED_HOSTS=["fake.local"]) @patch("repoapi.utils.dlfile") class BuildReleaseManagerTestCase(BaseTest): @@ -60,7 +71,13 @@ class BuildReleaseManagerTestCase(BaseTest): br = BuildRelease.objects.create_build_release("AAA", "mr8.1") self.assertEqual(br.release, "release-mr8.1") + def test_create_mrXX_update_building(self, dlf): + """mr8.1 is building, don't allow a new build""" + with self.assertRaises(PreviousBuildNotDone): + BuildRelease.objects.create_build_release("AAA", "mr8.1") + def test_create_mrXX_update(self, dlf): + set_build_done(BuildRelease.objects.filter(release="release-mr8.1")) br = BuildRelease.objects.create_build_release("AAA", "mr8.1") self.assertEqual(br.release, "release-mr8.1-update") @@ -97,6 +114,7 @@ class BuildReleaseManagerTestCase(BaseTest): def test_release(self, dlf): prev = BuildRelease.objects.filter(release="release-mr8.1") + set_build_done(prev) br = BuildRelease.objects.create_build_release("BBB", "mr8.1") self.assertEqual(br.release, "release-mr8.1-update") qs = BuildRelease.objects.release("release-mr8.1", "buster") @@ -160,12 +178,14 @@ class BuildReleaseTestCase(BaseTest): self.assertFalse(build.is_update) def test_is_update_ok(self): + set_build_done(BuildRelease.objects.filter(release="release-mr8.1")) 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): + set_build_done(BuildRelease.objects.filter(release="release-mr8.1")) build = BuildRelease.objects.create_build_release("AAA", "mr8.1") build.built_projects = build.projects self.assertTrue(build.done) @@ -478,6 +498,7 @@ class BRManageTest(BaseTest): @patch("build.tasks.trigger_copy_deps") @patch("build.signals.build_resume") def test_br_manage_ko(self, build_resume, trigger_copy_deps): + set_build_done(BuildRelease.objects.filter(release="release-mr8.1")) br = BuildRelease.objects.create_build_release("UUID1", "mr8.1") build_resume.delay.assert_called_once_with(br.id) trigger_copy_deps.assert_not_called() diff --git a/t/Dockerfile b/t/Dockerfile index 9da10cc..d0d6894 100644 --- a/t/Dockerfile +++ b/t/Dockerfile @@ -5,7 +5,7 @@ FROM docker.mgm.sipwise.com/sipwise-bullseye:latest # is updated with the current date. It will force refresh of all # of the base images and things like `apt-get update` won't be using # old cached versions when the Dockerfile is built. -ENV REFRESHED_AT 2022-05-27 +ENV REFRESHED_AT 2022-05-28 RUN apt-get update && apt-get install --assume-yes python3 python3-dev \ python3-pytest python3-pytest-pep8 \