Adding in UI for cancel anytime.
This commit is contained in:
parent
f6fe9023a4
commit
2fe74e4057
11 changed files with 31 additions and 25 deletions
1
buildstatus/cancelled.svg
Normal file
1
buildstatus/cancelled.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="123" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="123" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h63v20H0z"/><path fill="#9f9f9f" d="M63 0h60v20H63z"/><path fill="url(#b)" d="M0 0h123v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="32.5" y="15" fill="#010101" fill-opacity=".3">container</text><text x="32.5" y="14">container</text><text x="92" y="15" fill="#010101" fill-opacity=".3">cancelled</text><text x="92" y="14">cancelled</text></g></svg>
|
After Width: | Height: | Size: 751 B |
|
@ -128,7 +128,7 @@ class DefaultConfig(object):
|
||||||
|
|
||||||
# Status tag config
|
# Status tag config
|
||||||
STATUS_TAGS = {}
|
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')
|
tag_path = os.path.join('buildstatus', tag_name + '.svg')
|
||||||
with open(tag_path) as tag_svg:
|
with open(tag_path) as tag_svg:
|
||||||
STATUS_TAGS[tag_name] = tag_svg.read()
|
STATUS_TAGS[tag_name] = tag_svg.read()
|
||||||
|
|
|
@ -13,6 +13,7 @@ PRESUMED_DEAD_BUILD_AGE = timedelta(days=15)
|
||||||
PHASES_NOT_ALLOWED_TO_CANCEL_FROM = (BUILD_PHASE.PUSHING, BUILD_PHASE.COMPLETE,
|
PHASES_NOT_ALLOWED_TO_CANCEL_FROM = (BUILD_PHASE.PUSHING, BUILD_PHASE.COMPLETE,
|
||||||
BUILD_PHASE.ERROR, BUILD_PHASE.INTERNAL_ERROR)
|
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):
|
def update_build_trigger(trigger, config, auth_token=None):
|
||||||
trigger.config = json.dumps(config or {})
|
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):
|
def create_cancel_build_in_manager(build, build_canceller):
|
||||||
""" A function to cancel the build before it starts to push """
|
""" A function to cancel the build before it starts to push """
|
||||||
def cancel_build():
|
def cancel_build():
|
||||||
original_phase = build.phase
|
|
||||||
if build.phase in PHASES_NOT_ALLOWED_TO_CANCEL_FROM:
|
if build.phase in PHASES_NOT_ALLOWED_TO_CANCEL_FROM:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
build.phase = BUILD_PHASE.CANCELLED
|
return build_canceller.try_cancel_build(build.uuid)
|
||||||
build.save()
|
|
||||||
|
|
||||||
if not build_canceller.try_cancel_build(build.uuid):
|
|
||||||
build.phase = original_phase
|
|
||||||
build.save()
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
return cancel_build
|
return cancel_build
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,22 +206,23 @@ def cancel_repository_build(build, build_queue):
|
||||||
|
|
||||||
cancel_builds = [create_cancel_build_in_queue(build, build_queue),
|
cancel_builds = [create_cancel_build_in_queue(build, build_queue),
|
||||||
create_cancel_build_in_manager(build, build_canceller), ]
|
create_cancel_build_in_manager(build, build_canceller), ]
|
||||||
|
original_phase = build.phase
|
||||||
for cancelled in cancel_builds:
|
for cancelled in cancel_builds:
|
||||||
if cancelled():
|
if cancelled():
|
||||||
# Delete the build row.
|
build.phase = BUILD_PHASE.CANCELLED
|
||||||
# TODO Charlie 2016-11-11 Add in message that says build was cancelled and remove the delete build.
|
build.save()
|
||||||
build.delete_instance()
|
|
||||||
return True
|
return True
|
||||||
|
build.phase = original_phase
|
||||||
|
build.save()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_archivable_build():
|
def get_archivable_build():
|
||||||
presumed_dead_date = datetime.utcnow() - PRESUMED_DEAD_BUILD_AGE
|
presumed_dead_date = datetime.utcnow() - PRESUMED_DEAD_BUILD_AGE
|
||||||
|
|
||||||
candidates = (RepositoryBuild
|
candidates = (RepositoryBuild
|
||||||
.select(RepositoryBuild.id)
|
.select(RepositoryBuild.id)
|
||||||
.where((RepositoryBuild.phase == BUILD_PHASE.COMPLETE) |
|
.where((RepositoryBuild.phase << ARCHIVABLE_BUILD_PHASES) |
|
||||||
(RepositoryBuild.phase == BUILD_PHASE.ERROR) |
|
|
||||||
(RepositoryBuild.started < presumed_dead_date),
|
(RepositoryBuild.started < presumed_dead_date),
|
||||||
RepositoryBuild.logs_archived == False)
|
RepositoryBuild.logs_archived == False)
|
||||||
.limit(50)
|
.limit(50)
|
||||||
|
|
|
@ -318,7 +318,7 @@ class RepositoryBuildResource(RepositoryParamResource):
|
||||||
@require_repo_admin
|
@require_repo_admin
|
||||||
@nickname('cancelRepoBuild')
|
@nickname('cancelRepoBuild')
|
||||||
def delete(self, namespace, repository, build_uuid):
|
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:
|
try:
|
||||||
build = model.build.get_repository_build(build_uuid)
|
build = model.build.get_repository_build(build_uuid)
|
||||||
except model.build.InvalidRepositoryBuildException:
|
except model.build.InvalidRepositoryBuildException:
|
||||||
|
|
|
@ -440,6 +440,8 @@ def build_status_badge(namespace_name, repo_name):
|
||||||
status_name = 'ready'
|
status_name = 'ready'
|
||||||
elif recent_build and recent_build.phase == 'error':
|
elif recent_build and recent_build.phase == 'error':
|
||||||
status_name = 'failed'
|
status_name = 'failed'
|
||||||
|
elif recent_build and recent_build.phase == 'cancelled':
|
||||||
|
status_name = 'cancelled'
|
||||||
elif recent_build and recent_build.phase != 'complete':
|
elif recent_build and recent_build.phase != 'complete':
|
||||||
status_name = 'building'
|
status_name = 'building'
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -21,3 +21,7 @@
|
||||||
.build-state-icon .complete {
|
.build-state-icon .complete {
|
||||||
color: #2fcc66;
|
color: #2fcc66;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.build-state-icon .cancelled {
|
||||||
|
color: #9b9b9b;
|
||||||
|
}
|
||||||
|
|
|
@ -5,5 +5,6 @@
|
||||||
<i class="fa fa-times-circle" ng-if="build.phase == 'error'"></i>
|
<i class="fa fa-times-circle" ng-if="build.phase == 'error'"></i>
|
||||||
<i class="fa fa-exclamation-circle" ng-if="build.phase == 'expired'"></i>
|
<i class="fa fa-exclamation-circle" ng-if="build.phase == 'expired'"></i>
|
||||||
<i class="fa fa-exclamation-circle" ng-if="build.phase == 'internalerror'"></i>
|
<i class="fa fa-exclamation-circle" ng-if="build.phase == 'internalerror'"></i>
|
||||||
|
<i class="fa fa-minus-circle" ng-if="build.phase == 'cancelled'"></i>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -12,10 +12,10 @@ angular.module('quay').directive('buildMiniStatus', function () {
|
||||||
'build': '=build',
|
'build': '=build',
|
||||||
'isAdmin': '=isAdmin'
|
'isAdmin': '=isAdmin'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element) {
|
controller: function($scope, $element, BuildService) {
|
||||||
$scope.isBuilding = function(build) {
|
$scope.isBuilding = function(build) {
|
||||||
if (!build) { return true; }
|
if (!build) { return true; }
|
||||||
return build.phase != 'complete' && build.phase != 'error';
|
return BuildService.isActive(build)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
* Service which provides helper methods for reasoning about builds.
|
* Service which provides helper methods for reasoning about builds.
|
||||||
*/
|
*/
|
||||||
angular.module('quay').factory('BuildService', [function() {
|
angular.module('quay').factory('BuildService', [function() {
|
||||||
var buildService = {}
|
var buildService = {};
|
||||||
buildService.isActive = function(build) {
|
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) {
|
buildService.getBuildMessage = function(phase) {
|
||||||
|
@ -51,6 +51,10 @@ angular.module('quay').factory('BuildService', [function() {
|
||||||
|
|
||||||
case 'internalerror':
|
case 'internalerror':
|
||||||
return 'An internal system error occurred while building; the build will be retried in the next few minutes.';
|
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.';
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,7 @@
|
||||||
<i class="fa fa-clock-o"></i> Show Timestamps
|
<i class="fa fa-clock-o"></i> Show Timestamps
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="cor-option" option-click="askCancelBuild(build)"
|
<span class="cor-option" option-click="askCancelBuild(build)">
|
||||||
ng-if="build.phase == 'waiting'">
|
|
||||||
<i class="fa fa-times"></i> Cancel Build
|
<i class="fa fa-times"></i> Cancel Build
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -2191,7 +2191,8 @@ class TestRepositoryBuildResource(ApiTestCase):
|
||||||
json = self.getJsonResponse(RepositoryBuildList,
|
json = self.getJsonResponse(RepositoryBuildList,
|
||||||
params=dict(repository=ADMIN_ACCESS_USER + '/simple'))
|
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.
|
# Check for the build's queue item.
|
||||||
try:
|
try:
|
||||||
|
|
Reference in a new issue