@spinnaker/core 2026.0.3 → 2026.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ci/igor.service.d.ts +0 -1
- package/dist/domain/ITrigger.d.ts +1 -11
- package/dist/index.js +36 -36
- package/dist/index.js.map +1 -1
- package/dist/managed/graphql/client.d.ts +1 -1
- package/dist/managed/graphql/graphql-sdk.d.ts +9 -9
- package/dist/pipeline/config/stages/bakeManifest/ManifestRenderers.d.ts +2 -2
- package/dist/pipeline/config/triggers/Triggers.d.ts +1 -0
- package/dist/pipeline/config/triggers/index.d.ts +0 -1
- package/package.json +3 -3
- package/src/application/search/react-ultimate-pagination.d.ts +1 -1
- package/src/ci/igor.service.ts +0 -1
- package/src/domain/ITrigger.ts +1 -13
- package/src/help/help.contents.ts +1 -9
- package/src/pipeline/config/pipelineConfigView.html +1 -0
- package/src/pipeline/config/stages/bakeManifest/ManifestRenderers.ts +2 -2
- package/src/pipeline/config/stages/createLoadBalancer/createLoadBalancerStage.js +45 -28
- package/src/pipeline/config/stages/createLoadBalancer/createLoadBalancerStage.spec.js +101 -0
- package/src/pipeline/config/triggers/MetadataPageContent.spec.tsx +140 -0
- package/src/pipeline/config/triggers/Triggers.spec.tsx +80 -0
- package/src/pipeline/config/triggers/Triggers.tsx +6 -1
- package/src/pipeline/config/triggers/index.ts +0 -1
- package/src/pipeline/config/triggers/triggers.module.ts +1 -0
- package/src/pipeline/pipeline.module.ts +0 -2
- package/src/presentation/ReactModal.spec.tsx +72 -0
- package/src/presentation/ReactModal.tsx +12 -2
- package/dist/pipeline/config/stages/wercker/WerckerExecutionLabel.d.ts +0 -7
- package/dist/pipeline/config/stages/wercker/modal/addParameter.controller.modal.d.ts +0 -10
- package/dist/pipeline/config/stages/wercker/werckerExecutionDetails.controller.d.ts +0 -18
- package/dist/pipeline/config/stages/wercker/werckerStage.d.ts +0 -51
- package/dist/pipeline/config/stages/wercker/werckerStage.module.d.ts +0 -1
- package/dist/pipeline/config/triggers/wercker/WerckerTrigger.d.ts +0 -13
- package/dist/pipeline/config/triggers/wercker/WerckerTriggerTemplate.d.ts +0 -7
- package/dist/pipeline/config/triggers/wercker/wercker.trigger.d.ts +0 -1
- package/src/pipeline/config/stages/wercker/WerckerExecutionLabel.tsx +0 -32
- package/src/pipeline/config/stages/wercker/modal/addParameter.controller.modal.ts +0 -19
- package/src/pipeline/config/stages/wercker/modal/addParameter.html +0 -48
- package/src/pipeline/config/stages/wercker/werckerExecutionDetails.controller.spec.ts +0 -79
- package/src/pipeline/config/stages/wercker/werckerExecutionDetails.controller.ts +0 -55
- package/src/pipeline/config/stages/wercker/werckerExecutionDetails.html +0 -79
- package/src/pipeline/config/stages/wercker/werckerStage.controller.spec.ts +0 -152
- package/src/pipeline/config/stages/wercker/werckerStage.html +0 -150
- package/src/pipeline/config/stages/wercker/werckerStage.module.ts +0 -18
- package/src/pipeline/config/stages/wercker/werckerStage.ts +0 -232
- package/src/pipeline/config/triggers/wercker/WerckerTrigger.tsx +0 -122
- package/src/pipeline/config/triggers/wercker/WerckerTriggerTemplate.tsx +0 -13
- package/src/pipeline/config/triggers/wercker/wercker.trigger.ts +0 -28
|
@@ -13,6 +13,7 @@ import { ReactInjector } from '../../../reactShims/react.injector';
|
|
|
13
13
|
export interface ITriggersProps {
|
|
14
14
|
application: Application;
|
|
15
15
|
pipeline: IPipeline;
|
|
16
|
+
pipelineConfig?: IPipeline;
|
|
16
17
|
fieldUpdated: () => void;
|
|
17
18
|
updatePipelineConfig: (changes: Partial<IPipeline>) => void;
|
|
18
19
|
revertCount: number;
|
|
@@ -54,7 +55,11 @@ export function Triggers(props: ITriggersProps) {
|
|
|
54
55
|
<NotificationsPageContent {...props} />
|
|
55
56
|
</PageSection>
|
|
56
57
|
<PageSection pageKey="description" label="Metadata" noWrapper={true}>
|
|
57
|
-
<MetadataPageContent
|
|
58
|
+
<MetadataPageContent
|
|
59
|
+
pipeline={props.pipelineConfig || props.pipeline}
|
|
60
|
+
updatePipelineConfig={props.updatePipelineConfig}
|
|
61
|
+
key={revertCountKLUDGE}
|
|
62
|
+
/>
|
|
58
63
|
</PageSection>
|
|
59
64
|
</PageNavigator>
|
|
60
65
|
);
|
|
@@ -56,7 +56,6 @@ import './config/stages/wait/waitStage';
|
|
|
56
56
|
import './config/stages/waitForCondition/waitForConditionStage';
|
|
57
57
|
import { CORE_PIPELINE_CONFIG_STAGES_WAITFORPARENTTASKS_WAITFORPARENTTASKS } from './config/stages/waitForParentTasks/waitForParentTasks';
|
|
58
58
|
import { WEBHOOK_STAGE_MODULE } from './config/stages/webhook/webhookStage.module';
|
|
59
|
-
import { WERCKER_STAGE_MODULE } from './config/stages/wercker/werckerStage.module';
|
|
60
59
|
import { PIPELINE_TEMPLATES_V2_STATES_CONFIG } from './config/templates/v2/pipelineTemplateV2.states';
|
|
61
60
|
import { EXECUTION_DETAILS_SECTION_NAV } from './details/executionDetailsSectionNav.component';
|
|
62
61
|
import { STAGE_FAILURE_MESSAGE_COMPONENT } from './details/stageFailureMessage.component';
|
|
@@ -87,7 +86,6 @@ module(PIPELINE_MODULE, [
|
|
|
87
86
|
CORE_PIPELINE_CONFIG_PIPELINECONFIG_MODULE,
|
|
88
87
|
GROUP_STAGE_MODULE,
|
|
89
88
|
TRAVIS_STAGE_MODULE,
|
|
90
|
-
WERCKER_STAGE_MODULE,
|
|
91
89
|
PRECONFIGUREDJOB_STAGE_MODULE,
|
|
92
90
|
WEBHOOK_STAGE_MODULE,
|
|
93
91
|
UNMATCHED_STAGE_TYPE_STAGE,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
3
|
+
|
|
4
|
+
import type { IModalComponentProps } from './modal';
|
|
5
|
+
import { ReactModal } from './ReactModal';
|
|
6
|
+
|
|
7
|
+
const TestModal = (_props: IModalComponentProps): JSX.Element => null;
|
|
8
|
+
|
|
9
|
+
const getLastRender = (renders: React.ReactElement[]): React.ReactElement =>
|
|
10
|
+
renders[renders.length - 1] as React.ReactElement;
|
|
11
|
+
|
|
12
|
+
const flushPromises = (): Promise<void> => Promise.resolve();
|
|
13
|
+
|
|
14
|
+
describe('ReactModal', () => {
|
|
15
|
+
it('resolves after the modal exit completes', async () => {
|
|
16
|
+
const renders: React.ReactElement[] = [];
|
|
17
|
+
spyOn(ReactDOM, 'render').and.callFake((element) => {
|
|
18
|
+
renders.push(element as React.ReactElement);
|
|
19
|
+
return null;
|
|
20
|
+
});
|
|
21
|
+
const unmountSpy = spyOn(ReactDOM, 'unmountComponentAtNode').and.returnValue(true);
|
|
22
|
+
|
|
23
|
+
let resolvedValue: string | null = null;
|
|
24
|
+
const promise = ReactModal.show(TestModal);
|
|
25
|
+
promise.then((value) => {
|
|
26
|
+
resolvedValue = value as string;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const initialModal = getLastRender(renders);
|
|
30
|
+
const closeModal = (initialModal.props.children as any).props.closeModal as (value?: string) => void;
|
|
31
|
+
closeModal('gce');
|
|
32
|
+
|
|
33
|
+
await flushPromises();
|
|
34
|
+
expect(resolvedValue).toBeNull();
|
|
35
|
+
|
|
36
|
+
const afterCloseModal = getLastRender(renders);
|
|
37
|
+
afterCloseModal.props.onExited();
|
|
38
|
+
|
|
39
|
+
await flushPromises();
|
|
40
|
+
expect(resolvedValue).toBe('gce');
|
|
41
|
+
expect(unmountSpy).toHaveBeenCalled();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('rejects after the modal exit completes', async () => {
|
|
45
|
+
const renders: React.ReactElement[] = [];
|
|
46
|
+
spyOn(ReactDOM, 'render').and.callFake((element) => {
|
|
47
|
+
renders.push(element as React.ReactElement);
|
|
48
|
+
return null;
|
|
49
|
+
});
|
|
50
|
+
const unmountSpy = spyOn(ReactDOM, 'unmountComponentAtNode').and.returnValue(true);
|
|
51
|
+
|
|
52
|
+
let rejectedValue: string | null = null;
|
|
53
|
+
const promise = ReactModal.show(TestModal);
|
|
54
|
+
promise.catch((value) => {
|
|
55
|
+
rejectedValue = value as string;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const initialModal = getLastRender(renders);
|
|
59
|
+
const dismissModal = (initialModal.props.children as any).props.dismissModal as (value?: string) => void;
|
|
60
|
+
dismissModal('cancelled');
|
|
61
|
+
|
|
62
|
+
await flushPromises();
|
|
63
|
+
expect(rejectedValue).toBeNull();
|
|
64
|
+
|
|
65
|
+
const afterDismissModal = getLastRender(renders);
|
|
66
|
+
afterDismissModal.props.onExited();
|
|
67
|
+
|
|
68
|
+
await flushPromises();
|
|
69
|
+
expect(rejectedValue).toBe('cancelled');
|
|
70
|
+
expect(unmountSpy).toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -35,12 +35,19 @@ export class ReactModal {
|
|
|
35
35
|
const modalPromise = new Promise<T>((resolve, reject) => {
|
|
36
36
|
let mountNode = document.createElement('div');
|
|
37
37
|
let show = true;
|
|
38
|
+
let pendingResult: { handler: (result: any) => void; value: any } | null = null;
|
|
38
39
|
|
|
39
40
|
function onExited() {
|
|
40
41
|
if (!mountNode) {
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
if (pendingResult) {
|
|
46
|
+
const { handler, value } = pendingResult;
|
|
47
|
+
pendingResult = null;
|
|
48
|
+
handler(value);
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
ReactDOM.unmountComponentAtNode(mountNode);
|
|
45
52
|
mountNode = null;
|
|
46
53
|
}
|
|
@@ -50,8 +57,11 @@ export class ReactModal {
|
|
|
50
57
|
return;
|
|
51
58
|
}
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
if (pendingResult) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
pendingResult = { handler: resultHandler, value: result };
|
|
55
65
|
show = false;
|
|
56
66
|
render();
|
|
57
67
|
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { IController } from 'angular';
|
|
2
|
-
import type { IModalInstanceService } from 'angular-ui-bootstrap';
|
|
3
|
-
export declare class WerckerStageAddParameter implements IController {
|
|
4
|
-
private $scope;
|
|
5
|
-
private $uibModalInstance;
|
|
6
|
-
static $inject: string[];
|
|
7
|
-
constructor($scope: ng.IScope, $uibModalInstance: IModalInstanceService);
|
|
8
|
-
submit(): void;
|
|
9
|
-
}
|
|
10
|
-
export declare const WERCKER_STAGE_ADD_PARAMETER_MODAL_CONTROLLER = "spinnaker.core.pipeline.stage.wercker.modal.addParameter";
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { StateParams } from '@uirouter/angularjs';
|
|
2
|
-
import type { IController, IScope } from 'angular';
|
|
3
|
-
import type { ExecutionDetailsSectionService } from '../../../details/executionDetailsSection.service';
|
|
4
|
-
export declare class WerckerExecutionDetailsCtrl implements IController {
|
|
5
|
-
private $stateParams;
|
|
6
|
-
private executionDetailsSectionService;
|
|
7
|
-
private $scope;
|
|
8
|
-
configSections: string[];
|
|
9
|
-
detailsSection: string;
|
|
10
|
-
failureMessage: string;
|
|
11
|
-
stage: any;
|
|
12
|
-
static $inject: string[];
|
|
13
|
-
constructor($stateParams: StateParams, executionDetailsSectionService: ExecutionDetailsSectionService, $scope: IScope);
|
|
14
|
-
initialized(): void;
|
|
15
|
-
private getFailureMessage;
|
|
16
|
-
private initialize;
|
|
17
|
-
}
|
|
18
|
-
export declare const WERCKER_EXECUTION_DETAILS_CONTROLLER = "spinnaker.core.pipeline.stage.wercker.executionDetails.controller";
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { IController, IScope } from 'angular';
|
|
2
|
-
import type { IModalService } from 'angular-ui-bootstrap';
|
|
3
|
-
import type { IParameterDefinitionList } from '../../../../domain';
|
|
4
|
-
export interface IWerckerStageViewState {
|
|
5
|
-
mastersLoaded: boolean;
|
|
6
|
-
mastersRefreshing: boolean;
|
|
7
|
-
appsLoaded: boolean;
|
|
8
|
-
appsRefreshing: boolean;
|
|
9
|
-
failureOption?: string;
|
|
10
|
-
markUnstableAsSuccessful?: boolean;
|
|
11
|
-
waitForCompletion?: boolean;
|
|
12
|
-
masterIsParameterized?: boolean;
|
|
13
|
-
jobIsParameterized?: boolean;
|
|
14
|
-
}
|
|
15
|
-
export interface IParameter {
|
|
16
|
-
key: string;
|
|
17
|
-
value: string;
|
|
18
|
-
}
|
|
19
|
-
export declare class WerckerStage implements IController {
|
|
20
|
-
stage: any;
|
|
21
|
-
private $uibModal;
|
|
22
|
-
viewState: IWerckerStageViewState;
|
|
23
|
-
useDefaultParameters: any;
|
|
24
|
-
userSuppliedParameters: any;
|
|
25
|
-
masters: string[];
|
|
26
|
-
jobs: string[];
|
|
27
|
-
jobParams: IParameterDefinitionList[];
|
|
28
|
-
apps: string[];
|
|
29
|
-
pipelines: string[];
|
|
30
|
-
filterLimit: number;
|
|
31
|
-
private filterThreshold;
|
|
32
|
-
app: string;
|
|
33
|
-
pipeline: string;
|
|
34
|
-
job: string;
|
|
35
|
-
static $inject: string[];
|
|
36
|
-
constructor(stage: any, $scope: IScope, $uibModal: IModalService);
|
|
37
|
-
markUnstableChanged(): void;
|
|
38
|
-
waitForCompletionChanged(): void;
|
|
39
|
-
refreshMasters(): void;
|
|
40
|
-
private initializeMasters;
|
|
41
|
-
refreshApps(): void;
|
|
42
|
-
private updateAppsList;
|
|
43
|
-
refreshJobs(): void;
|
|
44
|
-
private updateJobsList;
|
|
45
|
-
private updateJob;
|
|
46
|
-
private updateJobConfig;
|
|
47
|
-
addParameter(): void;
|
|
48
|
-
removeParameter(key: string): void;
|
|
49
|
-
shouldFilter(): boolean;
|
|
50
|
-
}
|
|
51
|
-
export declare const WERCKER_STAGE = "spinnaker.core.pipeline.stage.werckerStage";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const WERCKER_STAGE_MODULE = "spinnaker.core.pipeline.stage.wercker";
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
import type { FormikProps } from 'formik';
|
|
3
|
-
import type { Application } from '../../../../application';
|
|
4
|
-
import type { IBaseBuildTriggerConfigProps } from '../baseBuild/BaseBuildTrigger';
|
|
5
|
-
import type { IWerckerTrigger } from '../../../../domain';
|
|
6
|
-
export interface IWerckerTriggerConfigProps extends IBaseBuildTriggerConfigProps {
|
|
7
|
-
formik: FormikProps<IWerckerTrigger>;
|
|
8
|
-
trigger: IWerckerTrigger;
|
|
9
|
-
application: Application;
|
|
10
|
-
pipelineId: string;
|
|
11
|
-
triggerUpdated: (trigger: IWerckerTrigger) => void;
|
|
12
|
-
}
|
|
13
|
-
export declare function WerckerTrigger(werckerTriggerProps: IWerckerTriggerConfigProps): JSX.Element;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { BaseBuildTriggerTemplate } from '../baseBuild/BaseBuildTriggerTemplate';
|
|
3
|
-
import type { ITriggerTemplateComponentProps } from '../../../manualExecution/TriggerTemplate';
|
|
4
|
-
export declare class WerckerTriggerTemplate extends React.Component<ITriggerTemplateComponentProps> {
|
|
5
|
-
static formatLabel: typeof BaseBuildTriggerTemplate.formatLabel;
|
|
6
|
-
render(): JSX.Element;
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import type { IExecutionStageSummary } from '../../../../domain';
|
|
4
|
-
|
|
5
|
-
export class WerckerExecutionLabel extends React.Component<{ stage: IExecutionStageSummary }> {
|
|
6
|
-
public render() {
|
|
7
|
-
const buildInfo = this.props.stage.masterStage.context.buildInfo || {};
|
|
8
|
-
const testResults = (buildInfo.testResults || []).map((result: any, index: number) => (
|
|
9
|
-
<div key={index}>
|
|
10
|
-
{'( '}
|
|
11
|
-
<span className="tests-pass-count">{result.totalCount - result.failCount - result.skipCount}</span>
|
|
12
|
-
{' / '}
|
|
13
|
-
<span className="tests-fail-count">{result.failCount}</span>
|
|
14
|
-
{result.skipCount > 0 && (
|
|
15
|
-
<span>
|
|
16
|
-
<span> / </span>
|
|
17
|
-
<span className="tests-skip-count">{result.skipCount}</span>
|
|
18
|
-
</span>
|
|
19
|
-
)}
|
|
20
|
-
{' )'}
|
|
21
|
-
</div>
|
|
22
|
-
));
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<span className="stage-label">
|
|
26
|
-
<span>{this.props.stage.name}</span>
|
|
27
|
-
{buildInfo.number && <div>Build #{buildInfo.number}</div>}
|
|
28
|
-
{testResults}
|
|
29
|
-
</span>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { IController } from 'angular';
|
|
2
|
-
import { module } from 'angular';
|
|
3
|
-
import type { IModalInstanceService } from 'angular-ui-bootstrap';
|
|
4
|
-
|
|
5
|
-
export class WerckerStageAddParameter implements IController {
|
|
6
|
-
public static $inject = ['$scope', '$uibModalInstance'];
|
|
7
|
-
constructor(private $scope: ng.IScope, private $uibModalInstance: IModalInstanceService) {}
|
|
8
|
-
|
|
9
|
-
public submit(): void {
|
|
10
|
-
this.$uibModalInstance.close(this.$scope.parameter);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const WERCKER_STAGE_ADD_PARAMETER_MODAL_CONTROLLER = 'spinnaker.core.pipeline.stage.wercker.modal.addParameter';
|
|
15
|
-
|
|
16
|
-
module(WERCKER_STAGE_ADD_PARAMETER_MODAL_CONTROLLER, []).controller(
|
|
17
|
-
'WerckerStageAddParameterCtrl',
|
|
18
|
-
WerckerStageAddParameter,
|
|
19
|
-
);
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
<div modal-page>
|
|
2
|
-
<modal-close dismiss="$dismiss()"></modal-close>
|
|
3
|
-
<div class="modal-header">
|
|
4
|
-
<h4 class="modal-title">Add Parameter</h4>
|
|
5
|
-
</div>
|
|
6
|
-
|
|
7
|
-
<form role="form" class="container-fluid" novalidate name="addParameterForm">
|
|
8
|
-
<div class="modal-body">
|
|
9
|
-
<div class="form-group row">
|
|
10
|
-
<div class="col-sm-3 sm-label-right">Key</div>
|
|
11
|
-
<div class="col-sm-9">
|
|
12
|
-
<input
|
|
13
|
-
type="text"
|
|
14
|
-
class="form-control input-sm"
|
|
15
|
-
ng-model="parameter.key"
|
|
16
|
-
placeholder="enter a parameter key"
|
|
17
|
-
required
|
|
18
|
-
/>
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="form-group row">
|
|
22
|
-
<div class="col-sm-3 sm-label-right">Value</div>
|
|
23
|
-
<div class="col-sm-9">
|
|
24
|
-
<input
|
|
25
|
-
type="text"
|
|
26
|
-
class="form-control input-sm"
|
|
27
|
-
ng-model="parameter.value"
|
|
28
|
-
placeholder="enter a parameter value"
|
|
29
|
-
required
|
|
30
|
-
/>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<div class="modal-footer">
|
|
36
|
-
<a href class="btn btn-default" ng-click="$dismiss()">Cancel</a>
|
|
37
|
-
<button
|
|
38
|
-
type="submit"
|
|
39
|
-
class="btn btn-primary"
|
|
40
|
-
data-purpose="submit"
|
|
41
|
-
ng-click="ctrl.submit()"
|
|
42
|
-
ng-disabled="addParameterForm.$invalid"
|
|
43
|
-
>
|
|
44
|
-
<span class="far fa-check-circle"></span> Add
|
|
45
|
-
</button>
|
|
46
|
-
</div>
|
|
47
|
-
</form>
|
|
48
|
-
</div>
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { IControllerService, IRootScopeService, IScope } from 'angular';
|
|
2
|
-
import { mock } from 'angular';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
WERCKER_EXECUTION_DETAILS_CONTROLLER,
|
|
6
|
-
WerckerExecutionDetailsCtrl,
|
|
7
|
-
} from './werckerExecutionDetails.controller';
|
|
8
|
-
|
|
9
|
-
describe('Wercker Execution Details Controller:', () => {
|
|
10
|
-
let $scope: IScope, $ctrl: IControllerService;
|
|
11
|
-
|
|
12
|
-
beforeEach(mock.module(WERCKER_EXECUTION_DETAILS_CONTROLLER));
|
|
13
|
-
|
|
14
|
-
beforeEach(
|
|
15
|
-
mock.inject(($controller: IControllerService, $rootScope: IRootScopeService) => {
|
|
16
|
-
$ctrl = $controller;
|
|
17
|
-
$scope = $rootScope.$new();
|
|
18
|
-
}),
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
const initializeController = (stage: any): WerckerExecutionDetailsCtrl => {
|
|
22
|
-
$scope.stage = stage;
|
|
23
|
-
return $ctrl(WerckerExecutionDetailsCtrl, {
|
|
24
|
-
$scope,
|
|
25
|
-
executionDetailsSectionService: {
|
|
26
|
-
synchronizeSection: (_availableSections: string[], fn: () => any) => fn(),
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
describe('getting failure message', () => {
|
|
32
|
-
it('should count number of failing tests', () => {
|
|
33
|
-
const stage = {
|
|
34
|
-
context: {
|
|
35
|
-
buildInfo: {
|
|
36
|
-
testResults: [{ failCount: 0 }, { failCount: 3 }, { failCount: 2 }],
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const controller = initializeController(stage);
|
|
42
|
-
|
|
43
|
-
expect(controller.failureMessage).toBe('5 tests failed.');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should fall back to "build failed" message when no failed tests found, but result is "FAILURE"', () => {
|
|
47
|
-
let stage = {
|
|
48
|
-
context: {
|
|
49
|
-
buildInfo: {
|
|
50
|
-
result: 'FAILURE',
|
|
51
|
-
testResults: [] as any,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
let controller = initializeController(stage);
|
|
57
|
-
|
|
58
|
-
expect(controller.failureMessage).toBe('Build failed.');
|
|
59
|
-
|
|
60
|
-
stage = {
|
|
61
|
-
context: {
|
|
62
|
-
buildInfo: {
|
|
63
|
-
result: 'FAILURE',
|
|
64
|
-
testResults: [{ failCount: 0 }],
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
controller = initializeController(stage);
|
|
70
|
-
|
|
71
|
-
expect(controller.failureMessage).toBe('Build failed.');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('should set failureMessage to undefined when not failing', function () {
|
|
75
|
-
const controller = initializeController({});
|
|
76
|
-
expect(controller.failureMessage).toBeUndefined();
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
});
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { StateParams } from '@uirouter/angularjs';
|
|
2
|
-
import type { IController, IScope } from 'angular';
|
|
3
|
-
import { module } from 'angular';
|
|
4
|
-
|
|
5
|
-
import type { ExecutionDetailsSectionService } from '../../../details/executionDetailsSection.service';
|
|
6
|
-
import { EXECUTION_DETAILS_SECTION_SERVICE } from '../../../details/executionDetailsSection.service';
|
|
7
|
-
|
|
8
|
-
export class WerckerExecutionDetailsCtrl implements IController {
|
|
9
|
-
public configSections = ['werckerConfig', 'taskStatus'];
|
|
10
|
-
public detailsSection: string;
|
|
11
|
-
public failureMessage: string;
|
|
12
|
-
public stage: any;
|
|
13
|
-
|
|
14
|
-
public static $inject = ['$stateParams', 'executionDetailsSectionService', '$scope'];
|
|
15
|
-
constructor(
|
|
16
|
-
private $stateParams: StateParams,
|
|
17
|
-
private executionDetailsSectionService: ExecutionDetailsSectionService,
|
|
18
|
-
private $scope: IScope,
|
|
19
|
-
) {
|
|
20
|
-
this.stage = this.$scope.stage;
|
|
21
|
-
this.initialize();
|
|
22
|
-
this.$scope.$on('$stateChangeSuccess', () => this.initialize());
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public initialized(): void {
|
|
26
|
-
this.detailsSection = this.$stateParams.details ?? '';
|
|
27
|
-
this.failureMessage = this.getFailureMessage();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
private getFailureMessage(): string {
|
|
31
|
-
let failureMessage = this.stage.failureMessage;
|
|
32
|
-
const context = this.stage.context || {};
|
|
33
|
-
const buildInfo = context.buildInfo || {};
|
|
34
|
-
const testResults: Array<{ failCount: number }> = buildInfo.testResults ?? [];
|
|
35
|
-
const failingTests = testResults.filter((results) => results.failCount > 0);
|
|
36
|
-
const failingTestCount = failingTests.reduce((acc, results) => acc + results.failCount, 0);
|
|
37
|
-
if (buildInfo.result === 'FAILURE') {
|
|
38
|
-
failureMessage = 'Build failed.';
|
|
39
|
-
}
|
|
40
|
-
if (failingTestCount) {
|
|
41
|
-
failureMessage = `${failingTestCount} test${failingTestCount > 1 ? 's' : ''} failed.`;
|
|
42
|
-
}
|
|
43
|
-
return failureMessage;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
private initialize(): void {
|
|
47
|
-
this.executionDetailsSectionService.synchronizeSection(this.configSections, () => this.initialized());
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export const WERCKER_EXECUTION_DETAILS_CONTROLLER = 'spinnaker.core.pipeline.stage.wercker.executionDetails.controller';
|
|
52
|
-
module(WERCKER_EXECUTION_DETAILS_CONTROLLER, [EXECUTION_DETAILS_SECTION_SERVICE]).controller(
|
|
53
|
-
'WerckerExecutionDetailsCtrl',
|
|
54
|
-
WerckerExecutionDetailsCtrl,
|
|
55
|
-
);
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
<div ng-controller="WerckerExecutionDetailsCtrl">
|
|
2
|
-
<execution-details-section-nav sections="configSections"></execution-details-section-nav>
|
|
3
|
-
<div class="step-section-details" ng-if="detailsSection === 'werckerConfig'">
|
|
4
|
-
<div class="row">
|
|
5
|
-
<div class="col-md-{{stage.context.buildInfo.testResults ? 6 : 12}}">
|
|
6
|
-
<h5>Wercker Stage Configuration</h5>
|
|
7
|
-
<dl class="dl-narrow dl-horizontal">
|
|
8
|
-
<dt>Build Service</dt>
|
|
9
|
-
<dd>{{stage.context.master}}</dd>
|
|
10
|
-
<dt>Job</dt>
|
|
11
|
-
<dd>{{stage.context.job}}</dd>
|
|
12
|
-
<dt>Build</dt>
|
|
13
|
-
<dd>
|
|
14
|
-
<span ng-if="!stage.context.buildInfo">{{stage.context.buildNumber}}</span>
|
|
15
|
-
<a ng-if="stage.context.buildInfo.url" href="{{stage.context.buildInfo.url}}" target="_blank"
|
|
16
|
-
>#{{stage.context.buildInfo.number}}</a
|
|
17
|
-
>
|
|
18
|
-
</dd>
|
|
19
|
-
</dl>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="col-md-6" ng-if="stage.context.buildInfo.testResults">
|
|
22
|
-
<h5>Test Results</h5>
|
|
23
|
-
<div class="row" ng-repeat="result in stage.context.buildInfo.testResults">
|
|
24
|
-
<div class="col-md-6">
|
|
25
|
-
<p>
|
|
26
|
-
<a target="_blank" href="{{stage.context.buildInfo.url}}{{result.urlName}}" class="pad-left">
|
|
27
|
-
{{result.urlName | robotToHuman }}
|
|
28
|
-
</a>
|
|
29
|
-
</p>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="col-md-6">
|
|
32
|
-
<p class="test-results">
|
|
33
|
-
<span class="test-result-section">
|
|
34
|
-
{{result.totalCount - result.failCount - result.skipCount}} <span class="small fa fa-check"></span>
|
|
35
|
-
</span>
|
|
36
|
-
<span class="test-result-section">
|
|
37
|
-
{{result.failCount}} <span class="small glyphicon glyphicon-remove informational"></span>
|
|
38
|
-
</span>
|
|
39
|
-
<span class="test-result-section" ng-if="result.skipCount">
|
|
40
|
-
{{result.skipCount}} <span class="small glyphicon glyphicon-minus"></span>
|
|
41
|
-
</span>
|
|
42
|
-
</p>
|
|
43
|
-
</div>
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
<div class="row" ng-if="stage.context.parameters">
|
|
48
|
-
<div class="col-md-12">
|
|
49
|
-
<h5 style="margin-bottom: 0; padding-bottom: 5px">Parameters</h5>
|
|
50
|
-
<dl>
|
|
51
|
-
<dt ng-repeat-start="(key, val) in stage.context.parameters">{{key}}</dt>
|
|
52
|
-
<dd ng-repeat-end>{{val}}</dd>
|
|
53
|
-
</dl>
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<div class="row" ng-if="stage.context.propertyFileContents">
|
|
58
|
-
<div class="col-md-12">
|
|
59
|
-
<h5 style="margin-bottom: 0; padding-bottom: 5px">Property File</h5>
|
|
60
|
-
<dl>
|
|
61
|
-
<dt ng-repeat-start="(key, val) in stage.context.propertyFileContents">{{key}}</dt>
|
|
62
|
-
<dd ng-repeat-end>{{val}}</dd>
|
|
63
|
-
</dl>
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
<stage-failure-message
|
|
68
|
-
stage="stage"
|
|
69
|
-
ng-if="stage.isFailed"
|
|
70
|
-
message="ctrl.getException(stage) || failureMessage"
|
|
71
|
-
></stage-failure-message>
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
<div class="step-section-details" ng-if="detailsSection === 'taskStatus'">
|
|
75
|
-
<div class="row">
|
|
76
|
-
<execution-step-details item="stage"></execution-step-details>
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|