From ab5513268ba4c1ac93f104eec86561d7d7132a7b Mon Sep 17 00:00:00 2001 From: AbdulRahman AlHamali Date: Thu, 25 Mar 2021 15:06:51 -0400 Subject: [PATCH 1/7] allow ignore failure --- .../modules/core/src/domain/IOrchestratedItem.ts | 1 + .../modules/core/src/help/help.contents.ts | 4 ++++ .../orchestratedItem.transformer.ts | 3 +++ .../config/stages/common/executionSummary.html | 16 +++++++++++++++- .../core/src/pipeline/config/stages/stage.html | 1 + .../pipeline/details/stageSummary.component.ts | 8 ++++++++ 6 files changed, 32 insertions(+), 1 deletion(-) diff --git a/app/scripts/modules/core/src/domain/IOrchestratedItem.ts b/app/scripts/modules/core/src/domain/IOrchestratedItem.ts index f342e6e638d..89f1de975ea 100644 --- a/app/scripts/modules/core/src/domain/IOrchestratedItem.ts +++ b/app/scripts/modules/core/src/domain/IOrchestratedItem.ts @@ -27,5 +27,6 @@ export interface IOrchestratedItem extends ITimedItem { isCanceled: boolean; isSuspended: boolean; isPaused: boolean; + isHalted: boolean; runningTime: string; } diff --git a/app/scripts/modules/core/src/help/help.contents.ts b/app/scripts/modules/core/src/help/help.contents.ts index 5ef64d38fbb..1e91edcb1da 100644 --- a/app/scripts/modules/core/src/help/help.contents.ts +++ b/app/scripts/modules/core/src/help/help.contents.ts @@ -80,6 +80,10 @@ const helpContents: { [key: string]: string } = {

When this option is enabled, stage will only execute when the supplied expression evaluates true.

The expression does not need to be wrapped in \${ and }.

If this expression evaluates to false, the stages following this stage will still execute.

`, + 'pipeline.config.allowIgnoreFailure': ` +

When this option is enabled, users will be able to manually ignore the stage if it failed.

+

You should use this only for stages that other stages don't closely depend on.

+

For example, if later stages depend on the outputs of this stage, you should not allow that option.

`, 'pipeline.config.checkPreconditions.failPipeline': `

Checked - the overall pipeline will fail whenever this precondition is false.

Unchecked - the overall pipeline will continue executing but this particular branch will stop.

`, diff --git a/app/scripts/modules/core/src/orchestratedItem/orchestratedItem.transformer.ts b/app/scripts/modules/core/src/orchestratedItem/orchestratedItem.transformer.ts index 54eb42f14de..4c8e40408c7 100644 --- a/app/scripts/modules/core/src/orchestratedItem/orchestratedItem.transformer.ts +++ b/app/scripts/modules/core/src/orchestratedItem/orchestratedItem.transformer.ts @@ -83,6 +83,9 @@ export class OrchestratedItemTransformer { isPaused: { get: (): boolean => item.status === 'PAUSED', }, + isHalted: { + get: (): boolean => ['TERMINAL', 'CANCELED', 'STOPPED'].includes(item.status), + }, status: { // Returns either SUCCEEDED, RUNNING, FAILED, CANCELED, or NOT_STARTED get: (): string => this.normalizeStatus(item), diff --git a/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html b/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html index 970065b9a2f..5041ce16045 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html +++ b/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html @@ -2,7 +2,7 @@
Stage details: {{stageSummary.name || stageSummary.type }} -
+
@@ -49,6 +59,10 @@
+ Failure ignored manually by {{stage.ignoreFailureDetails.by}} — {{stage.ignoreFailureDetails.time | + timestamp}} Previous exception: {{stage.ignoreFailureDetails.previousException}} +
diff --git a/app/scripts/modules/core/src/pipeline/config/stages/stage.html b/app/scripts/modules/core/src/pipeline/config/stages/stage.html index 4e39f4c955a..960bca3bc96 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/stage.html +++ b/app/scripts/modules/core/src/pipeline/config/stages/stage.html @@ -131,6 +131,7 @@

> + Date: Thu, 25 Mar 2021 15:07:13 -0400 Subject: [PATCH 2/7] add the directive --- .../allowIgnoreFailure.directive.html | 13 +++++++++++++ .../allowIgnoreFailure.directive.js | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.html create mode 100644 app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.js diff --git a/app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.html b/app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.html new file mode 100644 index 00000000000..38ae6430972 --- /dev/null +++ b/app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.html @@ -0,0 +1,13 @@ +
+
+
+
+ +
+
+
+
diff --git a/app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.js b/app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.js new file mode 100644 index 00000000000..6e432013d7f --- /dev/null +++ b/app/scripts/modules/core/src/pipeline/config/stages/allowIgnoreFailure/allowIgnoreFailure.directive.js @@ -0,0 +1,16 @@ +'use strict'; + +import { module } from 'angular'; + +export const CORE_PIPELINE_CONFIG_STAGES_ALLOWIGNOREFAILURE_ALLOWIGNOREFAILURE_DIRECTIVE = + 'spinnaker.core.pipeline.stage.allowIgnoreFailure.directive'; +export const name = CORE_PIPELINE_CONFIG_STAGES_ALLOWIGNOREFAILURE_ALLOWIGNOREFAILURE_DIRECTIVE; // for backwards compatibility +module(CORE_PIPELINE_CONFIG_STAGES_ALLOWIGNOREFAILURE_ALLOWIGNOREFAILURE_DIRECTIVE, []).component( + 'allowIgnoreFailure', + { + bindings: { + stage: '<', + }, + templateUrl: require('./allowIgnoreFailure.directive.html'), + }, +); From eda3856959668c96db105f6f05662ce6ec003476 Mon Sep 17 00:00:00 2001 From: AbdulRahman AlHamali Date: Thu, 25 Mar 2021 16:53:00 -0400 Subject: [PATCH 3/7] import module --- .../modules/core/src/pipeline/config/stages/stage.module.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/scripts/modules/core/src/pipeline/config/stages/stage.module.js b/app/scripts/modules/core/src/pipeline/config/stages/stage.module.js index 5818e956ed2..ac1d79f9793 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/stage.module.js +++ b/app/scripts/modules/core/src/pipeline/config/stages/stage.module.js @@ -18,6 +18,7 @@ import { EditStageJsonModal } from './common/EditStageJsonModal'; import { BASE_EXECUTION_DETAILS_CTRL } from './common/baseExecutionDetails.controller'; import { CORE_PIPELINE_CONFIG_STAGES_COMMON_STAGECONFIGFIELD_STAGECONFIGFIELD_DIRECTIVE } from './common/stageConfigField/stageConfigField.directive'; import { CORE_PIPELINE_CONFIG_STAGES_FAILONFAILEDEXPRESSIONS_FAILONFAILEDEXPRESSIONS_DIRECTIVE } from './failOnFailedExpressions/failOnFailedExpressions.directive'; +import { CORE_PIPELINE_CONFIG_STAGES_ALLOWIGNOREFAILURE_ALLOWIGNOREFAILURE_DIRECTIVE } from './allowIgnoreFailure/allowIgnoreFailure.directive'; import { CORE_PIPELINE_CONFIG_STAGES_OPTIONALSTAGE_OPTIONALSTAGE_DIRECTIVE } from './optionalStage/optionalStage.directive'; import { OVERRRIDE_FAILURE } from './overrideFailure/overrideFailure.module'; import { OVERRIDE_TIMEOUT_COMPONENT } from './overrideTimeout/overrideTimeout.module'; @@ -35,6 +36,7 @@ module(CORE_PIPELINE_CONFIG_STAGES_STAGE_MODULE, [ CORE_PIPELINE_CONFIG_STAGES_OPTIONALSTAGE_OPTIONALSTAGE_DIRECTIVE, CORE_PIPELINE_CONFIG_STAGES_FAILONFAILEDEXPRESSIONS_FAILONFAILEDEXPRESSIONS_DIRECTIVE, CORE_PIPELINE_CONFIG_STAGES_COMMON_STAGECONFIGFIELD_STAGECONFIGFIELD_DIRECTIVE, + CORE_PIPELINE_CONFIG_STAGES_ALLOWIGNOREFAILURE_ALLOWIGNOREFAILURE_DIRECTIVE ]) .directive('pipelineConfigStage', function () { return { From f6751a243bda78a99433f6d573335520e6093985 Mon Sep 17 00:00:00 2001 From: AbdulRahman AlHamali Date: Thu, 25 Mar 2021 15:39:16 -0400 Subject: [PATCH 4/7] add ignore action --- .../details/stageSummary.component.ts | 26 +++++++++++++++++++ .../src/pipeline/service/execution.service.ts | 4 +++ 2 files changed, 30 insertions(+) diff --git a/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts b/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts index 161a1d685c2..9432b3cef4b 100644 --- a/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts +++ b/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts @@ -109,6 +109,32 @@ export class StageSummaryController implements IController { return topLevelStage; } + public openIgnoreStageFailureModal(): void { + ConfirmationModalService.confirm({ + header: 'Really ignore this failure?', + buttonText: 'Ignore', + askForReason: true, + submitJustWithReason: true, + body: `
+ Warning: Ignoring this failure may have unpredictable results. +
    +
  • Downstream stages that depend on the outputs of this stage may fail or behave unexpectedly.
  • +
+
+ `, + submitMethod: (reason: string) => + this.executionService + .ignoreStageFailureInExecution(this.execution.id, this.stage.id, reason) + .then(() => + this.executionService.waitUntilExecutionMatches(this.execution.id, (execution) => { + const updatedStage = execution.stages.find((stage) => stage.id === this.stage.id); + return updatedStage && updatedStage.status === 'FAILED_CONTINUE'; + }), + ) + .then((updated) => this.executionService.updateExecution(this.application, updated)), + }); + } + public openManualSkipStageModal(): void { const topLevelStage = this.getTopLevelStage(); ConfirmationModalService.confirm({ diff --git a/app/scripts/modules/core/src/pipeline/service/execution.service.ts b/app/scripts/modules/core/src/pipeline/service/execution.service.ts index c3e958ef9d1..4a3295e3643 100644 --- a/app/scripts/modules/core/src/pipeline/service/execution.service.ts +++ b/app/scripts/modules/core/src/pipeline/service/execution.service.ts @@ -538,6 +538,10 @@ export class ExecutionService { return REST('/pipelines').path(executionId, 'stages', stageId).patch(data); } + public ignoreStageFailureInExecution(executionId: string, stageId: string, reason: string): PromiseLike { + return REST('/pipelines').path(executionId, 'stages', stageId, 'ignoreFailure').put({ reason }); + } + private stringifyExecution(execution: IExecution): string { const transient = { ...execution }; transient.stages = transient.stages.filter((s) => s.status !== 'SUCCEEDED' && s.status !== 'NOT_STARTED'); From c6db1f0208a53d040b52ff478ec5a77dedceed71 Mon Sep 17 00:00:00 2001 From: AbdulRahman AlHamali Date: Thu, 25 Mar 2021 15:53:15 -0400 Subject: [PATCH 5/7] fix reason --- .../core/src/pipeline/details/stageSummary.component.ts | 2 +- .../modules/core/src/pipeline/service/execution.service.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts b/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts index 9432b3cef4b..12e404c7532 100644 --- a/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts +++ b/app/scripts/modules/core/src/pipeline/details/stageSummary.component.ts @@ -122,7 +122,7 @@ export class StageSummaryController implements IController { `, - submitMethod: (reason: string) => + submitMethod: (reason: object) => this.executionService .ignoreStageFailureInExecution(this.execution.id, this.stage.id, reason) .then(() => diff --git a/app/scripts/modules/core/src/pipeline/service/execution.service.ts b/app/scripts/modules/core/src/pipeline/service/execution.service.ts index 4a3295e3643..49868098c83 100644 --- a/app/scripts/modules/core/src/pipeline/service/execution.service.ts +++ b/app/scripts/modules/core/src/pipeline/service/execution.service.ts @@ -538,8 +538,8 @@ export class ExecutionService { return REST('/pipelines').path(executionId, 'stages', stageId).patch(data); } - public ignoreStageFailureInExecution(executionId: string, stageId: string, reason: string): PromiseLike { - return REST('/pipelines').path(executionId, 'stages', stageId, 'ignoreFailure').put({ reason }); + public ignoreStageFailureInExecution(executionId: string, stageId: string, reason: object): PromiseLike { + return REST('/pipelines').path(executionId, 'stages', stageId, 'ignoreFailure').put(reason); } private stringifyExecution(execution: IExecution): string { From 88cb6a48cd63d570dd1680ae03d3ec8feb976b34 Mon Sep 17 00:00:00 2001 From: AbdulRahman AlHamali Date: Thu, 25 Mar 2021 16:05:03 -0400 Subject: [PATCH 6/7] fix display of details --- .../src/pipeline/config/stages/common/executionSummary.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html b/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html index 5041ce16045..9b19327b801 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html +++ b/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html @@ -60,8 +60,9 @@
- Failure ignored manually by {{stage.ignoreFailureDetails.by}} — {{stage.ignoreFailureDetails.time | - timestamp}} Previous exception: {{stage.ignoreFailureDetails.previousException}} + Failure ignored manually by {{stage.context.ignoreFailureDetails.by}} — + {{stage.context.ignoreFailureDetails.time | timestamp}} Previous exception: + {{stage.context.ignoreFailureDetails.previousException}}
From 2b7662fae773a567fe7d1030c3e61406ff77a75a Mon Sep 17 00:00:00 2001 From: AbdulRahman AlHamali Date: Thu, 25 Mar 2021 16:14:18 -0400 Subject: [PATCH 7/7] optional display of exception --- .../src/pipeline/config/stages/common/executionSummary.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html b/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html index 9b19327b801..2afbfe10617 100644 --- a/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html +++ b/app/scripts/modules/core/src/pipeline/config/stages/common/executionSummary.html @@ -61,8 +61,8 @@
Failure ignored manually by {{stage.context.ignoreFailureDetails.by}} — - {{stage.context.ignoreFailureDetails.time | timestamp}} Previous exception: - {{stage.context.ignoreFailureDetails.previousException}} + {{stage.context.ignoreFailureDetails.time | timestamp}} {{stage.context.ignoreFailureDetails.previousException? + 'Previous exception:' + stage.context.ignoreFailureDetails.previousException : ''}}