Making some refactors to make it easier to cancel the build at any time.
This commit is contained in:
parent
42ed8522fd
commit
1cde22e76c
3 changed files with 86 additions and 16 deletions
|
@ -63,10 +63,7 @@ class StatusHandler(object):
|
||||||
self._append_log_message(phase, self._build_logs.PHASE, extra_data)
|
self._append_log_message(phase, self._build_logs.PHASE, extra_data)
|
||||||
|
|
||||||
# Update the repository build with the new phase
|
# Update the repository build with the new phase
|
||||||
repo_build = model.build.get_repository_build(self._uuid)
|
return model.build.update_phase(self._uuid, phase)
|
||||||
repo_build.phase = phase
|
|
||||||
repo_build.save()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self._status
|
return self._status
|
||||||
|
|
|
@ -143,24 +143,47 @@ def get_pull_robot_name(trigger):
|
||||||
return trigger.pull_robot.username
|
return trigger.pull_robot.username
|
||||||
|
|
||||||
|
|
||||||
def cancel_repository_build(build, work_queue):
|
def update_phase(build_uuid, phase):
|
||||||
|
""" A function to change the phase of a build """
|
||||||
|
with db_transaction():
|
||||||
|
try:
|
||||||
|
build = get_repository_build(build_uuid)
|
||||||
|
build.phase = phase
|
||||||
|
build.save()
|
||||||
|
return True
|
||||||
|
except InvalidRepositoryBuildException:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def create_cancel_build_in_queue(build, build_queue):
|
||||||
|
""" A function to cancel a build before it leaves the queue """
|
||||||
|
def cancel_build():
|
||||||
|
if build.phase != BUILD_PHASE.WAITING or not build.queue_id:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return build_queue.cancel(build.queue_id)
|
||||||
|
|
||||||
|
return cancel_build
|
||||||
|
|
||||||
|
|
||||||
|
def cancel_repository_build(build, build_queue):
|
||||||
|
""" This tries to cancel the build returns true if request is successful false if it can't be cancelled """
|
||||||
with db_transaction():
|
with db_transaction():
|
||||||
# Reload the build for update.
|
# Reload the build for update.
|
||||||
|
# We are loading the build for update so checks should be as quick as possible.
|
||||||
try:
|
try:
|
||||||
build = db_for_update(RepositoryBuild.select().where(RepositoryBuild.id == build.id)).get()
|
build = db_for_update(RepositoryBuild.select().where(RepositoryBuild.id == build.id)).get()
|
||||||
except RepositoryBuild.DoesNotExist:
|
except RepositoryBuild.DoesNotExist:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if build.phase != BUILD_PHASE.WAITING or not build.queue_id:
|
cancel_builds = [create_cancel_build_in_queue(build, build_queue), ]
|
||||||
return False
|
for cancelled in cancel_builds:
|
||||||
|
if cancelled():
|
||||||
|
# Delete the build row.
|
||||||
|
build.delete_instance()
|
||||||
|
return True
|
||||||
|
|
||||||
# Try to cancel the queue item.
|
return False
|
||||||
if not work_queue.cancel(build.queue_id):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Delete the build row.
|
|
||||||
build.delete_instance()
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def get_archivable_build():
|
def get_archivable_build():
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import unittest
|
import unittest
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
from app import app
|
from app import app
|
||||||
|
from data.model.build import get_repository_build, update_phase, create_repository_build
|
||||||
from initdb import setup_database_for_testing, finished_database_for_testing
|
from initdb import setup_database_for_testing, finished_database_for_testing
|
||||||
from data import model
|
from data import model
|
||||||
from data.database import RepositoryBuild, Repository, Image, ImageStorage
|
from data.database import RepositoryBuild, Image, ImageStorage, BUILD_PHASE
|
||||||
|
|
||||||
ADMIN_ACCESS_USER = 'devtable'
|
ADMIN_ACCESS_USER = 'devtable'
|
||||||
SIMPLE_REPO = 'simple'
|
SIMPLE_REPO = 'simple'
|
||||||
|
|
||||||
|
|
||||||
class TestSpecificQueries(unittest.TestCase):
|
class TestSpecificQueries(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
setup_database_for_testing(self)
|
setup_database_for_testing(self)
|
||||||
|
@ -63,6 +66,53 @@ class TestSpecificQueries(unittest.TestCase):
|
||||||
self.fail('Expected BlobDoesNotExist exception')
|
self.fail('Expected BlobDoesNotExist exception')
|
||||||
|
|
||||||
|
|
||||||
|
class TestUpdatePhase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
setup_database_for_testing(self)
|
||||||
|
self.app = app.test_client()
|
||||||
|
self.ctx = app.test_request_context()
|
||||||
|
self.ctx.__enter__()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
finished_database_for_testing(self)
|
||||||
|
self.ctx.__exit__(True, None, None)
|
||||||
|
|
||||||
|
def testUpdatePhase(self):
|
||||||
|
build = self.create_build(model.repository.get_repository("devtable", "building"))
|
||||||
|
|
||||||
|
repo_build = get_repository_build(build.uuid)
|
||||||
|
|
||||||
|
self.assertEqual(repo_build.phase, BUILD_PHASE.WAITING)
|
||||||
|
self.assertTrue(update_phase(build.uuid, BUILD_PHASE.COMPLETE))
|
||||||
|
|
||||||
|
repo_build = get_repository_build(build.uuid)
|
||||||
|
|
||||||
|
self.assertEqual(repo_build.phase, BUILD_PHASE.COMPLETE)
|
||||||
|
|
||||||
|
repo_build.delete_instance()
|
||||||
|
|
||||||
|
self.assertFalse(update_phase(repo_build.uuid, BUILD_PHASE.PULLING))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_build(repository):
|
||||||
|
new_token = model.token.create_access_token(repository, 'write', 'build-worker')
|
||||||
|
repo = 'ci.devtable.com:5000/%s/%s' % (repository.namespace_user.username, repository.name)
|
||||||
|
job_config = {
|
||||||
|
'repository': repo,
|
||||||
|
'docker_tags': ['latest'],
|
||||||
|
'build_subdir': '',
|
||||||
|
'trigger_metadata': {
|
||||||
|
'commit': '3482adc5822c498e8f7db2e361e8d57b3d77ddd9',
|
||||||
|
'ref': 'refs/heads/master',
|
||||||
|
'default_branch': 'master'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
build = create_repository_build(repository, new_token, job_config,
|
||||||
|
'68daeebd-a5b9-457f-80a0-4363b882f8ea',
|
||||||
|
"build_name")
|
||||||
|
build.save()
|
||||||
|
return build
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Reference in a new issue