diff --git a/buildstatus/cancelled.svg b/buildstatus/cancelled.svg
new file mode 100644
index 000000000..0e565cf97
--- /dev/null
+++ b/buildstatus/cancelled.svg
@@ -0,0 +1 @@
+
diff --git a/config.py b/config.py
index 42b6aa491..dc647cd30 100644
--- a/config.py
+++ b/config.py
@@ -128,7 +128,7 @@ class DefaultConfig(object):
# Status tag config
STATUS_TAGS = {}
- for tag_name in ['building', 'failed', 'none', 'ready']:
+ for tag_name in ['building', 'failed', 'none', 'ready', 'cancelled']:
tag_path = os.path.join('buildstatus', tag_name + '.svg')
with open(tag_path) as tag_svg:
STATUS_TAGS[tag_name] = tag_svg.read()
diff --git a/data/model/build.py b/data/model/build.py
index 13e727edc..90b3d8bb1 100644
--- a/data/model/build.py
+++ b/data/model/build.py
@@ -13,6 +13,7 @@ PRESUMED_DEAD_BUILD_AGE = timedelta(days=15)
PHASES_NOT_ALLOWED_TO_CANCEL_FROM = (BUILD_PHASE.PUSHING, BUILD_PHASE.COMPLETE,
BUILD_PHASE.ERROR, BUILD_PHASE.INTERNAL_ERROR)
+ARCHIVABLE_BUILD_PHASES = [BUILD_PHASE.COMPLETE, BUILD_PHASE.ERROR, BUILD_PHASE.CANCELLED]
def update_build_trigger(trigger, config, auth_token=None):
trigger.config = json.dumps(config or {})
@@ -184,19 +185,11 @@ def create_cancel_build_in_queue(build, build_queue):
def create_cancel_build_in_manager(build, build_canceller):
""" A function to cancel the build before it starts to push """
def cancel_build():
- original_phase = build.phase
if build.phase in PHASES_NOT_ALLOWED_TO_CANCEL_FROM:
return False
- build.phase = BUILD_PHASE.CANCELLED
- build.save()
+ return build_canceller.try_cancel_build(build.uuid)
- if not build_canceller.try_cancel_build(build.uuid):
- build.phase = original_phase
- build.save()
- return False
-
- return True
return cancel_build
@@ -213,22 +206,23 @@ def cancel_repository_build(build, build_queue):
cancel_builds = [create_cancel_build_in_queue(build, build_queue),
create_cancel_build_in_manager(build, build_canceller), ]
+ original_phase = build.phase
for cancelled in cancel_builds:
if cancelled():
- # Delete the build row.
- # TODO Charlie 2016-11-11 Add in message that says build was cancelled and remove the delete build.
- build.delete_instance()
+ build.phase = BUILD_PHASE.CANCELLED
+ build.save()
return True
-
+ build.phase = original_phase
+ build.save()
return False
def get_archivable_build():
presumed_dead_date = datetime.utcnow() - PRESUMED_DEAD_BUILD_AGE
+
candidates = (RepositoryBuild
.select(RepositoryBuild.id)
- .where((RepositoryBuild.phase == BUILD_PHASE.COMPLETE) |
- (RepositoryBuild.phase == BUILD_PHASE.ERROR) |
+ .where((RepositoryBuild.phase << ARCHIVABLE_BUILD_PHASES) |
(RepositoryBuild.started < presumed_dead_date),
RepositoryBuild.logs_archived == False)
.limit(50)
diff --git a/endpoints/api/build.py b/endpoints/api/build.py
index cac1fdea1..7efedc993 100644
--- a/endpoints/api/build.py
+++ b/endpoints/api/build.py
@@ -318,7 +318,7 @@ class RepositoryBuildResource(RepositoryParamResource):
@require_repo_admin
@nickname('cancelRepoBuild')
def delete(self, namespace, repository, build_uuid):
- """ Cancels a repository build if it has not yet been picked up by a build worker. """
+ """ Cancels a repository build. """
try:
build = model.build.get_repository_build(build_uuid)
except model.build.InvalidRepositoryBuildException:
diff --git a/endpoints/web.py b/endpoints/web.py
index 4b7b2b65f..f08efd800 100644
--- a/endpoints/web.py
+++ b/endpoints/web.py
@@ -440,6 +440,8 @@ def build_status_badge(namespace_name, repo_name):
status_name = 'ready'
elif recent_build and recent_build.phase == 'error':
status_name = 'failed'
+ elif recent_build and recent_build.phase == 'cancelled':
+ status_name = 'cancelled'
elif recent_build and recent_build.phase != 'complete':
status_name = 'building'
else:
diff --git a/static/css/directives/ui/build-state-icon.css b/static/css/directives/ui/build-state-icon.css
index 125b0723e..acf9a8dd3 100644
--- a/static/css/directives/ui/build-state-icon.css
+++ b/static/css/directives/ui/build-state-icon.css
@@ -20,4 +20,8 @@
.build-state-icon .complete {
color: #2fcc66;
-}
\ No newline at end of file
+}
+
+.build-state-icon .cancelled {
+ color: #9b9b9b;
+}
diff --git a/static/directives/build-state-icon.html b/static/directives/build-state-icon.html
index f0408f339..bcc251269 100644
--- a/static/directives/build-state-icon.html
+++ b/static/directives/build-state-icon.html
@@ -5,5 +5,6 @@
+
diff --git a/static/js/directives/ui/build-mini-status.js b/static/js/directives/ui/build-mini-status.js
index a6698bd74..c48d7ea21 100644
--- a/static/js/directives/ui/build-mini-status.js
+++ b/static/js/directives/ui/build-mini-status.js
@@ -12,10 +12,10 @@ angular.module('quay').directive('buildMiniStatus', function () {
'build': '=build',
'isAdmin': '=isAdmin'
},
- controller: function($scope, $element) {
+ controller: function($scope, $element, BuildService) {
$scope.isBuilding = function(build) {
if (!build) { return true; }
- return build.phase != 'complete' && build.phase != 'error';
+ return BuildService.isActive(build)
};
}
};
diff --git a/static/js/services/build-service.js b/static/js/services/build-service.js
index 280419b06..0f68edec2 100644
--- a/static/js/services/build-service.js
+++ b/static/js/services/build-service.js
@@ -2,9 +2,9 @@
* Service which provides helper methods for reasoning about builds.
*/
angular.module('quay').factory('BuildService', [function() {
- var buildService = {}
+ var buildService = {};
buildService.isActive = function(build) {
- return build.phase != 'complete' && build.phase != 'error' && build.phase != 'expired';
+ return build.phase != 'complete' && build.phase != 'error' && build.phase != 'expired' && build.phase != 'cancelled';
};
buildService.getBuildMessage = function(phase) {
@@ -51,6 +51,10 @@ angular.module('quay').factory('BuildService', [function() {
case 'internalerror':
return 'An internal system error occurred while building; the build will be retried in the next few minutes.';
+
+ case 'cancelled':
+ return 'This build was previously cancelled.';
+
}
};
diff --git a/static/partials/build-view.html b/static/partials/build-view.html
index 2fbf99750..3b379c691 100644
--- a/static/partials/build-view.html
+++ b/static/partials/build-view.html
@@ -41,8 +41,7 @@
Show Timestamps
-
+
Cancel Build
diff --git a/test/test_api_usage.py b/test/test_api_usage.py
index bde1f3175..b356049a9 100644
--- a/test/test_api_usage.py
+++ b/test/test_api_usage.py
@@ -2191,7 +2191,8 @@ class TestRepositoryBuildResource(ApiTestCase):
json = self.getJsonResponse(RepositoryBuildList,
params=dict(repository=ADMIN_ACCESS_USER + '/simple'))
- self.assertEquals(0, len(json['builds']))
+ self.assertEquals(1, len(json['builds']))
+ self.assertEquals('cancelled', json['builds'][0]['phase'])
# Check for the build's queue item.
try: