@spinnaker/core 0.14.0 → 0.15.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.
Files changed (218) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/config/settings.d.ts +1 -1
  3. package/dist/core.module.d.ts +1 -1
  4. package/dist/index.js +89 -47
  5. package/dist/index.js.map +1 -1
  6. package/dist/instance/instanceType.service.d.ts +3 -2
  7. package/dist/managed/artifactActions/ArtifactActions.d.ts +24 -0
  8. package/dist/managed/constraints/registry.d.ts +13 -2
  9. package/dist/managed/environmentBaseElements/EnvironmentItem.d.ts +3 -2
  10. package/dist/managed/graphql/graphql-sdk.d.ts +123 -11
  11. package/dist/managed/overview/Resource.d.ts +5 -2
  12. package/dist/managed/overview/artifact/Artifact.d.ts +2 -1
  13. package/dist/managed/overview/artifact/ArtifactActionModal.d.ts +20 -9
  14. package/dist/managed/overview/artifact/ArtifactCollapsibleSection.d.ts +7 -0
  15. package/dist/managed/overview/artifact/ArtifactVersions.d.ts +9 -0
  16. package/dist/managed/overview/artifact/CurrentVersion.d.ts +7 -6
  17. package/dist/managed/overview/artifact/VersionTitle.d.ts +9 -0
  18. package/dist/managed/overview/artifact/hooks.d.ts +6 -11
  19. package/dist/managed/overview/artifact/useCreateRollbackActions.hook.d.ts +3 -0
  20. package/dist/managed/overview/artifact/utils.d.ts +15 -14
  21. package/dist/managed/overview/useIsUpdatingResources.hook.d.ts +1 -0
  22. package/dist/managed/resources/ResourceTitle.d.ts +3 -3
  23. package/dist/managed/resources/resourceRegistry.d.ts +1 -1
  24. package/dist/managed/utils/ActionModal.d.ts +1 -0
  25. package/dist/managed/utils/defaults.d.ts +1 -0
  26. package/dist/managed/versionMetadata/MetadataComponents.d.ts +18 -19
  27. package/dist/managed/versionMetadata/VersionMetadata.d.ts +6 -2
  28. package/dist/search/infrastructure/infrastructureSearch.service.d.ts +2 -1
  29. package/dist/securityGroup/index.d.ts +2 -1
  30. package/package.json +7 -7
  31. package/src/account/AccountSelectInput.spec.tsx +9 -4
  32. package/src/account/AccountService.spec.ts +6 -6
  33. package/src/api/ApiService.spec.ts +2 -2
  34. package/src/api/ApiServiceDeprecated.spec.ts +5 -2
  35. package/src/application/application.model.spec.ts +78 -79
  36. package/src/application/config/applicationAttributes.directive.html +6 -2
  37. package/src/application/config/applicationAttributes.directive.js +4 -0
  38. package/src/application/config/applicationConfig.view.html +14 -1
  39. package/src/application/config/customBanner/CustomBannerConfig.spec.tsx +3 -3
  40. package/src/application/config/dataSources/applicationDataSourceEditor.component.spec.ts +4 -3
  41. package/src/application/config/footer/configSectionFooter.component.spec.ts +2 -1
  42. package/src/application/listExtractor/AppListExtractor.spec.ts +4 -4
  43. package/src/application/modal/PermissionsConfigurer.spec.tsx +3 -2
  44. package/src/application/modal/editApplication.controller.modal.js +1 -0
  45. package/src/application/modal/editApplication.html +2 -2
  46. package/src/application/modal/validation/ApplicationNameValidator.spec.ts +2 -1
  47. package/src/application/modal/validation/validateApplicationName.directive.spec.ts +3 -2
  48. package/src/application/nav/ApplicationNavigation.spec.tsx +12 -11
  49. package/src/application/nav/NavItem.spec.tsx +7 -5
  50. package/src/application/nav/NavSection.spec.tsx +3 -2
  51. package/src/application/service/ApplicationReader.spec.ts +13 -8
  52. package/src/application/service/ApplicationWriter.spec.ts +4 -2
  53. package/src/application/service/InferredApplicationWarningService.spec.ts +2 -3
  54. package/src/artifact/expectedArtifact.service.spec.ts +2 -1
  55. package/src/artifact/react/ExpectedArtifactSelector.spec.tsx +2 -3
  56. package/src/authentication/AuthenticationInitializer.spec.ts +2 -1
  57. package/src/authentication/AuthenticationService.spec.ts +2 -1
  58. package/src/authentication/authentication.interceptor.spec.ts +4 -2
  59. package/src/cache/cacheInitializer.service.spec.ts +7 -4
  60. package/src/cache/infrastructureCaches.spec.ts +4 -4
  61. package/src/chaosMonkey/chaosMonkeyExceptions.component.spec.ts +4 -2
  62. package/src/cloudProvider/providerSelection/ProviderSelectionService.spec.ts +23 -21
  63. package/src/cluster/ClusterRuleMatcher.spec.ts +2 -1
  64. package/src/cluster/cluster.service.spec.ts +7 -7
  65. package/src/cluster/filter/ClusterFilterService.spec.ts +15 -14
  66. package/src/cluster/filter/LabelFilter.spec.tsx +3 -3
  67. package/src/cluster/filter/MultiselectModel.spec.ts +2 -2
  68. package/src/cluster/filter/labelFilterUtils.spec.ts +3 -7
  69. package/src/config/settings.ts +1 -3
  70. package/src/core.module.ts +1 -1
  71. package/src/filterModel/dependentFilter/DependentFilterService.spec.ts +1 -1
  72. package/src/function/filter/FunctionFilterService.spec.ts +5 -3
  73. package/src/function/function.read.service.spec.ts +4 -3
  74. package/src/header/customBanner/CustomBanner.spec.tsx +3 -4
  75. package/src/healthCounts/HealthCounts.spec.tsx +2 -2
  76. package/src/history/recentHistory.service.spec.ts +2 -1
  77. package/src/insight/InsightMenu.spec.tsx +9 -6
  78. package/src/instance/instance.write.service.spec.ts +8 -7
  79. package/src/instance/instanceType.service.ts +12 -2
  80. package/src/instance/instanceTypeService.spec.ts +2 -1
  81. package/src/loadBalancer/LoadBalancersTag.spec.tsx +8 -6
  82. package/src/loadBalancer/filter/LoadBalancerFilterService.spec.ts +2 -2
  83. package/src/managed/Environments.less +4 -4
  84. package/src/managed/Environments.tsx +1 -1
  85. package/src/managed/RelativeTimestamp.tsx +8 -6
  86. package/src/managed/artifactActions/ArtifactActions.tsx +77 -0
  87. package/src/managed/constraints/AllowedTimes.spec.ts +2 -1
  88. package/src/managed/constraints/registry.tsx +27 -1
  89. package/src/managed/environmentBaseElements/BaseEnvironment.less +3 -3
  90. package/src/managed/environmentBaseElements/EnvironmentItem.tsx +11 -4
  91. package/src/managed/graphql/graphql-sdk.ts +218 -29
  92. package/src/managed/graphql/schema.graphql +14 -1
  93. package/src/managed/overview/EnvironmentOverview.tsx +12 -15
  94. package/src/managed/overview/EnvironmentsOverview.less +6 -5
  95. package/src/managed/overview/PreviewEnvironments.tsx +0 -3
  96. package/src/managed/overview/Resource.less +1 -1
  97. package/src/managed/overview/Resource.tsx +62 -47
  98. package/src/managed/overview/artifact/Artifact.less +27 -52
  99. package/src/managed/overview/artifact/Artifact.tsx +86 -22
  100. package/src/managed/overview/artifact/ArtifactActionModal.less +19 -0
  101. package/src/managed/overview/artifact/ArtifactActionModal.tsx +150 -68
  102. package/src/managed/overview/artifact/ArtifactCollapsibleSection.tsx +32 -0
  103. package/src/managed/overview/artifact/ArtifactVersionTasks.tsx +2 -0
  104. package/src/managed/overview/artifact/{PendingVersion.tsx → ArtifactVersions.tsx} +35 -25
  105. package/src/managed/overview/artifact/Constraints.tsx +61 -21
  106. package/src/managed/overview/artifact/CurrentVersion.tsx +42 -27
  107. package/src/managed/overview/artifact/VersionTitle.tsx +18 -0
  108. package/src/managed/overview/artifact/hooks.ts +71 -34
  109. package/src/managed/overview/artifact/useCreateRollbackActions.hook.ts +75 -0
  110. package/src/managed/overview/artifact/utils.spec.ts +1 -1
  111. package/src/managed/overview/artifact/utils.ts +47 -80
  112. package/src/managed/overview/baseStyles.less +124 -88
  113. package/src/managed/overview/queries.graphql +54 -13
  114. package/src/managed/overview/useIsUpdatingResources.hook.ts +9 -0
  115. package/src/managed/resources/ResourceTitle.tsx +12 -5
  116. package/src/managed/utils/ActionModal.tsx +4 -1
  117. package/src/managed/utils/defaults.ts +3 -0
  118. package/src/managed/utils/useNotifyOnError.hook.ts +1 -1
  119. package/src/managed/versionMetadata/MetadataComponents.tsx +102 -70
  120. package/src/managed/versionMetadata/VersionMetadata.less +17 -18
  121. package/src/managed/versionMetadata/VersionMetadata.tsx +23 -31
  122. package/src/managed/versionsHistory/VersionContent.tsx +20 -13
  123. package/src/managed/versionsHistory/VersionHeading.tsx +2 -1
  124. package/src/managed/versionsHistory/VersionsHistory.less +11 -3
  125. package/src/manifest/PodNameProvider.spec.ts +1 -1
  126. package/src/navigation/customParamTypes.spec.ts +1 -1
  127. package/src/pagerDuty/pagerDuty.read.service.spec.ts +4 -2
  128. package/src/pagerDuty/pagerDutyTag.component.spec.ts +7 -3
  129. package/src/pipeline/config/PipelineRegistry.spec.ts +38 -37
  130. package/src/pipeline/config/actions/templateJson/ShowPipelineTemplateJsonModal.spec.tsx +3 -3
  131. package/src/pipeline/config/pipelineConfigurer.controller.spec.ts +3 -3
  132. package/src/pipeline/config/services/PipelineConfigService.spec.ts +4 -3
  133. package/src/pipeline/config/stages/bakeManifest/helm/BakeHelmConfigForm.spec.tsx +51 -8
  134. package/src/pipeline/config/stages/bakeManifest/helm/BakeHelmConfigForm.tsx +36 -6
  135. package/src/pipeline/config/stages/findArtifactFromExecution/findArtifactFromExecution.controller.spec.ts +2 -1
  136. package/src/pipeline/config/stages/manualJudgment/manualJudgment.service.spec.ts +6 -4
  137. package/src/pipeline/config/stages/travis/travisExecutionDetails.controller.spec.ts +5 -2
  138. package/src/pipeline/config/stages/travis/travisStage.controller.spec.ts +3 -2
  139. package/src/pipeline/config/stages/unmatchedStageTypeStage/unmatchedStageTypeStage.controller.spec.ts +2 -1
  140. package/src/pipeline/config/stages/wait/SkipWait.tsx +3 -1
  141. package/src/pipeline/config/stages/wercker/werckerExecutionDetails.controller.spec.ts +5 -2
  142. package/src/pipeline/config/stages/wercker/werckerStage.controller.spec.ts +3 -2
  143. package/src/pipeline/config/templates/Variable.spec.tsx +6 -5
  144. package/src/pipeline/config/templates/configurePipelineTemplateModal.controller.spec.ts +7 -8
  145. package/src/pipeline/config/templates/v2/configurePipelineTemplateModalV2.controller.spec.ts +7 -8
  146. package/src/pipeline/config/templates/v2/pipelineTemplateV2.service.spec.ts +1 -1
  147. package/src/pipeline/config/triggers/TriggersPageContent.spec.tsx +4 -4
  148. package/src/pipeline/config/triggers/TriggersPageContent.tsx +1 -2
  149. package/src/pipeline/config/triggers/artifacts/docker/defaultDocker.artifact.spec.ts +1 -2
  150. package/src/pipeline/config/validation/pipelineConfig.validator.spec.ts +14 -15
  151. package/src/pipeline/create/CreatePipelineModal.spec.tsx +9 -7
  152. package/src/pipeline/details/executionDetailsSection.service.spec.ts +3 -2
  153. package/src/pipeline/executions/Executions.spec.tsx +9 -6
  154. package/src/pipeline/executions/executionAction/ExecutionAction.spec.tsx +1 -1
  155. package/src/pipeline/executions/executionGroup/ExecutionGroup.tsx +2 -1
  156. package/src/pipeline/filter/executionFilter.service.spec.ts +1 -1
  157. package/src/pipeline/pipeline.dataSource.spec.ts +8 -7
  158. package/src/pipeline/service/ExecutionsTransformer.spec.ts +2 -2
  159. package/src/pipeline/service/execution.service.spec.ts +7 -5
  160. package/src/pipeline/status/Artifact.spec.tsx +7 -6
  161. package/src/pipeline/status/ArtifactList.spec.tsx +7 -6
  162. package/src/pipeline/status/ExecutionParameters.spec.tsx +5 -4
  163. package/src/pipeline/status/ResolvedArtifactList.spec.tsx +7 -6
  164. package/src/plugins/deck.plugin.spec.ts +4 -2
  165. package/src/plugins/plugin.registry.spec.ts +6 -4
  166. package/src/presentation/forms/SpinFormik.spec.tsx +3 -2
  167. package/src/presentation/forms/fields/FormikFormField.spec.tsx +3 -3
  168. package/src/presentation/forms/hooks/useSaveRestoreMutuallyExclusiveFields.hook.spec.tsx +4 -3
  169. package/src/presentation/forms/inputs/ChecklistInput.spec.tsx +1 -1
  170. package/src/presentation/forms/inputs/RadioButtonInput.spec.tsx +2 -1
  171. package/src/presentation/forms/inputs/SelectInput.spec.tsx +2 -1
  172. package/src/presentation/forms/inputs/hooks/useInternalValidator.hook.spec.tsx +4 -3
  173. package/src/presentation/forms/validation/FormValidator.spec.ts +2 -2
  174. package/src/presentation/forms/validation/useValidationData.spec.tsx +4 -3
  175. package/src/presentation/hooks/useContainerClassNames.hook.spec.tsx +2 -1
  176. package/src/presentation/hooks/useData.hook.spec.tsx +3 -2
  177. package/src/presentation/hooks/useDebouncedValue.hook.spec.tsx +1 -1
  178. package/src/presentation/hooks/useDeepObjectDiff.hook.spec.tsx +2 -1
  179. package/src/presentation/hooks/useEventListener.hook.spec.tsx +2 -1
  180. package/src/presentation/hooks/useForceUpdate.hook.spec.tsx +2 -1
  181. package/src/presentation/hooks/useInterval.hook.spec.tsx +2 -1
  182. package/src/presentation/hooks/useIsMountedRef.hook.spec.tsx +1 -1
  183. package/src/presentation/hooks/useLatestCallback.hook.spec.tsx +2 -1
  184. package/src/presentation/hooks/useLatestPromise.hook.spec.tsx +9 -3
  185. package/src/presentation/hooks/useMountStatusRef.hook.spec.tsx +3 -1
  186. package/src/presentation/hooks/usePollingData.hook.spec.tsx +3 -2
  187. package/src/presentation/hooks/usePrevious.hook.spec.tsx +2 -1
  188. package/src/presentation/navigation/pageNavigator.component.spec.ts +6 -6
  189. package/src/presentation/spel/SpelInput.spec.tsx +9 -4
  190. package/src/presentation/spel/SpelService.spec.ts +1 -1
  191. package/src/scheduler/SchedulerFactory.spec.ts +2 -1
  192. package/src/search/infrastructure/infrastructureSearch.service.ts +3 -2
  193. package/src/search/widgets/Filter.spec.tsx +5 -3
  194. package/src/search/widgets/Filters.spec.tsx +5 -3
  195. package/src/search/widgets/Search.spec.tsx +4 -2
  196. package/src/securityGroup/index.ts +2 -1
  197. package/src/securityGroup/securityGroupReader.service.spec.ts +8 -10
  198. package/src/serverGroup/configure/common/deployInitializer.component.spec.ts +7 -3
  199. package/src/serverGroup/configure/common/v2instanceArchetypeSelector.component.ts +1 -1
  200. package/src/serverGroup/details/capacity/CapacityDetailsSection.spec.tsx +1 -1
  201. package/src/serverGroup/details/scalingActivities/ScalingActivitiesModal.spec.ts +2 -1
  202. package/src/serverGroup/details/serverGroupWarningMessage.service.spec.ts +4 -4
  203. package/src/serverGroup/serverGroupWriter.service.spec.ts +10 -8
  204. package/src/slack/SlackReader.spec.ts +2 -1
  205. package/src/subnet/subnet.read.service.spec.ts +4 -3
  206. package/src/task/monitor/taskMonitor.spec.ts +6 -5
  207. package/src/task/task.dataSource.spec.ts +5 -4
  208. package/src/task/task.write.service.spec.ts +3 -1
  209. package/src/utils/clipboard/CopyToClipboard.spec.tsx +2 -1
  210. package/src/utils/json/json.utility.service.spec.ts +2 -1
  211. package/src/utils/timeFormatters.spec.ts +3 -2
  212. package/src/utils/workerPool.spec.ts +2 -1
  213. package/src/widgets/ApplicationsPickerInput.spec.tsx +3 -2
  214. package/src/widgets/spelText/SpelAutocompleteService.spec.ts +4 -3
  215. package/src/widgets/tags/Tag.spec.tsx +4 -2
  216. package/src/widgets/tags/TagList.spec.tsx +5 -3
  217. package/src/yamlEditor/yamlEditorUtils.spec.ts +1 -1
  218. package/dist/managed/overview/artifact/PendingVersion.d.ts +0 -7
