@spinnaker/core 0.17.0 → 0.18.0
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/CHANGELOG.md +16 -0
- package/dist/config/settings.d.ts +0 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/pipeline/triggers/QuietPeriodBadge.d.ts +2 -8
- package/dist/pipeline/triggers/TriggersTag.d.ts +2 -11
- package/dist/pipeline/triggers/useQuietPeriod.hook.d.ts +7 -0
- package/package.json +2 -2
- package/src/config/settings.ts +0 -1
- package/src/pipeline/details/StageFailureMessage.tsx +1 -1
- package/src/pipeline/triggers/QuietPeriodBadge.tsx +23 -34
- package/src/pipeline/triggers/TriggersTag.tsx +34 -64
- package/src/pipeline/triggers/useQuietPeriod.hook.ts +43 -0
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
start: Date;
|
|
4
|
-
end: Date;
|
|
5
|
-
}
|
|
6
|
-
export declare class QuietPeriodBadge extends React.Component<IQuietPeriodBadgeProps> {
|
|
7
|
-
render(): JSX.Element;
|
|
8
|
-
}
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare function QuietPeriodBadge(): JSX.Element;
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
2
|
import type { IPipeline } from '../../domain/IPipeline';
|
|
3
3
|
export interface ITriggersTagProps {
|
|
4
4
|
pipeline: IPipeline;
|
|
5
5
|
}
|
|
6
|
-
export
|
|
7
|
-
triggerCount: number;
|
|
8
|
-
activeTriggerCount: number;
|
|
9
|
-
}
|
|
10
|
-
export declare class TriggersTag extends React.Component<ITriggersTagProps, ITriggersTagState> {
|
|
11
|
-
private quietPeriodStart;
|
|
12
|
-
private quietPeriodEnd;
|
|
13
|
-
constructor(props: ITriggersTagProps);
|
|
14
|
-
render(): React.ReactElement<TriggersTag>;
|
|
15
|
-
}
|
|
6
|
+
export declare function TriggersTag(props: ITriggersTagProps): JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spinnaker/core",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.18.0",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -120,5 +120,5 @@
|
|
|
120
120
|
"shx": "0.3.3",
|
|
121
121
|
"typescript": "4.3.5"
|
|
122
122
|
},
|
|
123
|
-
"gitHead": "
|
|
123
|
+
"gitHead": "8f3171b4918a445dc508fb4baf676baf639de0ab"
|
|
124
124
|
}
|
package/src/config/settings.ts
CHANGED
|
@@ -143,7 +143,6 @@ export interface ISpinnakerSettings {
|
|
|
143
143
|
[key: string]: IProviderSettings; // allows custom providers not typed in here (good for testing too)
|
|
144
144
|
};
|
|
145
145
|
pubsubProviders: string[];
|
|
146
|
-
quietPeriod: [string | number, string | number];
|
|
147
146
|
resetProvider: (provider: string) => () => void;
|
|
148
147
|
resetToOriginal: () => void;
|
|
149
148
|
searchVersion: 1 | 2;
|
|
@@ -74,7 +74,7 @@ export class StageFailureMessage extends React.Component<IStageFailureMessagePro
|
|
|
74
74
|
const { message, messages, stage } = this.props;
|
|
75
75
|
const { isFailed, failedTask, failedExecutionId, failedStageName, failedStageId } = this.state;
|
|
76
76
|
|
|
77
|
-
let stageMessages = message
|
|
77
|
+
let stageMessages = message && !messages.length ? [message] : messages;
|
|
78
78
|
if (stageMessages.length > 0) {
|
|
79
79
|
const exceptionTitle = isFailed ? (messages.length ? 'Exceptions' : 'Exception') : 'Warning';
|
|
80
80
|
|
|
@@ -2,11 +2,7 @@ import type { DateTimeFormatOptions } from 'luxon';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
4
|
import { Tooltip } from '../../presentation';
|
|
5
|
-
|
|
6
|
-
export interface IQuietPeriodBadgeProps {
|
|
7
|
-
start: Date;
|
|
8
|
-
end: Date;
|
|
9
|
-
}
|
|
5
|
+
import { useQuietPeriod } from './useQuietPeriod.hook';
|
|
10
6
|
|
|
11
7
|
const locale = 'en-US';
|
|
12
8
|
const dateOptions: DateTimeFormatOptions = {
|
|
@@ -18,37 +14,30 @@ const dateOptions: DateTimeFormatOptions = {
|
|
|
18
14
|
minute: '2-digit',
|
|
19
15
|
};
|
|
20
16
|
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
17
|
+
export function QuietPeriodBadge() {
|
|
18
|
+
const quietPeriod = useQuietPeriod();
|
|
19
|
+
if (quietPeriod.currentStatus === 'NO_QUIET_PERIOD' || quietPeriod.currentStatus === 'UNKNOWN') {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
28
22
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (afterQuietPeriod) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
23
|
+
const start = new Date(quietPeriod.startTime);
|
|
24
|
+
const end = new Date(quietPeriod.endTime);
|
|
34
25
|
|
|
35
|
-
|
|
26
|
+
const message =
|
|
27
|
+
quietPeriod.currentStatus === 'DURING_QUIET_PERIOD'
|
|
28
|
+
? 'This pipeline will not be automatically triggered until the end of the quiet period. '
|
|
29
|
+
: 'This pipeline will not be automatically triggered during the quiet period. ';
|
|
36
30
|
|
|
37
|
-
|
|
31
|
+
const template = (
|
|
32
|
+
<span>
|
|
33
|
+
{message}
|
|
38
34
|
<span>{`(${start.toLocaleString(locale, dateOptions)} - ${end.toLocaleString(locale, dateOptions)})`}</span>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<Tooltip template={tooltipTemplate}>
|
|
50
|
-
<i className="fa icon-calendar-warning" style={{ color: 'red' }} />
|
|
51
|
-
</Tooltip>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
35
|
+
</span>
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Tooltip template={template}>
|
|
40
|
+
<i className="fa icon-calendar-warning" style={{ color: 'red' }} />
|
|
41
|
+
</Tooltip>
|
|
42
|
+
);
|
|
54
43
|
}
|
|
@@ -1,79 +1,49 @@
|
|
|
1
|
-
import
|
|
2
|
-
import React from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
|
|
4
3
|
import { QuietPeriodBadge } from './QuietPeriodBadge';
|
|
5
|
-
import {
|
|
4
|
+
import type { ITrigger } from '../../domain';
|
|
6
5
|
import type { IPipeline } from '../../domain/IPipeline';
|
|
6
|
+
import { useQuietPeriod } from './useQuietPeriod.hook';
|
|
7
7
|
|
|
8
8
|
export interface ITriggersTagProps {
|
|
9
9
|
pipeline: IPipeline;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
constructor(props: ITriggersTagProps) {
|
|
22
|
-
super(props);
|
|
23
|
-
|
|
24
|
-
let triggerCount = 0;
|
|
25
|
-
let activeTriggerCount = 0;
|
|
26
|
-
let quietPeriodEnabled = false;
|
|
27
|
-
|
|
28
|
-
const pipeline = this.props.pipeline;
|
|
29
|
-
if (pipeline && pipeline.triggers && pipeline.triggers.length) {
|
|
30
|
-
triggerCount = pipeline.triggers.length;
|
|
31
|
-
activeTriggerCount = filter(pipeline.triggers, { enabled: true }).length;
|
|
32
|
-
quietPeriodEnabled = Boolean(pipeline.respectQuietPeriod);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const hasQuietPeriod = SETTINGS.feature.quietPeriod && SETTINGS.quietPeriod && SETTINGS.quietPeriod.length === 2;
|
|
36
|
-
|
|
37
|
-
if (hasQuietPeriod && quietPeriodEnabled) {
|
|
38
|
-
this.quietPeriodStart = new Date(SETTINGS.quietPeriod[0]);
|
|
39
|
-
this.quietPeriodEnd = new Date(SETTINGS.quietPeriod[1]);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
this.state = {
|
|
43
|
-
triggerCount,
|
|
44
|
-
activeTriggerCount,
|
|
45
|
-
};
|
|
12
|
+
function getTriggerLabel(totalTriggers: number, activeTriggers: number) {
|
|
13
|
+
if (totalTriggers === 1) {
|
|
14
|
+
return `Trigger: ${activeTriggers ? 'enabled' : 'disabled'}`;
|
|
15
|
+
} else if (totalTriggers === activeTriggers) {
|
|
16
|
+
return `All triggers: enabled`;
|
|
17
|
+
} else if (activeTriggers === 0) {
|
|
18
|
+
return `All triggers: disabled`;
|
|
19
|
+
} else {
|
|
20
|
+
return `Some triggers: enabled`;
|
|
46
21
|
}
|
|
22
|
+
}
|
|
47
23
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const { triggerCount, activeTriggerCount } = this.state;
|
|
51
|
-
|
|
52
|
-
if (triggerCount > 0) {
|
|
53
|
-
const now = new Date();
|
|
54
|
-
const inQuietPeriod = this.quietPeriodStart < now && now < this.quietPeriodEnd;
|
|
24
|
+
export function TriggersTag(props: ITriggersTagProps) {
|
|
25
|
+
const quietPeriod = useQuietPeriod();
|
|
55
26
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const displayTriggers = `${triggers}: ${activeTriggerCount === 0 || inQuietPeriod ? 'disabled' : 'enabled'}`;
|
|
27
|
+
const { pipeline } = props;
|
|
28
|
+
const triggers = pipeline?.triggers ?? [];
|
|
29
|
+
const isTriggerDisabled = (t: ITrigger) =>
|
|
30
|
+
!t.enabled ||
|
|
31
|
+
(pipeline.respectQuietPeriod && quietPeriod.currentStatus === 'DURING_QUIET_PERIOD' && t.type !== 'pipeline');
|
|
32
|
+
const activeTriggers = triggers.filter((t: ITrigger) => !isTriggerDisabled(t));
|
|
63
33
|
|
|
64
|
-
|
|
65
|
-
<div
|
|
66
|
-
className={`triggers-toggle ${activeTriggerCount ? '' : 'disabled'}`}
|
|
67
|
-
style={{ visibility: pipeline.disabled ? 'hidden' : 'visible' }}
|
|
68
|
-
>
|
|
69
|
-
<span>
|
|
70
|
-
<span>
|
|
71
|
-
<QuietPeriodBadge start={this.quietPeriodStart} end={this.quietPeriodEnd} /> {displayTriggers}
|
|
72
|
-
</span>
|
|
73
|
-
</span>
|
|
74
|
-
</div>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
34
|
+
if (triggers.length === 0) {
|
|
77
35
|
return <div />;
|
|
78
36
|
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
className={`triggers-toggle ${activeTriggers.length > 0 ? '' : 'disabled'}`}
|
|
41
|
+
style={{ visibility: pipeline.disabled ? 'hidden' : 'visible' }}
|
|
42
|
+
>
|
|
43
|
+
<span className="flex-container-h margin-between-sm baseline">
|
|
44
|
+
{pipeline.respectQuietPeriod && <QuietPeriodBadge />}
|
|
45
|
+
<span>{getTriggerLabel(triggers.length, activeTriggers.length)}</span>
|
|
46
|
+
</span>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
79
49
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { REST } from '../../api';
|
|
2
|
+
import { useLatestPromise } from '../../presentation';
|
|
3
|
+
|
|
4
|
+
// Shape from back end
|
|
5
|
+
interface IQuietPeriodConfig {
|
|
6
|
+
startTime: number;
|
|
7
|
+
endTime: number;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
// Do not use in UI -- point-in-time data from back-end
|
|
10
|
+
inQuietPeriod: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class QuietPeriodService {
|
|
14
|
+
private static _quietPeriodConfig: PromiseLike<IQuietPeriodConfig>;
|
|
15
|
+
static async quietPeriodConfig(): Promise<IQuietPeriodConfig> {
|
|
16
|
+
this._quietPeriodConfig = this._quietPeriodConfig ?? REST('/capabilities/quietPeriod').get<IQuietPeriodConfig>();
|
|
17
|
+
return await this._quietPeriodConfig;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface IQuietPeriod {
|
|
22
|
+
currentStatus: 'UNKNOWN' | 'BEFORE_QUIET_PERIOD' | 'DURING_QUIET_PERIOD' | 'AFTER_QUIET_PERIOD' | 'NO_QUIET_PERIOD';
|
|
23
|
+
startTime: number;
|
|
24
|
+
endTime: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function useQuietPeriod(): IQuietPeriod {
|
|
28
|
+
const result = useLatestPromise(() => QuietPeriodService.quietPeriodConfig(), []);
|
|
29
|
+
if (result.status !== 'RESOLVED') {
|
|
30
|
+
return { currentStatus: 'UNKNOWN', startTime: undefined, endTime: undefined };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const { startTime, endTime, enabled } = result.result;
|
|
34
|
+
if (!enabled || !startTime || startTime < 0 || !endTime || endTime < 0) {
|
|
35
|
+
return { currentStatus: 'NO_QUIET_PERIOD', startTime: undefined, endTime: undefined };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
const currentStatus =
|
|
40
|
+
now < startTime ? 'BEFORE_QUIET_PERIOD' : now > endTime ? 'AFTER_QUIET_PERIOD' : 'DURING_QUIET_PERIOD';
|
|
41
|
+
|
|
42
|
+
return { currentStatus, startTime, endTime };
|
|
43
|
+
}
|