Skip to content

Commit

Permalink
keptn#4073 fixed sequence and trace status for traces without a stage (
Browse files Browse the repository at this point in the history
…keptn#4278)

* keptn#4073 fixed sequence and trace status for traces without a stage

Signed-off-by: Klaus Strießnig <k.striessnig@gmail.com>

* keptn#4073 fixed success status

Signed-off-by: Klaus Strießnig <k.striessnig@gmail.com>
  • Loading branch information
Kirdock authored Jun 10, 2021
1 parent f7af2d1 commit 09a2563
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
[stage]="stage"
[evaluation]="deployment.getEvaluation(stage)"
[isSelected]="selectedStage === stage"
[success]="!deployment.sequence.hasPendingApproval(stage) && stage !== deployment.sequence.isFaulty()"
[error]="stage === deployment.sequence.isFaulty()"
[class.warning]="stage === deployment.sequence.isWarning()"
[success]="!deployment.sequence.hasPendingApproval(stage) && !deployment.sequence.isFaulty(stage)"
[error]="deployment.sequence.isFaulty(stage)"
[class.warning]="deployment.sequence.isWarning(stage)"
[highlight]="deployment.sequence.hasPendingApproval(stage)"
[fill]="deployment.hasStage(stage)"
(click)="$event.stopPropagation(); selectStage(stage)"></ktb-stage-badge>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
<p class="m-0 mr-1 small" *ngIf="event.getStages().length > 0">in</p>
<ng-container *ngFor="let stage of event.getStages();">
<ktb-stage-badge [stage]="stage" [evaluation]="event.getEvaluation(stage)"
[success]="event.getFirstTraceOfStage(stage).isFinished() && stage != event.isFaulty()"
[error]="stage == event.isFaulty()" [class.warning]="stage == event.isWarning()"
[success]="event.getFirstTraceOfStage(stage).isFinished() && !event.isFaulty(stage)"
[error]="event.isFaulty(stage)" [class.warning]="event.isWarning(stage)"
[highlight]="event.hasPendingApproval(stage)"
(click)="$event.stopPropagation();selectEvent(event, stage)"></ktb-stage-badge>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@
<div class="stage-info">
<dt-icon *ngIf="!currentSequence.getLastSequenceOfStage(stage).isLoading(); else showLoading" class="event-icon"
[name]="currentSequence.getFirstTraceOfStage(stage).isFinished() ? currentSequence.getIcon() : currentSequence.getLastTrace().getIcon()"
[class.error]="stage === currentSequence.isFaulty()"
[class.success]="currentSequence.getFirstTraceOfStage(stage).isFinished() && stage !== currentSequence.isFaulty()"
[class.error]="currentSequence.isFaulty(stage)"
[class.success]="currentSequence.getFirstTraceOfStage(stage).isFinished() && !currentSequence.isFaulty(stage)"
[class.highlight]="currentSequence.hasPendingApproval(stage)"></dt-icon>
<ng-template #showLoading>
<button class="m-0 p-0" dt-button disabled variant="nested">
<dt-loading-spinner aria-label="Task is running..."></dt-loading-spinner>
</button>
</ng-template>
<span class="stage-text"
[class.error]="stage === currentSequence.isFaulty()"
[class.success]="!currentSequence.hasPendingApproval(stage) && stage !== currentSequence.isFaulty()"
[class.error]="currentSequence.isFaulty(stage)"
[class.success]="!currentSequence.hasPendingApproval(stage) && !currentSequence.isFaulty(stage)"
[class.highlight]="currentSequence.hasPendingApproval(stage)"
[class.warning]="stage === currentSequence.isWarning()"
[class.warning]="currentSequence.isWarning(stage)"
[class.focused]="stage === selectedStage"
[textContent]="stage"></span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
<div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="5px" *ngIf="row.getRecentSequence() as currentSequence">
<dt-icon *ngIf="!currentSequence.getLastSequenceOfStage(row.stage).isLoading() || currentSequence.hasPendingApproval(row.stage); else showLoading" class="event-icon"
[name]="currentSequence.getFirstTraceOfStage(row.stage).isFinished() ? currentSequence.getIcon() : currentSequence.getLastTrace().getIcon()"
[class.error]="row.stage === currentSequence.isFaulty()"
[class.success]="currentSequence.getFirstTraceOfStage(row.stage).isFinished() && row.stage !== currentSequence.isFaulty()"
[class.error]="currentSequence.isFaulty(row.stage)"
[class.success]="currentSequence.getFirstTraceOfStage(row.stage).isFinished() && !currentSequence.isFaulty(row.stage)"
[class.highlight]="currentSequence.hasPendingApproval(row.stage)"></dt-icon>
<ng-template #showLoading>
<button class="m-0 p-0" dt-button disabled variant="nested">
Expand Down
39 changes: 24 additions & 15 deletions bridge/client/app/_models/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,26 @@ import {EventTypes} from "./event-types";
export class Root extends Trace {
traces: Trace[] = [];

isFaulty(): string {
isFaulty(stageName?: string): boolean {
// a Sequence is faulty, if there is a sequence that is faulty, but no other sequence that is successful on the same stage
let result: string = null;
this.getStages().forEach(stage => {
let stageTraces = this.traces.filter(t => t.getStage() == stage);
if(stageTraces.some(t => t.isFaulty() != null) && !stageTraces.some(t => t.isSuccessful() != null))
result = stage;
});
let result = false;
const stages = stageName ? [stageName] : this.getStages();
if (stages.length > 0) {
stages.forEach(stage => {
result ||= this.areTracesFaulty(stage);
});
}
else {
result = this.areTracesFaulty();
}
return result;
}

private areTracesFaulty(stageName?: string): boolean {
const stageTraces = stageName ? this.traces.filter(t => t.getStage() === stageName) : this.traces;
return stageTraces.some(t => t.isFaulty()) && !stageTraces.some(t => t.isSuccessful());
}

isStarted(): boolean {
return this.traces.length === 0 ? false : this.traces[this.traces.length-1].isStarted();
}
Expand All @@ -37,17 +46,17 @@ export class Root extends Trace {
return this.traces.reduce((result: string, trace: Trace) => result ? result : trace.isDeployment(), null);
}

isWarning(): string {
return this.traces.reduce((result: string, trace: Trace) => trace.isWarning() ? trace.data.stage : result, null);
isWarning(stageName?: string): boolean {
return this.traces.reduce((result: boolean, trace: Trace) => trace.isWarning(stageName), false);
}

isSuccessful(): string {
return this.traces.reduce((result: string, trace: Trace) => {
if(result)
return trace.isFaulty() ? null : result;
isSuccessful(stageName?: string): boolean {
return this.traces.reduce((result: boolean, trace: Trace) => {
if (result)
return !trace.isFaulty(stageName);
else
return trace.isSuccessful() ? trace.data.stage : result
}, null);
return trace.isSuccessful(stageName);
}, false);
}

hasPendingApproval(stage: string): boolean {
Expand Down
30 changes: 15 additions & 15 deletions bridge/client/app/_models/trace.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2124,48 +2124,48 @@ describe('Trace', () => {
expect(rootTraces[0].getLabel()).toBe('create', 'Label for trace "sh.keptn.event.service.create.started" should be "create"');
expect(rootTraces[0].getShortImageName()).toBe(undefined);
expect(rootTraces[0].getIcon()).toBe('information', 'Icon for trace "sh.keptn.event.service.create.started" should be "information"');
expect(rootTraces[0].isFaulty()).toBe(null);
expect(rootTraces[0].isWarning()).toBe(null);
expect(rootTraces[0].isSuccessful()).toBe(null);
expect(rootTraces[0].isFaulty()).toBe(false);
expect(rootTraces[0].isWarning()).toBe(false);
expect(rootTraces[0].isSuccessful()).toBe(false);
expect(rootTraces[0].getProject()).toBe('sockshop');
expect(rootTraces[0].getService()).toBe('carts');

expect(rootTraces[1].type).toBe('sh.keptn.event.dev.artifact-delivery.triggered');
expect(rootTraces[1].getLabel()).toBe('artifact-delivery', 'Label for trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "artifact-delivery"');
expect(rootTraces[1].getShortImageName()).toBe('carts:0.10.1', 'ShortImageName for first trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "carts:0.10.1"');
expect(rootTraces[1].getIcon()).toBe('duplicate', 'Icon for trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "duplicate"');
expect(rootTraces[1].isFaulty()).toBe(null);
expect(rootTraces[1].isWarning()).toBe(null);
expect(rootTraces[1].isSuccessful()).toBe(null);
expect(rootTraces[1].isFaulty()).toBe(false);
expect(rootTraces[1].isWarning()).toBe(false);
expect(rootTraces[1].isSuccessful()).toBe(false);
expect(rootTraces[1].getProject()).toBe('sockshop');
expect(rootTraces[1].getService()).toBe('carts');

expect(rootTraces[2].type).toBe('sh.keptn.event.dev.artifact-delivery.triggered');
expect(rootTraces[2].getLabel()).toBe('artifact-delivery', 'Label for trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "artifact-delivery"');
expect(rootTraces[2].getShortImageName()).toBe('carts:0.10.2', 'ShortImageName for second trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "carts:0.10.2"');
expect(rootTraces[2].getIcon()).toBe('duplicate', 'Icon for trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "duplicate"');
expect(rootTraces[2].isFaulty()).toBe(null);
expect(rootTraces[2].isWarning()).toBe(null);
expect(rootTraces[2].isSuccessful()).toBe(null);
expect(rootTraces[2].isFaulty()).toBe(false);
expect(rootTraces[2].isWarning()).toBe(false);
expect(rootTraces[2].isSuccessful()).toBe(false);
expect(rootTraces[2].getProject()).toBe('sockshop');
expect(rootTraces[2].getService()).toBe('carts');

expect(rootTraces[8].type).toBe('sh.keptn.event.dev.artifact-delivery.triggered');
expect(rootTraces[8].getLabel()).toBe('artifact-delivery', 'Label for trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "artifact-delivery"');
expect(rootTraces[8].getShortImageName()).toBe(undefined, 'ShortImageName for third trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "undefined"');
expect(rootTraces[8].getIcon()).toBe('duplicate', 'Icon for trace "sh.keptn.event.dev.artifact-delivery.triggered" should be "duplicate"');
expect(rootTraces[8].isFaulty()).toBe(null);
expect(rootTraces[8].isWarning()).toBe(null);
expect(rootTraces[8].isSuccessful()).toBe(null);
expect(rootTraces[8].isFaulty()).toBe(false);
expect(rootTraces[8].isWarning()).toBe(false);
expect(rootTraces[8].isSuccessful()).toBe(false);
expect(rootTraces[8].getProject()).toBe('keptn');
expect(rootTraces[8].getService()).toBe('control-plane');

expect(evaluationTraces[0].type).toBe('sh.keptn.event.evaluation.finished');
expect(evaluationTraces[0].getLabel()).toBe('evaluation', 'Label for trace "sh.keptn.event.evaluation.finished" should be "evaluation"');
expect(evaluationTraces[0].getIcon()).toBe('traffic-light', 'Icon for trace "sh.keptn.event.evaluation.finished" should be "traffic-light"');
expect(evaluationTraces[0].isFaulty()).toBe(null);
expect(evaluationTraces[0].isWarning()).toBe(null);
expect(evaluationTraces[0].isSuccessful()).toBe(evaluationTraces[0].data.stage, 'Successful evaluation should return true');
expect(evaluationTraces[0].isFaulty()).toBe(false);
expect(evaluationTraces[0].isWarning()).toBe(false);
expect(evaluationTraces[0].isSuccessful(evaluationTraces[0].data.stage)).toBe(true, 'Successful evaluation should return true');
expect(evaluationTraces[0].getProject()).toBe('sockshop');
expect(evaluationTraces[0].getService()).toBe('carts');
}));
Expand Down
30 changes: 15 additions & 15 deletions bridge/client/app/_models/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,14 @@ class Trace {
State: string;
};

isFaulty(): string {
let result: string = null;
if(this.data) {
if(this.isFailed() ||
isFaulty(stageName?: string): boolean {
let result = false;
if (this.data) {
if (this.isFailed() ||
(this.isProblem() && !this.isProblemResolvedOrClosed()) ||
(this.isRemediation() && !this.isSuccessfulRemediation()) ||
this.traces.some(t => t.isFaulty() != null)) {
result = this.data.stage;
this.traces.some(t => t.isFaulty())) {
result = stageName ? this.data.stage === stageName : true;
}
}
return result;
Expand All @@ -137,20 +137,20 @@ class Trace {
return result;
}

isWarning(): string {
let result: string = null;
if(this.getFinishedEvent()?.data.result == ResultTypes.WARNING) {
result = this.data.stage;
isWarning(stageName?: string): boolean {
let result = false;
if (this.getFinishedEvent()?.data.result === ResultTypes.WARNING) {
result = stageName ? this.data.stage === stageName : true;
}
return result;
}

isSuccessful(): string {
let result: string = null;
if ( this.isFinished() && this.getFinishedEvent()?.data.result === ResultTypes.PASSED || this.isApprovalFinished() && this.isApproved() || this.isProblem() && this.isProblemResolvedOrClosed() || this.isSuccessfulRemediation()) {
result = this.data.stage;
isSuccessful(stageName?: string): boolean {
let result = false;
if (this.isFinished() && this.getFinishedEvent()?.data.result === ResultTypes.PASSED || this.isApprovalFinished() && this.isApproved() || this.isProblem() && this.isProblemResolvedOrClosed() || this.isSuccessfulRemediation()) {
result = stageName ? this.data.stage === stageName : true;
}
return !this.isFaulty() && result ? result : null;
return !this.isFaulty() && result;
}

public isFailed(): boolean {
Expand Down
2 changes: 1 addition & 1 deletion bridge/client/app/_services/data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ export class DataService {
map(result => result.events||[]),
mergeMap((roots) => this.rootMapper(roots))
).subscribe((roots: Root[]) => {
if(!project.sequences?.length && roots.length < this.DEFAULT_SEQUENCE_PAGE_SIZE) {
if(!fromTime && !project.sequences?.length && roots.length < this.DEFAULT_SEQUENCE_PAGE_SIZE) {
project.allSequencesLoaded = true;
}
project.sequences = [...roots||[], ...project.sequences||[]].sort(DateUtil.compareTraceTimesAsc);
Expand Down

0 comments on commit 09a2563

Please sign in to comment.