@@ -1,29 +1,32 @@
1
1
  .Artifact {
2
- --version-left-padding: 18px;
3
-
4
- @media (max-width: 768px) {
5
- --version-left-padding: 14px;
6
- }
7
-
8
2
  .artifact-current-version {
9
3
  display: flex;
10
4
  flex-direction: column;
11
- border-radius: 5px;
12
- padding-left: var(--version-left-padding);
13
5
  }
14
6
 
15
- .artifact-versions-title {
16
- margin-bottom: var(--s-spacing);
7
+ .artifact-section {
8
+ margin-left: -16px;
9
+ }
10
+
11
+ .artifact-section-title {
17
12
  text-transform: uppercase;
18
- color: var(--color-titanium);
19
- font-size: 14px;
20
- font-weight: 600;
13
+ color: rgb(45%, 45%, 45%);
14
+ font-size: 15px;
15
+ font-weight: 700;
16
+ letter-spacing: 0.2px;
17
+
18
+ .section-heading-chevron {
19
+ margin-top: -1px;
20
+ }
21
+
22
+ .in-progress-dot {
23
+ margin-left: 6px;
24
+ margin-top: -1px;
25
+ }
21
26
  }
22
27
 
23
- .artifact-pending-versions {
24
- margin-top: var(--l-spacing);
28
+ .artifact-versions {
25
29
  position: relative;
26
- --circle-shift: 6px;
27
30
 
28
31
  .artifact-pending-versions-list {
29
32
  .show-more-versions {
@@ -36,48 +39,12 @@
36
39
  .artifact-pending-version {
37
40
  display: flex;
38
41
  flex-direction: column;
39
- padding-right: var(--l-spacing);
40
42
  position: relative;
41
- padding-left: var(--version-left-padding);
42
43
 
43
44
  &:not(:last-of-type) {
44
45
  padding-bottom: 32px;
45
46
  }
46
47
 
47
- // Line
48
- &::before {
49
- content: '';
50
- position: absolute;
51
- top: 0;
52
- left: calc(4px);
53
- height: 100%;
54
- border-left: 2px solid var(--color-accent-g2);
55
- }
56
-
57
- // circle
58
- &::after {
59
- content: '';
60
- position: absolute;
61
- top: var(--circle-shift);
62
- left: 0;
63
- width: 10px;
64
- height: 10px;
65
- background: var(--color-accent-g2);
66
- border-radius: 50%;
67
- }
68
-
69
- &:last-of-type {
70
- &::before {
71
- height: var(--circle-shift);
72
- }
73
- }
74
-
75
- &:first-of-type {
76
- &::before {
77
- top: var(--circle-shift);
78
- }
79
- }
80
-
81
48
  .artifact-pending-version-commit {
82
49
  font-weight: 600;
83
50
  display: flex;
@@ -96,4 +63,12 @@
96
63
  color: var(--color-warning);
97
64
  }
98
65
  }
66
+
67
+ .VersionTitle {
68
+ display: grid;
69
+ grid-template-columns: minmax(auto, max-content) auto;
70
+ align-items: baseline;
71
+ column-gap: 20px;
72
+ justify-content: flex-start;
73
+ }
99
74
  }
@@ -1,13 +1,17 @@
1
1
  import { orderBy } from 'lodash';
2
2
  import React from 'react';
3
3
 
4
+ import { ArtifactCollapsibleSection } from './ArtifactCollapsibleSection';
5
+ import { ArtifactVersions } from './ArtifactVersions';
4
6
  import { CurrentVersion } from './CurrentVersion';
5
- import { PendingVersions } from './PendingVersion';
7
+ import { Resource } from '../Resource';
6
8
  import { EnvironmentItem } from '../../environmentBaseElements/EnvironmentItem';
7
- import { HoverablePopover, Markdown } from '../../../presentation';
9
+ import { useMarkVersionAsBad } from './hooks';
10
+ import { HoverablePopover, Markdown, useApplicationContextSafe } from '../../../presentation';
8
11
  import type { QueryArtifact, QueryArtifactVersion } from '../types';
9
- import { tooltipShowHideProps } from '../../utils/defaults';
10
- import { toPinnedMetadata } from '../../versionMetadata/MetadataComponents';
12
+ import { useIsUpdatingResources } from '../useIsUpdatingResources.hook';
13
+ import { isVersionVetoed } from './utils';
14
+ import { ACTION_BUTTON_CLASS_NAME, tooltipShowHideProps } from '../../utils/defaults';
11
15
 
12
16
  import './Artifact.less';
13
17
 
@@ -57,39 +61,99 @@ export const PinnedVersion = ({ version }: { version: NonNullable<QueryArtifact[
57
61
  </div>
58
62
  );
59
63
  };
64
+ interface IRollbackActionProps {
65
+ currentVersion: QueryArtifactVersion;
66
+ environment: string;
67
+ reference: string;
68
+ isPinned: boolean;
69
+ }
70
+
71
+ const RollbackAction = ({ currentVersion, environment, reference, isPinned }: IRollbackActionProps) => {
72
+ const appName = useApplicationContextSafe().name;
73
+ const onMarkAsBad = useMarkVersionAsBad({
74
+ application: appName,
75
+ environment,
76
+ reference,
77
+ version: currentVersion.version,
78
+ isVetoed: isVersionVetoed(currentVersion),
79
+ isPinned,
80
+ isCurrent: true,
81
+ selectedVersion: {
82
+ buildNumber: currentVersion.buildNumber,
83
+ commitMessage: currentVersion.gitMetadata?.commitInfo?.message,
84
+ commitSha: currentVersion.gitMetadata?.commit,
85
+ },
86
+ });
87
+ return (
88
+ <button className={ACTION_BUTTON_CLASS_NAME} onClick={onMarkAsBad}>
89
+ Rollback...
90
+ </button>
91
+ );
92
+ };
60
93
 
61
94
  interface IArtifactProps {
62
95
  artifact: QueryArtifact;
96
+ isPreview?: boolean;
63
97
  }
64
98
 
65
- export const Artifact = ({ artifact }: IArtifactProps) => {
66
- const currentVersion = artifact.versions?.find((version) => version.isCurrent === true);
67
- const newerVersions = filterPendingVersions(artifact.versions, currentVersion);
68
- const { pinnedVersion } = artifact;
99
+ const ArtifactResources = ({ environment, resources }: Pick<QueryArtifact, 'environment' | 'resources'>) => {
100
+ const isUpdatingResources = useIsUpdatingResources(environment);
101
+ return (
102
+ <ArtifactCollapsibleSection heading="DEPLOYED TO" isUpdating={isUpdatingResources}>
103
+ {resources?.map((resource) => (
104
+ <Resource
105
+ key={resource.id}
106
+ resource={resource}
107
+ environment={environment}
108
+ size="small"
109
+ className="sp-margin-m-top"
110
+ withPadding={false}
111
+ />
112
+ ))}
113
+ </ArtifactCollapsibleSection>
114
+ );
115
+ };
69
116
 
117
+ export const Artifact = ({ artifact, isPreview }: IArtifactProps) => {
118
+ const { environment, type, reference, versions, pinnedVersion, resources } = artifact;
119
+ const currentVersion = versions?.find((version) => version.isCurrent === true);
120
+ const newerVersions = filterPendingVersions(versions, currentVersion);
121
+ const deployingVersion = newerVersions.filter((version) => version.status === 'DEPLOYING');
122
+ const pendingVersions = newerVersions.filter((version) => version.status !== 'DEPLOYING');
70
123
  return (
71
124
  <EnvironmentItem
72
125
  iconName="artifact"
73
- iconTooltip={`Artifact - ${artifact.type}`}
126
+ iconTooltip={`Artifact - ${type}`}
74
127
  className="Artifact"
75
- title={artifact.reference}
128
+ title={reference}
129
+ rightElement={
130
+ currentVersion && !isPreview ? (
131
+ <RollbackAction {...{ environment, currentVersion, reference }} isPinned={Boolean(pinnedVersion)} />
132
+ ) : undefined
133
+ }
76
134
  >
77
- <div className="artifact-versions-title sp-margin-m-top">Current version</div>
78
- {currentVersion ? (
135
+ <div className="sp-margin-m-top sp-margin-xl-bottom">
79
136
  <CurrentVersion
80
137
  data={currentVersion}
81
- environment={artifact.environment}
82
- reference={artifact.reference}
138
+ environment={environment}
139
+ reference={reference}
83
140
  numNewerVersions={newerVersions?.length}
84
- pinned={pinnedVersion?.version === currentVersion.version ? toPinnedMetadata(pinnedVersion) : undefined}
141
+ pinnedVersion={pinnedVersion}
142
+ isPreview={isPreview}
85
143
  />
86
- ) : (
87
- <div>No version is deployed</div>
88
- )}
89
- {pinnedVersion && pinnedVersion.buildNumber !== currentVersion?.buildNumber && (
90
- <PinnedVersion version={pinnedVersion} />
91
- )}
92
- <PendingVersions artifact={artifact} pendingVersions={newerVersions} />
144
+ {pinnedVersion &&
145
+ pinnedVersion.buildNumber !== currentVersion?.buildNumber && // The current version is not the pinned one
146
+ !deployingVersion.some((v) => v.buildNumber === pinnedVersion.buildNumber) && ( // we are not already deploy this version
147
+ <PinnedVersion version={pinnedVersion} />
148
+ )}
149
+ </div>
150
+ <ArtifactVersions title="Now deploying" artifact={artifact} versions={deployingVersion} isDeploying={true} />
151
+ <ArtifactResources {...{ environment, resources }} />
152
+ <ArtifactVersions
153
+ title={`${pendingVersions.length} pending version` + (pendingVersions.length > 1 ? 's' : '')}
154
+ artifact={artifact}
155
+ versions={pendingVersions}
156
+ />
93
157
  </EnvironmentItem>
94
158
  );
95
159
  };
@@ -0,0 +1,19 @@
1
+ .ArtifactActionModal {
2
+ .details {
3
+ display: grid;
4
+ grid-template-columns: auto 1fr;
5
+ column-gap: 10px;
6
+ align-items: baseline;
7
+
8
+ dd {
9
+ min-width: 0;
10
+ }
11
+
12
+ dt {
13
+ font-weight: 600;
14
+ text-transform: uppercase;
15
+ font-size: 13px;
16
+ color: var(--color-concrete);
17
+ }
18
+ }
19
+ }
@@ -1,28 +1,97 @@
1
1
  import React from 'react';
2
2
 
3
3
  import { Illustration } from '@spinnaker/presentation';
4
+
5
+ import { GitLink } from './GitLink';
6
+ import { LabeledValue } from '../../../presentation';
4
7
  import { logger } from '../../../utils';
8
+ import type { ICurrentVersion, IVersionDetails, IVersionRelativeAgeToCurrent } from './utils';
9
+ import { extractVersionRollbackDetails } from './utils';
5
10
  import type { IArtifactActionModalProps } from '../../utils/ActionModal';
6
11
  import { ActionModal } from '../../utils/ActionModal';
7
12
  import { getDocsUrl } from '../../utils/defaults';
8
13
 
9
- type InternalModalProps = Omit<IArtifactActionModalProps, 'logCategory'> & { application: string };
14
+ import './ArtifactActionModal.less';
10
15
 
11
16
  const MARK_BAD_DOCS_URL = getDocsUrl('markAsBad');
12
17
  const PINNING_DOCS_URL = getDocsUrl('pinning');
13
18
 
14
- export const PinActionModal = ({ application, ...props }: InternalModalProps) => {
19
+ const CLASS_NAME = 'ArtifactActionModal';
20
+
21
+ export interface IVersionActionsProps {
22
+ application: string;
23
+ environment: string;
24
+ reference: string;
25
+ version: string;
26
+ selectedVersion: IVersionDetails;
27
+ isPinned: boolean;
28
+ isVetoed?: boolean;
29
+ isCurrent?: boolean;
30
+ }
31
+
32
+ const VersionDetails = ({ buildNumber, commitMessage, commitSha, title }: IVersionDetails & { title: string }) => {
15
33
  return (
16
- <ActionModal logCategory="Environments::Artifact" {...props}>
34
+ <div className="sp-margin-xl-top">
35
+ <div className="uppercase bold">{title}</div>
36
+ <dl className="details sp-margin-s-top">
37
+ {commitMessage && (
38
+ <LabeledValue
39
+ label="Commit"
40
+ value={
41
+ <GitLink gitMetadata={{ commitInfo: { message: commitMessage }, commit: commitSha }} asLink={false} />
42
+ }
43
+ />
44
+ )}
45
+ {buildNumber && <LabeledValue label="Build #" value={buildNumber} />}
46
+ </dl>
47
+ </div>
48
+ );
49
+ };
50
+
51
+ type InternalModalProps<T = any> = Omit<IArtifactActionModalProps, 'logCategory'> & {
52
+ actionProps: IVersionActionsProps & T;
53
+ };
54
+
55
+ export const PinActionModal = ({
56
+ actionProps,
57
+ ...props
58
+ }: InternalModalProps<
59
+ IVersionActionsProps & { ageRelativeToCurrent: IVersionRelativeAgeToCurrent; currentVersion?: ICurrentVersion }
60
+ >) => {
61
+ const {
62
+ application,
63
+ selectedVersion: { buildNumber },
64
+ isCurrent,
65
+ environment,
66
+ ageRelativeToCurrent,
67
+ currentVersion,
68
+ } = actionProps;
69
+ const rollingType = ageRelativeToCurrent === 'NEWER' ? 'forward' : 'back';
70
+ return (
71
+ <ActionModal logCategory="Environments::Artifact" className={CLASS_NAME} {...props}>
17
72
  <div className="flex-container-h middle sp-margin-xl-bottom">
18
73
  <span className="sp-margin-m-right" style={{ minWidth: 145 }}>
19
74
  <Illustration name="pinArtifactVersion" />
20
75
  </span>
21
76
  <span>
22
77
  <p>
23
- Pinning ensures an environment uses a specific version, even if Spinnaker would've normally deployed a
24
- different one. If you pin a version, it'll remain pinned until you manually unpin it.
25
- </p>{' '}
78
+ {isCurrent ? (
79
+ `Pinning ensures an environment uses a specific version, even if Spinnaker would've normally deployed a
80
+ different one. New versions won't be deployed until you unpin this version.`
81
+ ) : (
82
+ <>
83
+ Rolling {rollingType} will:
84
+ <ul className="sp-margin-xs-top">
85
+ <li>Ignore any constraints on this version</li>
86
+ <li>Deploy this version immediately</li>
87
+ <li>
88
+ Pin this version to {environment.toLocaleUpperCase()} so no other versions deploy until you unpin
89
+ </li>
90
+ </ul>
91
+ </>
92
+ )}
93
+ </p>
94
+ For more information{' '}
26
95
  <a
27
96
  target="_blank"
28
97
  onClick={() =>
@@ -34,22 +103,29 @@ export const PinActionModal = ({ application, ...props }: InternalModalProps) =>
34
103
  }
35
104
  href={PINNING_DOCS_URL}
36
105
  >
37
- Check out our documentation
38
- </a>{' '}
39
- for more information.
106
+ check out our documentation
107
+ </a>
108
+ .<p></p>
109
+ {isCurrent ? (
110
+ <p>Version #{buildNumber} is already live and no actions will be take immediately</p>
111
+ ) : (
112
+ <div>
113
+ {currentVersion && (
114
+ <VersionDetails title="Live Version" {...extractVersionRollbackDetails(currentVersion)} />
115
+ )}
116
+ <VersionDetails title={`Rolling ${rollingType} to`} {...actionProps.selectedVersion} />
117
+ </div>
118
+ )}
40
119
  </span>
41
120
  </div>
42
121
  </ActionModal>
43
122
  );
44
123
  };
45
124
 
46
- export const UnpinActionModal = ({
47
- application,
48
- environment,
49
- ...props
50
- }: InternalModalProps & { environment: string }) => {
125
+ export const UnpinActionModal = ({ actionProps, ...props }: InternalModalProps) => {
126
+ const { application, environment, isCurrent } = actionProps;
51
127
  return (
52
- <ActionModal logCategory="Environments::Artifact" {...props}>
128
+ <ActionModal logCategory="Environments::Artifact" className={CLASS_NAME} {...props}>
53
129
  <div className="flex-container-h middle sp-margin-xl-bottom">
54
130
  <span className="sp-margin-m-right" style={{ minWidth: 145 }}>
55
131
  <Illustration name="unpinArtifactVersion" />
@@ -57,79 +133,85 @@ export const UnpinActionModal = ({
57
133
  <span>
58
134
  <p>
59
135
  When you unpin this version from {environment.toUpperCase()}, Spinnaker will use the latest version that's
60
- approved for deployment.
61
- </p>{' '}
62
- <a
63
- target="_blank"
64
- onClick={() =>
65
- logger.log({
66
- category: 'Environments - unpin version modal',
67
- action: 'Pinning docs link clicked',
68
- data: { label: application, application },
69
- })
70
- }
71
- href={PINNING_DOCS_URL}
72
- >
73
- Check out our documentation
74
- </a>{' '}
75
- for more information.
136
+ approved for deployment. For more information,{' '}
137
+ <a
138
+ target="_blank"
139
+ onClick={() =>
140
+ logger.log({
141
+ category: 'Environments - unpin version modal',
142
+ action: 'Pinning docs link clicked',
143
+ data: { label: application, application },
144
+ })
145
+ }
146
+ href={PINNING_DOCS_URL}
147
+ >
148
+ Check out our documentation
149
+ </a>
150
+ .
151
+ </p>
152
+ <VersionDetails title={isCurrent ? 'Current version' : 'Unpinned version'} {...actionProps.selectedVersion} />
76
153
  </span>
77
154
  </div>
78
155
  </ActionModal>
79
156
  );
80
157
  };
81
158
 
82
- export const MarkAsBadActionModal = ({ application, ...props }: InternalModalProps) => {
159
+ export const MarkAsBadActionModal = ({ actionProps, ...props }: InternalModalProps) => {
160
+ const {
161
+ application,
162
+ isCurrent,
163
+ selectedVersion: { buildNumber },
164
+ } = actionProps;
165
+ const environment = actionProps.environment.toUpperCase();
83
166
  return (
84
- <ActionModal logCategory="Environments::Artifact" {...props}>
167
+ <ActionModal logCategory="Environments::Artifact" className={CLASS_NAME} {...props}>
85
168
  <div className="flex-container-h middle sp-margin-xl-bottom">
86
169
  <span className="sp-margin-m-right" style={{ minWidth: 145 }}>
87
170
  <Illustration name="markArtifactVersionAsBad" />
88
171
  </span>
89
172
  <span>
90
173
  <p>
91
- If you mark a version as bad in an environment, Spinnaker will never deploy it there. If the version is
92
- already deployed there, Spinnaker will immediately replace it with the latest good version approved for
93
- deployment.
94
- </p>{' '}
95
- <a
96
- target="_blank"
97
- onClick={() =>
98
- logger.log({
99
- category: 'Environments - mark version as bad modal',
100
- action: 'Mark as bad docs link clicked',
101
- data: { label: application, application },
102
- })
103
- }
104
- href={MARK_BAD_DOCS_URL}
105
- >
106
- Check out our documentation
107
- </a>{' '}
108
- for more information.
174
+ {isCurrent
175
+ ? `Spinnaker will immediately deploy the latest version approved for deployment to ${environment}. Version #${buildNumber} will be rejected and will not be deployed again`
176
+ : `This action will reject version ${buildNumber} and Spinnaker will not be deploy it to ${environment}. This will not affect the live version`}
177
+ . For more information,{' '}
178
+ <a
179
+ target="_blank"
180
+ onClick={() =>
181
+ logger.log({
182
+ category: 'Environments - mark version as bad modal',
183
+ action: 'Mark as bad docs link clicked',
184
+ data: { label: application, application },
185
+ })
186
+ }
187
+ href={MARK_BAD_DOCS_URL}
188
+ >
189
+ Check out our documentation
190
+ </a>
191
+ .
192
+ </p>
193
+ <VersionDetails title="Rejected version" {...actionProps.selectedVersion} />
109
194
  </span>
110
195
  </div>
111
196
  </ActionModal>
112
197
  );
113
198
  };
114
199
 
115
- const MarkAsGoodIntro = () => (
116
- <div className="flex-container-h middle sp-margin-xl-bottom">
117
- <span className="sp-margin-m-right" style={{ minWidth: 145 }}>
118
- <Illustration name="markArtifactVersionAsGood" />
119
- </span>
120
- <span>
121
- <p>
122
- By marking this version as good, Spinnaker will be able to deploy it again. If this is the latest version, it
123
- will be deployed immediately.
124
- </p>
125
- </span>
126
- </div>
127
- );
128
-
129
- export const MarkAsGoodActionModal = ({ application, ...props }: InternalModalProps) => {
200
+ export const MarkAsGoodActionModal = ({ actionProps, ...props }: InternalModalProps) => {
130
201
  return (
131
- <ActionModal logCategory="Environments::Artifact" {...props}>
132
- <MarkAsGoodIntro />
202
+ <ActionModal logCategory="Environments::Artifact" className={CLASS_NAME} {...props}>
203
+ <div className="flex-container-h middle sp-margin-xl-bottom">
204
+ <span className="sp-margin-m-right" style={{ minWidth: 145 }}>
205
+ <Illustration name="markArtifactVersionAsGood" />
206
+ </span>
207
+ <span>
208
+ <p>
209
+ This action will allow Spinnaker to deploy this version again. If this is the latest version, it will be
210
+ deployed immediately.
211
+ </p>
212
+ <VersionDetails title="Allowed Version" {...actionProps.selectedVersion} />
213
+ </span>
214
+ </div>
133
215
  </ActionModal>
134
216
  );
135
217
  };
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import type { ICollapsibleSectionProps } from '../../../presentation';
3
+ import { CollapsibleSection } from '../../../presentation';
4
+
5
+ interface IArtifactCollapsibleSectionProps extends ICollapsibleSectionProps {
6
+ isUpdating?: boolean;
7
+ }
8
+
9
+ export const ArtifactCollapsibleSection: React.FC<IArtifactCollapsibleSectionProps> = ({
10
+ heading,
11
+ isUpdating,
12
+ ...props
13
+ }) => {
14
+ return (
15
+ <CollapsibleSection
16
+ outerDivClassName="artifact-section"
17
+ bodyClassName="sp-padding-xl-bottom sp-padding-l-left"
18
+ toggleClassName="artifact-section-title sp-margin-l-bottom"
19
+ enableCaching={false}
20
+ expandIconSize="14px"
21
+ expandIconPosition="left"
22
+ heading={({ chevron }) => (
23
+ <div className="horizontal middle">
24
+ {chevron}
25
+ {heading}
26
+ {isUpdating && <span className="in-progress-dot" />}
27
+ </div>
28
+ )}
29
+ {...props}
30
+ />
31
+ );
32
+ };
@@ -38,6 +38,7 @@ interface IArtifactVersionTaskProps extends IBaseTaskProps {
38
38
  task: QueryArtifactVersionTask;
39
39
  }
40
40
 
41
+ // Example of a task: postDeploy and verification
41
42
  const ArtifactVersionTask = ({ type, artifact, task }: IArtifactVersionTaskProps) => {
42
43
  const status = task.status || 'PENDING';
43
44
  const { link, startedAt, completedAt } = task;
@@ -111,6 +112,7 @@ interface IArtifactVersionTasksProps extends IBaseTaskProps {
111
112
  tasks?: QueryArtifactVersionTask[];
112
113
  }
113
114
 
115
+ // Example of tasks: postDeploys and verifications
114
116
  export const ArtifactVersionTasks = ({ tasks, ...restProps }: IArtifactVersionTasksProps) => {
115
117
  if (!tasks || !tasks.length) return null;
116
118
  return (