From fc5b1cf8cf3e7d363232ef40ac208d45b81bf30c Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 18:15:59 +0000 Subject: [PATCH 1/7] feat(taskView): Implement opt-in paginated request for TaskView (#10093) (#10095) * feat(tasksview): Allowing opt-in pagination for tasks view loading * feat(taskView): Implement opt-in paginated request for TaskView (cherry picked from commit 5fa1e96b90c7398338d67ef7a7337ee3628591bd) Co-authored-by: Christos Arvanitis Co-authored-by: Jason --- packages/core/src/config/settings.ts | 1 + packages/core/src/task/task.dataSource.js | 20 ++++++++++++++++++-- packages/core/src/task/task.read.service.ts | 13 +++++++++++-- yarn.lock | 8 ++++---- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/packages/core/src/config/settings.ts b/packages/core/src/config/settings.ts index 95c2d60cbed..0b009d37e29 100644 --- a/packages/core/src/config/settings.ts +++ b/packages/core/src/config/settings.ts @@ -141,6 +141,7 @@ export interface ISpinnakerSettings { }; stashTriggerInfo?: string; pollSchedule: number; + tasksViewLimitPerPage: number; providers?: { [key: string]: IProviderSettings; // allows custom providers not typed in here (good for testing too) }; diff --git a/packages/core/src/task/task.dataSource.js b/packages/core/src/task/task.dataSource.js index 03f9ce7dc54..515e1a9c771 100644 --- a/packages/core/src/task/task.dataSource.js +++ b/packages/core/src/task/task.dataSource.js @@ -2,6 +2,7 @@ import * as angular from 'angular'; import { ApplicationDataSourceRegistry } from '../application/service/ApplicationDataSourceRegistry'; import { CLUSTER_SERVICE } from '../cluster/cluster.service'; +import { SETTINGS } from '../config'; import { TaskReader } from './task.read.service'; export const CORE_TASK_TASK_DATASOURCE = 'spinnaker.core.task.dataSource'; @@ -14,8 +15,23 @@ angular.module(CORE_TASK_TASK_DATASOURCE, [CLUSTER_SERVICE]).run([ return $q.when(angular.isArray(tasks) ? tasks : []); }; - const loadTasks = (application) => { - return TaskReader.getTasks(application.name); + const loadPaginatedTasks = async (application, page = 1) => { + let limitPerPage = SETTINGS.tasksViewLimitPerPage; + const tasks = await TaskReader.getTasks(application.name, [], limitPerPage, page); + if (tasks.length === limitPerPage) { + return tasks.concat(await loadPaginatedTasks(application, page + 1)); + } else { + return tasks; + } + }; + + const loadTasks = (application, page = 1) => { + let limitPerPage = SETTINGS.tasksViewLimitPerPage; + if (limitPerPage === undefined) { + return TaskReader.getTasks(application.name); + } else { + return loadPaginatedTasks(application, page); + } }; const loadRunningTasks = (application) => { diff --git a/packages/core/src/task/task.read.service.ts b/packages/core/src/task/task.read.service.ts index efb273b3edc..14662fc5ac6 100644 --- a/packages/core/src/task/task.read.service.ts +++ b/packages/core/src/task/task.read.service.ts @@ -8,10 +8,19 @@ import { OrchestratedItemTransformer } from '../orchestratedItem/orchestratedIte export class TaskReader { private static activeStatuses: string[] = ['RUNNING', 'SUSPENDED', 'NOT_STARTED']; - public static getTasks(applicationName: string, statuses: string[] = []): PromiseLike { + public static getTasks( + applicationName: string, + statuses: string[] = [], + limitPerPage: number = null, + page: number = null, + ): PromiseLike { return REST('/applications') .path(applicationName, 'tasks') - .query({ statuses: statuses.join(',') }) + .query({ + statuses: statuses.join(','), + limit: limitPerPage, + page: page, + }) .get() .then((tasks: ITask[]) => { tasks.forEach((task) => this.setTaskProperties(task)); diff --git a/yarn.lock b/yarn.lock index 3d3034a9dea..c75f48e9d1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18292,10 +18292,10 @@ vite-plugin-svgr@^0.3.0: dependencies: "@svgr/core" "^5.5.0" -vite@2.9.16: - version "2.9.16" - resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.16.tgz#daf7ba50f5cc37a7bf51b118ba06bc36e97898e9" - integrity sha512-X+6q8KPyeuBvTQV8AVSnKDvXoBMnTx8zxh54sOwmmuOdxkjMmEJXH2UEchA+vTMps1xw9vL64uwJOWryULg7nA== +vite@2.9.18: + version "2.9.18" + resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.18.tgz#74e2a83b29da81e602dac4c293312cc575f091c7" + integrity sha512-sAOqI5wNM9QvSEE70W3UGMdT8cyEn0+PmJMTFvTB8wB0YbYUWw3gUbY62AOyrXosGieF2htmeLATvNxpv/zNyQ== dependencies: esbuild "^0.14.27" postcss "^8.4.13" From 6775182f09a0e25b806ab171e6ae8ab5e682328e Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 13:37:07 +0000 Subject: [PATCH 2/7] fix(pipelineGraph): Handling exception when requisiteStageRefIds is not defined (#10086) (#10088) (cherry picked from commit 4e1635d6026c6fbcb5912de1859c45038fd1258a) Co-authored-by: Christos Arvanitis --- .../core/src/pipeline/config/services/PipelineConfigService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/pipeline/config/services/PipelineConfigService.ts b/packages/core/src/pipeline/config/services/PipelineConfigService.ts index 0d32a9943ae..8fd8c6d5331 100644 --- a/packages/core/src/pipeline/config/services/PipelineConfigService.ts +++ b/packages/core/src/pipeline/config/services/PipelineConfigService.ts @@ -142,6 +142,9 @@ export class PipelineConfigService { private static groupStagesByRequisiteStageRefIds(pipeline: IPipeline) { return pipeline.stages.reduce((acc, obj) => { const parent = obj['refId']; + if (obj['requisiteStageRefIds'] === undefined) { + obj['requisiteStageRefIds'] = []; + } obj.requisiteStageRefIds.forEach((child) => { const values = acc.get(child); if (values && values.length) { From f660a02a6651da7726e49d710aa71dbccca19f0e Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 13:53:14 +0000 Subject: [PATCH 3/7] fix(lambdaStages): Exporting Lambda stages based on the feature flag settings (#10085) (#10091) Co-authored-by: Jason Co-authored-by: ovidiupopa07 <105648914+ovidiupopa07@users.noreply.github.com> (cherry picked from commit 93bab656555fabd539e186587a40dd8a0358dbd9) Co-authored-by: Christos Arvanitis --- packages/amazon/src/aws.module.ts | 8 +++++ .../src/pipeline/stages/deleteLambda/index.ts | 14 ++++++--- .../components/AwsLambdaFunctionStageForm.tsx | 3 +- .../src/pipeline/stages/deployLambda/index.ts | 13 +++++++-- .../src/pipeline/stages/invokeLambda/index.ts | 13 +++++++-- .../RouteLambdaFunctionStageForm.tsx | 3 +- .../src/pipeline/stages/routeLambda/index.ts | 13 +++++++-- .../LambdaUpdateCodeStage.less | 5 ++++ .../pipeline/stages/updateCodeLambda/index.ts | 13 +++++++-- .../forms/inputs/NumberConcurrencyInput.tsx | 29 ------------------- 10 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 packages/amazon/src/pipeline/stages/updateCodeLambda/LambdaUpdateCodeStage.less delete mode 100644 packages/core/src/presentation/forms/inputs/NumberConcurrencyInput.tsx diff --git a/packages/amazon/src/aws.module.ts b/packages/amazon/src/aws.module.ts index d06b6dc7c21..69880732559 100644 --- a/packages/amazon/src/aws.module.ts +++ b/packages/amazon/src/aws.module.ts @@ -26,22 +26,26 @@ import { AWS_LOAD_BALANCER_MODULE } from './loadBalancer/loadBalancer.module'; import amazonLogo from './logo/amazon.logo.svg'; import { AMAZON_PIPELINE_STAGES_BAKE_AWSBAKESTAGE } from './pipeline/stages/bake/awsBakeStage'; import { AMAZON_PIPELINE_STAGES_CLONESERVERGROUP_AWSCLONESERVERGROUPSTAGE } from './pipeline/stages/cloneServerGroup/awsCloneServerGroupStage'; +import { AMAZON_PIPELINE_STAGES_LAMBDA_DELETE } from './pipeline/stages/deleteLambda'; import { CLOUD_FORMATION_CHANGE_SET_INFO } from './pipeline/stages/deployCloudFormation/CloudFormationChangeSetInfo'; import { CLOUDFORMATION_TEMPLATE_ENTRY } from './pipeline/stages/deployCloudFormation/cloudFormationTemplateEntry.component'; import { DEPLOY_CLOUDFORMATION_STACK_STAGE } from './pipeline/stages/deployCloudFormation/deployCloudFormationStackStage'; import { AWS_EVALUATE_CLOUD_FORMATION_CHANGE_SET_EXECUTION_SERVICE } from './pipeline/stages/deployCloudFormation/evaluateCloudFormationChangeSetExecution.service'; +import { AMAZON_PIPELINE_STAGES_LAMBDA_DEPLOY } from './pipeline/stages/deployLambda'; import { AMAZON_PIPELINE_STAGES_DESTROYASG_AWSDESTROYASGSTAGE } from './pipeline/stages/destroyAsg/awsDestroyAsgStage'; import { AMAZON_PIPELINE_STAGES_DISABLEASG_AWSDISABLEASGSTAGE } from './pipeline/stages/disableAsg/awsDisableAsgStage'; import { AMAZON_PIPELINE_STAGES_DISABLECLUSTER_AWSDISABLECLUSTERSTAGE } from './pipeline/stages/disableCluster/awsDisableClusterStage'; import { AMAZON_PIPELINE_STAGES_ENABLEASG_AWSENABLEASGSTAGE } from './pipeline/stages/enableAsg/awsEnableAsgStage'; import { AMAZON_PIPELINE_STAGES_FINDAMI_AWSFINDAMISTAGE } from './pipeline/stages/findAmi/awsFindAmiStage'; import { AMAZON_PIPELINE_STAGES_FINDIMAGEFROMTAGS_AWSFINDIMAGEFROMTAGSSTAGE } from './pipeline/stages/findImageFromTags/awsFindImageFromTagsStage'; +import { AMAZON_PIPELINE_STAGES_LAMBDA_INVOKE } from './pipeline/stages/invokeLambda'; import { AMAZON_PIPELINE_STAGES_MODIFYSCALINGPROCESS_MODIFYSCALINGPROCESSSTAGE } from './pipeline/stages/modifyScalingProcess/modifyScalingProcessStage'; import { AMAZON_PIPELINE_STAGES_RESIZEASG_AWSRESIZEASGSTAGE } from './pipeline/stages/resizeAsg/awsResizeAsgStage'; import { AMAZON_PIPELINE_STAGES_ROLLBACKCLUSTER_AWSROLLBACKCLUSTERSTAGE } from './pipeline/stages/rollbackCluster/awsRollbackClusterStage'; import { AMAZON_PIPELINE_STAGES_SCALEDOWNCLUSTER_AWSSCALEDOWNCLUSTERSTAGE } from './pipeline/stages/scaleDownCluster/awsScaleDownClusterStage'; import { AMAZON_PIPELINE_STAGES_SHRINKCLUSTER_AWSSHRINKCLUSTERSTAGE } from './pipeline/stages/shrinkCluster/awsShrinkClusterStage'; import { AMAZON_PIPELINE_STAGES_TAGIMAGE_AWSTAGIMAGESTAGE } from './pipeline/stages/tagImage/awsTagImageStage'; +import { AMAZON_PIPELINE_STAGES_LAMBDA_UPDATE } from './pipeline/stages/updateCodeLambda'; import { AWS_REACT_MODULE } from './reactShims/aws.react.module'; import { AMAZON_SEARCH_SEARCHRESULTFORMATTER } from './search/searchResultFormatter'; import { AWS_SECURITY_GROUP_MODULE } from './securityGroup/securityGroup.module'; @@ -114,6 +118,10 @@ module(AMAZON_MODULE, [ INSTANCE_SECURITY_GROUPS_COMPONENT, INSTANCE_DNS_COMPONENT, AMAZON_INSTANCE_INFORMATION_COMPONENT, + AMAZON_PIPELINE_STAGES_LAMBDA_DELETE, + AMAZON_PIPELINE_STAGES_LAMBDA_DEPLOY, + AMAZON_PIPELINE_STAGES_LAMBDA_INVOKE, + AMAZON_PIPELINE_STAGES_LAMBDA_UPDATE, ]).config(() => { CloudProviderRegistry.registerProvider('aws', { name: 'Amazon', diff --git a/packages/amazon/src/pipeline/stages/deleteLambda/index.ts b/packages/amazon/src/pipeline/stages/deleteLambda/index.ts index a2bcdd62906..9df8bc99929 100644 --- a/packages/amazon/src/pipeline/stages/deleteLambda/index.ts +++ b/packages/amazon/src/pipeline/stages/deleteLambda/index.ts @@ -1,11 +1,17 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +import { module } from 'angular'; + import { Registry, SETTINGS } from '@spinnaker/core'; -import { lambdaDeleteStage } from './LambdaDeleteStage'; +import { lambdaDeleteStage } from './LambdaDeleteStage'; export * from './LambdaDeleteStage'; -if (SETTINGS.feature.lambdaAdditionalStages) { - Registry.pipeline.registerStage(lambdaDeleteStage); -} +export const AMAZON_PIPELINE_STAGES_LAMBDA_DELETE = 'spinnaker.amazon.pipeline.stage.Aws.LambdaDeleteStage'; + +module(AMAZON_PIPELINE_STAGES_LAMBDA_DELETE, []).config(function () { + if (SETTINGS.feature.lambdaAdditionalStages) { + Registry.pipeline.registerStage(lambdaDeleteStage); + } +}); diff --git a/packages/amazon/src/pipeline/stages/deployLambda/components/AwsLambdaFunctionStageForm.tsx b/packages/amazon/src/pipeline/stages/deployLambda/components/AwsLambdaFunctionStageForm.tsx index bbe837f855b..9e03752a57b 100644 --- a/packages/amazon/src/pipeline/stages/deployLambda/components/AwsLambdaFunctionStageForm.tsx +++ b/packages/amazon/src/pipeline/stages/deployLambda/components/AwsLambdaFunctionStageForm.tsx @@ -15,7 +15,6 @@ import { TetheredCreatable, TextInput, } from '@spinnaker/core'; -import { NumberConcurrencyInput } from '@spinnaker/core/dist/presentation/forms/inputs/NumberConcurrencyInput'; import { BasicSettingsForm, ExecutionRoleForm, LambdaAtEdgeForm, NetworkForm, TriggerEventsForm } from './index'; @@ -96,7 +95,7 @@ export function AwsLambdaFunctionStageForm(props: IFormikStageConfigInjectedProp help={ } - input={(props) => } + input={(props) => } /> ) : ( - + ) } required={false} diff --git a/packages/amazon/src/pipeline/stages/routeLambda/index.ts b/packages/amazon/src/pipeline/stages/routeLambda/index.ts index 154d3d60cb2..3ae71566143 100644 --- a/packages/amazon/src/pipeline/stages/routeLambda/index.ts +++ b/packages/amazon/src/pipeline/stages/routeLambda/index.ts @@ -1,11 +1,18 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +import { module } from 'angular'; + import { Registry, SETTINGS } from '@spinnaker/core'; + import { lambdaRouteStage } from './LambdaRouteStage'; export * from './LambdaRouteStage'; -if (SETTINGS.feature.lambdaAdditionalStages) { - Registry.pipeline.registerStage(lambdaRouteStage); -} +export const AMAZON_PIPELINE_STAGES_LAMBDA_ROUTE = 'spinnaker.amazon.pipeline.stage.Aws.LambdaTrafficRoutingStage'; + +module(AMAZON_PIPELINE_STAGES_LAMBDA_ROUTE, []).config(function () { + if (SETTINGS.feature.lambdaAdditionalStages) { + Registry.pipeline.registerStage(lambdaRouteStage); + } +}); diff --git a/packages/amazon/src/pipeline/stages/updateCodeLambda/LambdaUpdateCodeStage.less b/packages/amazon/src/pipeline/stages/updateCodeLambda/LambdaUpdateCodeStage.less new file mode 100644 index 00000000000..35112591771 --- /dev/null +++ b/packages/amazon/src/pipeline/stages/updateCodeLambda/LambdaUpdateCodeStage.less @@ -0,0 +1,5 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +.LambdaCodeUpdateStageConfig { +} diff --git a/packages/amazon/src/pipeline/stages/updateCodeLambda/index.ts b/packages/amazon/src/pipeline/stages/updateCodeLambda/index.ts index f8f0dccc76a..65297db27d3 100644 --- a/packages/amazon/src/pipeline/stages/updateCodeLambda/index.ts +++ b/packages/amazon/src/pipeline/stages/updateCodeLambda/index.ts @@ -1,11 +1,18 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +import { module } from 'angular'; + import { Registry, SETTINGS } from '@spinnaker/core'; + import { lambdaUpdateCodeStage } from './LambdaUpdateCodeStage'; export * from './LambdaUpdateCodeStage'; -if (SETTINGS.feature.lambdaAdditionalStages) { - Registry.pipeline.registerStage(lambdaUpdateCodeStage); -} +export const AMAZON_PIPELINE_STAGES_LAMBDA_UPDATE = 'spinnaker.amazon.pipeline.stage.Aws.LambdaUpdateCodeStage'; + +module(AMAZON_PIPELINE_STAGES_LAMBDA_UPDATE, []).config(function () { + if (SETTINGS.feature.lambdaAdditionalStages) { + Registry.pipeline.registerStage(lambdaUpdateCodeStage); + } +}); diff --git a/packages/core/src/presentation/forms/inputs/NumberConcurrencyInput.tsx b/packages/core/src/presentation/forms/inputs/NumberConcurrencyInput.tsx deleted file mode 100644 index 81970637415..00000000000 --- a/packages/core/src/presentation/forms/inputs/NumberConcurrencyInput.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; - -import { useInternalValidator } from './hooks'; -import type { IFormInputProps, OmitControlledInputPropsFrom } from './interface'; -import { orEmptyString, validationClassName } from './utils'; -import type { IValidator } from '../validation'; -import { composeValidators, Validators } from '../validation'; - -interface INumberInputProps extends IFormInputProps, OmitControlledInputPropsFrom> { - inputClassName?: string; -} - -const isNumber = (val: any): val is number => typeof val === 'number'; - -export function NumberConcurrencyInput(props: INumberInputProps) { - const { value, validation, inputClassName, ...otherProps } = props; - - const minMaxValidator: IValidator = (val: any, label?: string) => { - const minValidator = isNumber(props.min) ? Validators.minValue(props.min) : undefined; - const maxValidator = isNumber(props.max) ? Validators.maxValue(props.max) : undefined; - const validator = composeValidators([minValidator, maxValidator]); - return validator ? validator(val, label) : null; - }; - - useInternalValidator(validation, minMaxValidator); - - const className = `NumberInput form-control ${orEmptyString(inputClassName)} ${validationClassName(validation)}`; - return ; -} From de401d5ad8429fe2f5996c488e14ef96ededa006 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 16:50:05 +0000 Subject: [PATCH 4/7] fix(lambda): Invoke stage excludedArtifactTypes not including the embedded-artifact type (#10097) (#10101) (cherry picked from commit 9374f0630afb6a174bacf64e9f2ced750bbf4f1d) Co-authored-by: Christos Arvanitis --- .../stages/invokeLambda/components/InvokeLambdaOperation.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/amazon/src/pipeline/stages/invokeLambda/components/InvokeLambdaOperation.tsx b/packages/amazon/src/pipeline/stages/invokeLambda/components/InvokeLambdaOperation.tsx index d328d53735f..fc9efe1eb0f 100644 --- a/packages/amazon/src/pipeline/stages/invokeLambda/components/InvokeLambdaOperation.tsx +++ b/packages/amazon/src/pipeline/stages/invokeLambda/components/InvokeLambdaOperation.tsx @@ -19,6 +19,7 @@ export function InvokeLambdaOperation(props: IFormikStageConfigInjectedProps) { ArtifactTypePatterns.BITBUCKET_FILE, ArtifactTypePatterns.CUSTOM_OBJECT, ArtifactTypePatterns.EMBEDDED_BASE64, + ArtifactTypePatterns.REMOTE_BASE64, ArtifactTypePatterns.GCS_OBJECT, ArtifactTypePatterns.GITHUB_FILE, ArtifactTypePatterns.GITLAB_FILE, From ccb4e4ec0d5e489da04d98e67dbeab56760b34e2 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 16:35:43 +0000 Subject: [PATCH 5/7] fix(pipeline): Handle render/validation when stageTimeoutMs is a Spel expression (#10103) (#10105) (cherry picked from commit 9237f7890e5f02f5369bc91984de98b18591ef9e) Co-authored-by: Christos Arvanitis --- .../overrideTimeout/OverrideTimeout.tsx | 28 ++++++++++++++++--- .../validation/PipelineConfigValidator.ts | 6 +++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/core/src/pipeline/config/stages/overrideTimeout/OverrideTimeout.tsx b/packages/core/src/pipeline/config/stages/overrideTimeout/OverrideTimeout.tsx index 8b31a7e9696..841092e09d1 100644 --- a/packages/core/src/pipeline/config/stages/overrideTimeout/OverrideTimeout.tsx +++ b/packages/core/src/pipeline/config/stages/overrideTimeout/OverrideTimeout.tsx @@ -1,4 +1,4 @@ -import { get } from 'lodash'; +import { get, isNumber } from 'lodash'; import { Duration } from 'luxon'; import React from 'react'; @@ -10,7 +10,7 @@ const { useEffect, useState } = React; export interface IOverrideTimeoutConfigProps { stageConfig: IStageConfig; - stageTimeoutMs: number; + stageTimeoutMs: number | any; updateStageField: (changes: Partial) => void; } @@ -41,8 +41,13 @@ export const OverrideTimeout = (props: IOverrideTimeoutConfigProps) => { }, [props.stageTimeoutMs]); const stageChanged = () => { - if (props.stageTimeoutMs !== undefined) { + if (props.stageTimeoutMs !== undefined && !isExpression) { enableTimeout(); + } else if (props.stageTimeoutMs !== undefined && isExpression) { + setOverrideTimeout(true); + props.updateStageField({ + stageTimeoutMs: props.stageTimeoutMs || null, + }); } else { clearTimeout(); } @@ -74,6 +79,10 @@ export const OverrideTimeout = (props: IOverrideTimeoutConfigProps) => { }; const isConfigurable = !!get(props.stageConfig, 'supportsCustomTimeout'); + const isExpression = + props.stageTimeoutMs !== undefined && props.stageTimeoutMs !== null && !isNumber(props.stageTimeoutMs) + ? props.stageTimeoutMs.includes('${') + : false; if (isConfigurable) { return ( @@ -94,7 +103,7 @@ export const OverrideTimeout = (props: IOverrideTimeoutConfigProps) => { - {overrideTimeout && ( + {overrideTimeout && !isExpression && (
@@ -123,6 +132,17 @@ export const OverrideTimeout = (props: IOverrideTimeoutConfigProps) => {
)} + {overrideTimeout && isExpression && ( +
+
+
+ + Resolved at runtime from expression: {props.stageTimeoutMs} + +
+
+
+ )} ); } else { diff --git a/packages/core/src/pipeline/config/validation/PipelineConfigValidator.ts b/packages/core/src/pipeline/config/validation/PipelineConfigValidator.ts index 19c2f7f3dcc..2e37c59b415 100644 --- a/packages/core/src/pipeline/config/validation/PipelineConfigValidator.ts +++ b/packages/core/src/pipeline/config/validation/PipelineConfigValidator.ts @@ -54,6 +54,10 @@ export interface ICustomValidator extends IStageOrTriggerValidator, IValidatorCo [k: string]: any; } +function isNumberOrSpel(valInput: any) { + return (isNumber(valInput) && valInput > 0) || (typeof valInput === 'string' && valInput.includes('${')); +} + export class PipelineConfigValidator { private static validators: Map = new Map(); private static validationStream: Subject = new Subject(); @@ -151,7 +155,7 @@ export class PipelineConfigValidator { ); } - if (stage.stageTimeoutMs !== undefined && !(isNumber(stage.stageTimeoutMs) && stage.stageTimeoutMs > 0)) { + if (stage.stageTimeoutMs !== undefined && !isNumberOrSpel(stage.stageTimeoutMs)) { stageValidations.set(stage, [ ...(stageValidations.get(stage) || []), 'Stage is configured to fail after a specific amount of time, but no time is set.', From 6dc1e42e2bc95ccf0076c19705fce1b5bfebfaf9 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 18:14:47 +0000 Subject: [PATCH 6/7] fix(redblack): fixing redblack onchange values (#10107) (#10110) * fix(redblack): fixing redblack onchange values * fix(lint): fixing linting erros * fix(lint): fixing linting - lodash * fix(prettier): fixing prettier for AdditionalFields.tsx --------- Co-authored-by: ovidiupopa07 <105648914+ovidiupopa07@users.noreply.github.com> (cherry picked from commit 443408e7f6404b10d195b146f2f68fe926c2413a) Co-authored-by: Shlomo Daari <104773977+shlomodaari@users.noreply.github.com> --- .../strategies/redblack/AdditionalFields.tsx | 165 ++++++++++-------- 1 file changed, 97 insertions(+), 68 deletions(-) diff --git a/packages/core/src/deploymentStrategy/strategies/redblack/AdditionalFields.tsx b/packages/core/src/deploymentStrategy/strategies/redblack/AdditionalFields.tsx index 1142429eb42..b243a78d22c 100644 --- a/packages/core/src/deploymentStrategy/strategies/redblack/AdditionalFields.tsx +++ b/packages/core/src/deploymentStrategy/strategies/redblack/AdditionalFields.tsx @@ -8,72 +8,101 @@ export interface IRedBlackStrategyAdditionalFieldsProps extends IDeploymentStrat command: IRedBlackCommand; } -export const AdditionalFields = ({ command, onChange }: IRedBlackStrategyAdditionalFieldsProps) => ( -
-
- -
-
- -
-
- - onChange('maxRemainingAsgs', e.target.value)} - min="2" - /> -
-
- - onChange('delayBeforeDisableSec', e.target.value)} - placeholder="0" - /> - seconds -
- {command.scaleDown && ( -
- - onChange('delayBeforeScaleDownSec', e.target.value)} - placeholder="0" - /> - seconds +export class AdditionalFields extends React.Component { + private rollbackOnFailureChange = (e: React.ChangeEvent) => { + this.props.command.rollback.onFailure = e.target.checked; + this.forceUpdate(); + }; + + private scaleDownChange = (e: React.ChangeEvent) => { + this.props.command.scaleDown = e.target.checked; + this.forceUpdate(); + }; + + private maxRemainingAsgsChange = (e: React.ChangeEvent) => { + this.props.command.maxRemainingAsgs = parseInt(e.target.value, 10); + this.forceUpdate(); + }; + + private delayBeforeDisableSecChange = (e: React.ChangeEvent) => { + this.props.command.delayBeforeDisableSec = parseInt(e.target.value, 10); + this.forceUpdate(); + }; + + private delayBeforeScaleDownSecChange = (e: React.ChangeEvent) => { + this.props.command.delayBeforeScaleDownSec = parseInt(e.target.value, 10); + this.forceUpdate(); + }; + + public render() { + const { command } = this.props; + return ( +
+
+ +
+
+ +
+
+ + +
+
+ + + seconds +
+ {command.scaleDown && ( +
+ + + seconds +
+ )}
- )} -
-); + ); + } +} From 4de853db136e67d8d4bc01ce3e57fa152fe59c14 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:19:08 +0000 Subject: [PATCH 7/7] fix(lambda): Export LambdaRoute stage on aws module (#10116) (#10118) (cherry picked from commit 1f6d2c1a69bfae5fd8b6bb9f5fbf0b7fb86930d3) Co-authored-by: Christos Arvanitis --- packages/amazon/src/aws.module.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/amazon/src/aws.module.ts b/packages/amazon/src/aws.module.ts index 69880732559..1c0aca5aa88 100644 --- a/packages/amazon/src/aws.module.ts +++ b/packages/amazon/src/aws.module.ts @@ -42,6 +42,7 @@ import { AMAZON_PIPELINE_STAGES_LAMBDA_INVOKE } from './pipeline/stages/invokeLa import { AMAZON_PIPELINE_STAGES_MODIFYSCALINGPROCESS_MODIFYSCALINGPROCESSSTAGE } from './pipeline/stages/modifyScalingProcess/modifyScalingProcessStage'; import { AMAZON_PIPELINE_STAGES_RESIZEASG_AWSRESIZEASGSTAGE } from './pipeline/stages/resizeAsg/awsResizeAsgStage'; import { AMAZON_PIPELINE_STAGES_ROLLBACKCLUSTER_AWSROLLBACKCLUSTERSTAGE } from './pipeline/stages/rollbackCluster/awsRollbackClusterStage'; +import { AMAZON_PIPELINE_STAGES_LAMBDA_ROUTE } from './pipeline/stages/routeLambda'; import { AMAZON_PIPELINE_STAGES_SCALEDOWNCLUSTER_AWSSCALEDOWNCLUSTERSTAGE } from './pipeline/stages/scaleDownCluster/awsScaleDownClusterStage'; import { AMAZON_PIPELINE_STAGES_SHRINKCLUSTER_AWSSHRINKCLUSTERSTAGE } from './pipeline/stages/shrinkCluster/awsShrinkClusterStage'; import { AMAZON_PIPELINE_STAGES_TAGIMAGE_AWSTAGIMAGESTAGE } from './pipeline/stages/tagImage/awsTagImageStage'; @@ -122,6 +123,7 @@ module(AMAZON_MODULE, [ AMAZON_PIPELINE_STAGES_LAMBDA_DEPLOY, AMAZON_PIPELINE_STAGES_LAMBDA_INVOKE, AMAZON_PIPELINE_STAGES_LAMBDA_UPDATE, + AMAZON_PIPELINE_STAGES_LAMBDA_ROUTE, ]).config(() => { CloudProviderRegistry.registerProvider('aws', { name: 'Amazon',