diff --git a/contrib/buildbot/build.py b/contrib/buildbot/build.py index fe3e0631f..2b837047c 100755 --- a/contrib/buildbot/build.py +++ b/contrib/buildbot/build.py @@ -1,57 +1,60 @@ #!/usr/bin/env python3 # # Copyright (c) 2020 The Bitcoin ABC developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. from enum import Enum class BuildStatus(Enum): Queued = "queued" Running = "running" Success = "success" Failure = "failure" Unknown = "unknown" class Build: def __init__(self, build_id, status, name): self.build_id = build_id self.status = status self.name = name class BuildTarget: def __init__(self, phid): self.phid = phid self.builds = {} def queue_build(self, build_id, name): self.builds[build_id] = Build(build_id, BuildStatus.Queued, name) def update_build_status(self, build_id, status): if build_id not in self.builds: raise AssertionError( "Attempting to update the build id {} to status {} that does not belong to the build target {}".format( build_id, status, self.phid ) ) self.builds[build_id].status = status def status(self): + # If there are no builds, the build target is by default a success + if len(self.builds.values()) == 0: + return BuildStatus.Success # If any build is a failure, the build target is a failure if any([build.status == BuildStatus.Failure for build in self.builds.values()]): return BuildStatus.Failure # If all the builds are a success, the build target is a success if all([build.status == BuildStatus.Success for build in self.builds.values()]): return BuildStatus.Success # If all the builds are queued, the build target is queued if all([build.status == BuildStatus.Queued for build in self.builds.values()]): return BuildStatus.Queued # Otherwise the build target is running return BuildStatus.Running def is_finished(self): return all([(build.status == BuildStatus.Success or build.status == BuildStatus.Failure) for build in self.builds.values()]) diff --git a/contrib/buildbot/test/test_build.py b/contrib/buildbot/test/test_build.py index f126d5afc..b4413bfdc 100755 --- a/contrib/buildbot/test/test_build.py +++ b/contrib/buildbot/test/test_build.py @@ -1,76 +1,80 @@ #!/usr/bin/env python3 # # Copyright (c) 2019 The Bitcoin ABC developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. from build import BuildStatus, BuildTarget import unittest class BuildTests(unittest.TestCase): def setUp(self): pass def tearDown(self): pass def test_buildTarget(self): build_target_phid = "PHID-HMBT-123456" # Create a build target build_target = BuildTarget(build_target_phid) + # With no builds, the target has default status of success + self.assertEqual(build_target.status(), BuildStatus.Success) + self.assertEqual(build_target.is_finished(), True) + # Queue a few builds for i in range(10): name = "build-{}".format(i) build_target.queue_build(i, name) self.assertEqual(len(build_target.builds), i + 1) self.assertEqual(build_target.builds[i].status, BuildStatus.Queued) self.assertEqual(build_target.status(), BuildStatus.Queued) self.assertEqual(build_target.is_finished(), False) # Update the status of a single build to running, the build target # should be running build_target.update_build_status(3, BuildStatus.Running) self.assertEqual(build_target.builds[3].status, BuildStatus.Running) self.assertEqual(build_target.status(), BuildStatus.Running) self.assertEqual(build_target.is_finished(), False) # If all the builds are finished with success, the build target is also # finished with success. Check it is running until the last one... build_ids = list(build_target.builds.keys()) for build_id in build_ids[:-1]: build_target.update_build_status(build_id, BuildStatus.Success) self.assertEqual( build_target.builds[build_id].status, BuildStatus.Success) self.assertEqual(build_target.status(), BuildStatus.Running) self.assertEqual(build_target.is_finished(), False) # ... which will change the state to finished/success. build_id = build_ids[-1] build_target.update_build_status(build_id, BuildStatus.Success) self.assertEqual( build_target.builds[build_id].status, BuildStatus.Success) self.assertEqual(build_target.status(), BuildStatus.Success) self.assertEqual(build_target.is_finished(), True) # If a single build fails, the build target should fail build_target.update_build_status(3, BuildStatus.Failure) self.assertEqual(build_target.builds[3].status, BuildStatus.Failure) self.assertEqual(build_target.status(), BuildStatus.Failure) self.assertEqual(build_target.is_finished(), True) # All the builds are finished and successful excepted one which remains # queued: the build target should be running and not finished build_target.update_build_status(3, BuildStatus.Queued) self.assertEqual(build_target.builds[3].status, BuildStatus.Queued) self.assertEqual(build_target.status(), BuildStatus.Running) self.assertEqual(build_target.is_finished(), False) if __name__ == '__main__': unittest.main()