From a4c0df8947905dede7fb9b4dd0c614ff83238dd9 Mon Sep 17 00:00:00 2001 From: Gostuski Date: Mon, 29 May 2023 18:44:20 +0200 Subject: [PATCH 1/3] Implement action execution type --- commands/actions/init.go | 105 +++++++---- commands/actions/publish.go | 164 ++++++++++++------ model/actions/action.go | 22 ++- .../generated/actions/structs.conjure.go | 11 +- 4 files changed, 207 insertions(+), 95 deletions(-) diff --git a/commands/actions/init.go b/commands/actions/init.go index f84c77b..797c15e 100644 --- a/commands/actions/init.go +++ b/commands/actions/init.go @@ -57,15 +57,24 @@ module.exports = { blockHelloWorldFn }; var initDescription = "This is just an example, but you can publish this action." var initAction = &actionsModel.ActionSpec{ - Description: &initDescription, - Function: "example:blockHelloWorldFn", - Trigger: actionsModel.TriggerUnparsed{Type: "block"}, + Description: &initDescription, + Function: "example:blockHelloWorldFn", + Trigger: actionsModel.TriggerUnparsed{Type: "block"}, + ExecutionType: "sequential", } func init() { - initCmd.PersistentFlags().StringVar(&actionsSourcesDir, "sources", "", "The path where the actions will be created.") - initCmd.PersistentFlags().StringVar(&actionsLanguage, "language", "typescript", "Initialize actions for this language. Supported {javascript, typescript}") - initCmd.PersistentFlags().StringVar(&actionsTemplateName, "template", "", "Initialize actions from this template, see Tenderly/tenderly-actions.") + initCmd.PersistentFlags().StringVar( + &actionsSourcesDir, "sources", "", "The path where the actions will be created.", + ) + initCmd.PersistentFlags().StringVar( + &actionsLanguage, "language", "typescript", + "Initialize actions for this language. Supported {javascript, typescript}", + ) + initCmd.PersistentFlags().StringVar( + &actionsTemplateName, "template", "", + "Initialize actions from this template, see Tenderly/tenderly-actions.", + ) actionsCmd.AddCommand(initCmd) } @@ -88,11 +97,13 @@ var initCmd = &cobra.Command{ "Actions for project are already initialized", userError.NewUserError( fmt.Errorf("actions initialized"), - commands.Colorizer.Sprintf("Actions for project %s are already initialized, see %s", + commands.Colorizer.Sprintf( + "Actions for project %s are already initialized, see %s", commands.Colorizer.Bold(commands.Colorizer.Green(projectSlug)), commands.Colorizer.Bold(commands.Colorizer.Green("tenderly.yaml")), ), - )) + ), + ) os.Exit(0) } @@ -106,7 +117,10 @@ var initCmd = &cobra.Command{ if err != nil { userError.LogErrorf( "failed to load template", - userError.NewUserError(err, fmt.Sprintf("Failed to load template %s", actionsTemplateName))) + userError.NewUserError( + err, fmt.Sprintf("Failed to load template %s", actionsTemplateName), + ), + ) os.Exit(1) } @@ -127,17 +141,22 @@ var initCmd = &cobra.Command{ if err != nil { userError.LogErrorf( "failed to load template specs", - userError.NewUserError(err, fmt.Sprintf("Failed to load specs for template %s", actionsTemplateName))) + userError.NewUserError( + err, fmt.Sprintf("Failed to load specs for template %s", actionsTemplateName), + ), + ) os.Exit(1) } } - config.MustWriteActionsInit(projectSlug, &actionsModel.ProjectActions{ - Runtime: actionsModel.RuntimeV2, - Sources: sources, - Dependencies: nil, - Specs: specs, - }) + config.MustWriteActionsInit( + projectSlug, &actionsModel.ProjectActions{ + Runtime: actionsModel.RuntimeV2, + Sources: sources, + Dependencies: nil, + Specs: specs, + }, + ) if actionsLanguage == LanguageJavaScript { filePath := filepath.Join(sources, "example.js") @@ -145,10 +164,13 @@ var initCmd = &cobra.Command{ util.CreateFileWithContent(filePath, content) - logrus.Info(commands.Colorizer.Sprintf("\nInitialized actions project. Sources directory created at %s. Configuration created in %s.", - commands.Colorizer.Bold(commands.Colorizer.Green(sources)), - commands.Colorizer.Bold(commands.Colorizer.Green("tenderly.yaml")), - )) + logrus.Info( + commands.Colorizer.Sprintf( + "\nInitialized actions project. Sources directory created at %s. Configuration created in %s.", + commands.Colorizer.Bold(commands.Colorizer.Green(sources)), + commands.Colorizer.Bold(commands.Colorizer.Green("tenderly.yaml")), + ), + ) os.Exit(0) } @@ -183,7 +205,10 @@ var initCmd = &cobra.Command{ if err != nil { userError.LogErrorf( "failed to create from template", - userError.NewUserError(err, fmt.Sprintf("Failed to create from template %s", actionsTemplateName))) + userError.NewUserError( + err, fmt.Sprintf("Failed to create from template %s", actionsTemplateName), + ), + ) os.Exit(1) } } @@ -191,10 +216,13 @@ var initCmd = &cobra.Command{ // Install dependencies mustInstallDependencies(sources) - logrus.Info(commands.Colorizer.Sprintf("\nInitialized actions project. Sources directory created at %s. Configuration created in %s.", - commands.Colorizer.Bold(commands.Colorizer.Green(sources)), - commands.Colorizer.Bold(commands.Colorizer.Green("tenderly.yaml")), - )) + logrus.Info( + commands.Colorizer.Sprintf( + "\nInitialized actions project. Sources directory created at %s. Configuration created in %s.", + commands.Colorizer.Bold(commands.Colorizer.Green(sources)), + commands.Colorizer.Bold(commands.Colorizer.Green("tenderly.yaml")), + ), + ) os.Exit(0) }, @@ -229,8 +257,10 @@ func promptTemplateArg(arg actionsModel.TemplateArg) string { if result == "" { userError.LogErrorf( "value for template arg not entered", - userError.NewUserError(errors.New("enter template arg"), - "Value for template arg not entered correctly"), + userError.NewUserError( + errors.New("enter template arg"), + "Value for template arg not entered correctly", + ), ) os.Exit(1) } @@ -241,7 +271,11 @@ func mustValidateFlags() { if actionsLanguage != LanguageTypeScript && actionsLanguage != LanguageJavaScript { userError.LogErrorf( "language not supported", - userError.NewUserError(errors.New("language not supported"), fmt.Sprintf("Language %s not supported", actionsLanguage))) + userError.NewUserError( + errors.New("language not supported"), + fmt.Sprintf("Language %s not supported", actionsLanguage), + ), + ) os.Exit(1) } } @@ -251,8 +285,10 @@ func chooseSources() string { if util.ExistFile(actionsSourcesDir) { userError.LogErrorf( "sources dir is file: %s", - userError.NewUserError(errors.New("sources dir is file"), - "Selected sources directory is a file."), + userError.NewUserError( + errors.New("sources dir is file"), + "Selected sources directory is a file.", + ), ) os.Exit(1) } @@ -260,8 +296,10 @@ func chooseSources() string { if util.ExistDir(actionsSourcesDir) { userError.LogErrorf( "sources dir exists: %s", - userError.NewUserError(errors.New("sources dir exists"), - "Selected sources directory already exists."), + userError.NewUserError( + errors.New("sources dir exists"), + "Selected sources directory already exists.", + ), ) os.Exit(1) } @@ -324,7 +362,8 @@ func excludeFromTsconfigParent(sourcesPath string, parentPath string) { if err != nil { userError.LogErrorf( "failed to get path relative to parentPath", - userError.NewUserError(err, fmt.Sprintf("Can't find relative path for %s", sourcesPath))) + userError.NewUserError(err, fmt.Sprintf("Can't find relative path for %s", sourcesPath)), + ) os.Exit(1) } rel = relTmp diff --git a/commands/actions/publish.go b/commands/actions/publish.go index 4cfc053..6cc63cb 100644 --- a/commands/actions/publish.go +++ b/commands/actions/publish.go @@ -86,17 +86,28 @@ func buildFunc(cmd *cobra.Command, args []string) { actions = mustGetProjectActions(allActions, projectSlug) logrus.Info("\nBuilding actions:") for actionName := range actions.Specs { - logrus.Info(commands.Colorizer.Sprintf( - "- %s", commands.Colorizer.Bold(commands.Colorizer.Green(actionName)))) + logrus.Info( + commands.Colorizer.Sprintf( + "- %s", commands.Colorizer.Bold(commands.Colorizer.Green(actionName)), + ), + ) } util.MustExistDir(actions.Sources) if !actionsModel.IsRuntimeSupported(actions.Runtime) { - logrus.Error(commands.Colorizer.Sprintf( - "Configured runtime %s is not supported. Supported values: {%s}", - commands.Colorizer.Bold(commands.Colorizer.Red(actions.Runtime)), - commands.Colorizer.Bold(commands.Colorizer.Green(strings.Join(actionsModel.SupportedRuntimes, ","))), - )) + logrus.Error( + commands.Colorizer.Sprintf( + "Configured runtime %s is not supported. Supported values: {%s}", + commands.Colorizer.Bold(commands.Colorizer.Red(actions.Runtime)), + commands.Colorizer.Bold( + commands.Colorizer.Green( + strings.Join( + actionsModel.SupportedRuntimes, ",", + ), + ), + ), + ), + ) os.Exit(1) } mustParseAndValidateTriggers(actions) @@ -104,13 +115,20 @@ func buildFunc(cmd *cobra.Command, args []string) { tsConfigExists := util.TsConfigExists(actions.Sources) tsFileExists, tsFile := anyFunctionTsFileExists(actions) if tsFileExists && !tsConfigExists { - err := errors.New(fmt.Sprintf("File %s is a typescript file but there is no typescript config file!", tsFile)) - userError.LogErrorf("missing typescript config file %s", - userError.NewUserError(err, + err := errors.New( + fmt.Sprintf( + "File %s is a typescript file but there is no typescript config file!", tsFile, + ), + ) + userError.LogErrorf( + "missing typescript config file %s", + userError.NewUserError( + err, commands.Colorizer.Sprintf( "Missing typescript config file in your sources! Sources: %s, File: %s", commands.Colorizer.Bold(commands.Colorizer.Red(actions.Sources)), - commands.Colorizer.Bold(commands.Colorizer.Red(tsFile))), + commands.Colorizer.Bold(commands.Colorizer.Red(tsFile)), + ), ), ) os.Exit(1) @@ -161,11 +179,14 @@ func mustParseAndValidateTriggers(projectActions *actionsModel.ProjectActions) { for name, spec := range projectActions.Specs { err := spec.Parse() if err != nil { - userError.LogErrorf("failed parsing action trigger with %s", - userError.NewUserError(err, + userError.LogErrorf( + "failed parsing action trigger with %s", + userError.NewUserError( + err, commands.Colorizer.Sprintf( "Failed parsing action trigger for %s", - commands.Colorizer.Bold(commands.Colorizer.Red(name))), + commands.Colorizer.Bold(commands.Colorizer.Red(name)), + ), ), ) os.Exit(1) @@ -216,8 +237,11 @@ func publish( logrus.Info("\nPublishing and deploying actions:") } for actionName := range actions.Specs { - logrus.Info(commands.Colorizer.Sprintf( - "- %s", commands.Colorizer.Bold(commands.Colorizer.Green(actionName)))) + logrus.Info( + commands.Colorizer.Sprintf( + "- %s", commands.Colorizer.Bold(commands.Colorizer.Green(actionName)), + ), + ) } logicZip, logicHash := util.MustZipAndHashDir(outDir, srcPathInZip, zipLimitBytes) @@ -226,7 +250,9 @@ func publish( } dependenciesDir := filepath.Join(actions.Sources, typescript.NodeModulesDir) - dependenciesZip, dependenciesHash := util.ZipAndHashDir(dependenciesDir, nodeModulesPathInZip, zipLimitBytes) + dependenciesZip, dependenciesHash := util.ZipAndHashDir( + dependenciesDir, nodeModulesPathInZip, zipLimitBytes, + ) if dependenciesExist { dependenciesZip = nil } @@ -248,11 +274,14 @@ func publish( s.Stop() if err != nil { - userError.LogErrorf("publish request failed", + userError.LogErrorf( + "publish request failed", userError.NewUserError( err, - commands.Colorizer.Sprintf("Publish request failed: %s", - commands.Colorizer.Red(err.Error())), + commands.Colorizer.Sprintf( + "Publish request failed: %s", + commands.Colorizer.Red(err.Error()), + ), ), ) os.Exit(1) @@ -264,11 +293,15 @@ func publish( logrus.Info("\nPublished and deployed actions:") } for key, version := range response.Actions { - logrus.Info(commands.Colorizer.Sprintf("- %s (actionId = %s, versionId = %s) %s", - commands.Colorizer.Bold(commands.Colorizer.Green(key)), - version.ActionId, - version.Id, - fmt.Sprintf(ActionUrlPattern, projectSlug, version.ActionId))) + logrus.Info( + commands.Colorizer.Sprintf( + "- %s (actionId = %s, versionId = %s) %s", + commands.Colorizer.Bold(commands.Colorizer.Green(key)), + version.ActionId, + version.Id, + fmt.Sprintf(ActionUrlPattern, projectSlug, version.ActionId), + ), + ) } } @@ -286,8 +319,10 @@ func mustBuildProject(sourcesDir string, tsconfig *typescript.TsConfig) { err := cmd.Run() if err != nil { - userError.LogErrorf("failed to run build typescript: %s", - userError.NewUserError(err, + userError.LogErrorf( + "failed to run build typescript: %s", + userError.NewUserError( + err, commands.Colorizer.Sprintf( "Failed to run: %s.", commands.Colorizer.Bold( @@ -323,7 +358,8 @@ func mustValidateAndGetSources( func mustGetSource(sourcesDir string, locator string) string { internalLocator, err := actionsModel.NewInternalLocator(locator) if err != nil { - userError.LogErrorf("invalid locator: %s", + userError.LogErrorf( + "invalid locator: %s", userError.NewUserError( err, commands.Colorizer.Sprintf( @@ -349,11 +385,13 @@ func mustGetSource(sourcesDir string, locator string) string { } } if !exists { - logrus.Error(commands.Colorizer.Sprintf( - "Invalid locator %s (file %s not found).", - commands.Colorizer.Bold(commands.Colorizer.Red(locator)), - commands.Colorizer.Bold(commands.Colorizer.Red(filePath)), - )) + logrus.Error( + commands.Colorizer.Sprintf( + "Invalid locator %s (file %s not found).", + commands.Colorizer.Bold(commands.Colorizer.Red(locator)), + commands.Colorizer.Bold(commands.Colorizer.Red(filePath)), + ), + ) os.Exit(1) } @@ -384,11 +422,14 @@ func mustValidate( response, err := r.Actions.Validate(request, projectSlug) if err != nil { - userError.LogErrorf("validate request failed", + userError.LogErrorf( + "validate request failed", userError.NewUserError( err, - commands.Colorizer.Sprintf("Validate request failed: %s", - commands.Colorizer.Red(err.Error())), + commands.Colorizer.Sprintf( + "Validate request failed: %s", + commands.Colorizer.Red(err.Error()), + ), ), ) os.Exit(1) @@ -397,7 +438,9 @@ func mustValidate( if len(response.Errors) > 0 { for name, errs := range response.Errors { logrus.Info( - commands.Colorizer.Sprintf("Validation for %s failed with errors:", commands.Colorizer.Yellow(name)), + commands.Colorizer.Sprintf( + "Validation for %s failed with errors:", commands.Colorizer.Yellow(name), + ), ) for _, e := range errs { logrus.Info(commands.Colorizer.Sprintf("%s: %s", commands.Colorizer.Red(e.Name), e.Message)) @@ -411,10 +454,12 @@ func mustValidate( func mustValidateTsconfig(tsconfig *typescript.TsConfig) { if tsconfig.CompilerOptions.OutDir == nil { - logrus.Error(commands.Colorizer.Sprintf( - "Invalid tsconfig - %s must be set.", - commands.Colorizer.Bold(commands.Colorizer.Red("compilerOptions.outDir")), - )) + logrus.Error( + commands.Colorizer.Sprintf( + "Invalid tsconfig - %s must be set.", + commands.Colorizer.Bold(commands.Colorizer.Red("compilerOptions.outDir")), + ), + ) os.Exit(1) } } @@ -424,7 +469,8 @@ func anyFunctionTsFileExists(actions *actionsModel.ProjectActions) (bool, string locator := spec.Function internalLocator, err := actionsModel.NewInternalLocator(locator) if err != nil { - userError.LogErrorf("invalid locator: %s", + userError.LogErrorf( + "invalid locator: %s", userError.NewUserError( err, commands.Colorizer.Sprintf( @@ -450,12 +496,16 @@ func mustExistCompiledFiles(outDir string, actions *actionsModel.ProjectActions) for _, spec := range actions.Specs { internalLocator, err := actionsModel.NewInternalLocator(spec.Function) if err != nil { - userError.LogErrorf("invalid locator: %s", - userError.NewUserError(err, + userError.LogErrorf( + "invalid locator: %s", + userError.NewUserError( + err, commands.Colorizer.Sprintf( "Invalid locator format %s.", commands.Colorizer.Bold(commands.Colorizer.Red(spec.Function)), - ))) + ), + ), + ) os.Exit(1) } @@ -469,12 +519,14 @@ func mustExistCompiledFiles(outDir string, actions *actionsModel.ProjectActions) } } if len(missingFilePaths) > 0 { - logrus.Errorf("Unable to resolve path for some of the compiled files: %s\n"+ - "Make sure all imported files are contained in the configured action sources directory (%s).\n"+ - "If the problem persists, please run this command with the %s flag and send logs to our customer support.", + logrus.Errorf( + "Unable to resolve path for some of the compiled files: %s\n"+ + "Make sure all imported files are contained in the configured action sources directory (%s).\n"+ + "If the problem persists, please run this command with the %s flag and send logs to our customer support.", commands.Colorizer.Bold(commands.Colorizer.Red(strings.Join(missingFilePaths, ", "))), commands.Colorizer.Bold(actions.Sources), - commands.Colorizer.Bold(commands.Colorizer.Red("--debug"))) + commands.Colorizer.Bold(commands.Colorizer.Red("--debug")), + ) os.Exit(1) } } @@ -482,11 +534,13 @@ func mustExistCompiledFiles(outDir string, actions *actionsModel.ProjectActions) func printPackageValidationErrors(validationErrors []*packagejson.ValidationError) { logrus.Error("The following packages have invalid versions:") for _, e := range validationErrors { - logrus.Error(commands.Colorizer.Sprintf( - " %s\n\tFound: %s\n\tRequired: %s", - commands.Colorizer.Bold(commands.Colorizer.Bold(e.Name)), - commands.Colorizer.Bold(commands.Colorizer.Red(e.PackageJsonVersion)), - commands.Colorizer.Bold(commands.Colorizer.Red(e.Constraint)), - )) + logrus.Error( + commands.Colorizer.Sprintf( + " %s\n\tFound: %s\n\tRequired: %s", + commands.Colorizer.Bold(commands.Colorizer.Bold(e.Name)), + commands.Colorizer.Bold(commands.Colorizer.Red(e.PackageJsonVersion)), + commands.Colorizer.Bold(commands.Colorizer.Red(e.Constraint)), + ), + ) } } diff --git a/model/actions/action.go b/model/actions/action.go index 49d0c6b..5896627 100644 --- a/model/actions/action.go +++ b/model/actions/action.go @@ -9,6 +9,11 @@ import ( "github.com/tenderly/tenderly-cli/rest/payloads/generated/actions" ) +const ( + sequentialExecutionType = "sequential" + parallelExecutionType = "parallel" +) + type Action struct { ID string `json:"id"` Name string `json:"name"` @@ -36,8 +41,9 @@ func (s *ProjectActions) ToRequest(sources map[string]string) map[string]actions Runtime: actions.New_Runtime(actions.Runtime_Value(s.Runtime)), Function: actions.Function(action.Function), // Field will be set when we access it - TriggerType: action.TriggerParsed.ToRequestType(), - Trigger: action.TriggerParsed.ToRequest(), + TriggerType: action.TriggerParsed.ToRequestType(), + Trigger: action.TriggerParsed.ToRequest(), + InvocationType: invocationTypeFromExecution(action.ExecutionType), } response[name] = spec } @@ -50,6 +56,7 @@ type ActionSpec struct { // Parsing and validation of trigger happens later, and Trigger field is set Trigger TriggerUnparsed `json:"trigger" yaml:"trigger"` TriggerParsed *Trigger `json:"-" yaml:"-"` + ExecutionType string `json:"execution_type" yaml:"execution_type"` } type TriggerUnparsed struct { @@ -105,3 +112,14 @@ func IsRuntimeSupported(runtime string) bool { return false } + +func invocationTypeFromExecution(executionType string) string { + switch executionType { + case sequentialExecutionType: + return "SYNC" + case parallelExecutionType: + return "ASYNC" + default: + return "" + } +} diff --git a/rest/payloads/generated/actions/structs.conjure.go b/rest/payloads/generated/actions/structs.conjure.go index 9f5ec2a..ada0ad8 100644 --- a/rest/payloads/generated/actions/structs.conjure.go +++ b/rest/payloads/generated/actions/structs.conjure.go @@ -65,11 +65,12 @@ type ActionSpec struct { Name string `json:"name"` Description *string `json:"description"` // Source code, usually just top level file when function is defined. - Source *string `json:"source" conjure-docs:"Source code, usually just top level file when function is defined."` - Runtime Runtime `json:"runtime"` - Function Function `json:"function"` - TriggerType TriggerType `json:"triggerType"` - Trigger *Trigger `json:"trigger"` + Source *string `json:"source" conjure-docs:"Source code, usually just top level file when function is defined."` + Runtime Runtime `json:"runtime"` + Function Function `json:"function"` + TriggerType TriggerType `json:"triggerType"` + Trigger *Trigger `json:"trigger"` + InvocationType string `json:"invocationType"` } func (o ActionSpec) MarshalYAML() (interface{}, error) { From 4c4161638cff5210d6cb1e8afd717a87b2859b49 Mon Sep 17 00:00:00 2001 From: Gostuski Date: Wed, 31 May 2023 15:39:13 +0200 Subject: [PATCH 2/3] Add check for execution_type fields while building and publishing actions --- commands/actions/publish.go | 21 +++++++++++++++++++-- model/actions/action.go | 8 ++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/commands/actions/publish.go b/commands/actions/publish.go index 6cc63cb..2c825e6 100644 --- a/commands/actions/publish.go +++ b/commands/actions/publish.go @@ -110,7 +110,7 @@ func buildFunc(cmd *cobra.Command, args []string) { ) os.Exit(1) } - mustParseAndValidateTriggers(actions) + mustParseAndValidateActions(actions) tsConfigExists := util.TsConfigExists(actions.Sources) tsFileExists, tsFile := anyFunctionTsFileExists(actions) @@ -175,8 +175,25 @@ func buildFunc(cmd *cobra.Command, args []string) { logrus.Info(commands.Colorizer.Green("\nBuild completed.")) } -func mustParseAndValidateTriggers(projectActions *actionsModel.ProjectActions) { +func mustParseAndValidateActions(projectActions *actionsModel.ProjectActions) { for name, spec := range projectActions.Specs { + if spec.ExecutionType != actionsModel.ParallelExecutionType && + spec.ExecutionType != actionsModel.SequentialExecutionType { + userError.LogErrorf( + "validation of action failed", + userError.NewUserError( + nil, + commands.Colorizer.Sprintf( + "Invalid execution type %s for action %s. Supported values: {%s, %s}", + commands.Colorizer.Bold(commands.Colorizer.Red(spec.ExecutionType)), + commands.Colorizer.Bold(commands.Colorizer.Blue(name)), + commands.Colorizer.Bold(commands.Colorizer.Green(actionsModel.SequentialExecutionType)), + commands.Colorizer.Bold(commands.Colorizer.Green(actionsModel.ParallelExecutionType)), + ), + ), + ) + os.Exit(1) + } err := spec.Parse() if err != nil { userError.LogErrorf( diff --git a/model/actions/action.go b/model/actions/action.go index 5896627..cc17be5 100644 --- a/model/actions/action.go +++ b/model/actions/action.go @@ -10,8 +10,8 @@ import ( ) const ( - sequentialExecutionType = "sequential" - parallelExecutionType = "parallel" + SequentialExecutionType = "sequential" + ParallelExecutionType = "parallel" ) type Action struct { @@ -115,9 +115,9 @@ func IsRuntimeSupported(runtime string) bool { func invocationTypeFromExecution(executionType string) string { switch executionType { - case sequentialExecutionType: + case SequentialExecutionType: return "SYNC" - case parallelExecutionType: + case ParallelExecutionType: return "ASYNC" default: return "" From 6e7d1ab5f834c3e9fa13369ede22b9ca877cee63 Mon Sep 17 00:00:00 2001 From: Gostuski Date: Wed, 31 May 2023 15:51:10 +0200 Subject: [PATCH 3/3] Add check for empty execution_type --- commands/actions/publish.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/commands/actions/publish.go b/commands/actions/publish.go index 2c825e6..4242a54 100644 --- a/commands/actions/publish.go +++ b/commands/actions/publish.go @@ -178,7 +178,8 @@ func buildFunc(cmd *cobra.Command, args []string) { func mustParseAndValidateActions(projectActions *actionsModel.ProjectActions) { for name, spec := range projectActions.Specs { if spec.ExecutionType != actionsModel.ParallelExecutionType && - spec.ExecutionType != actionsModel.SequentialExecutionType { + spec.ExecutionType != actionsModel.SequentialExecutionType && + spec.ExecutionType != "" { userError.LogErrorf( "validation of action failed", userError.NewUserError(