From 71fdf86cc8dd021ef7c9daf6ee926f0f2b746635 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Thu, 5 Feb 2026 11:53:08 -0500 Subject: [PATCH 1/8] feat(deploy): improve error message when no deploy script found --- cmd/platform/deploy.go | 12 ++++-------- cmd/platform/deploy_test.go | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/cmd/platform/deploy.go b/cmd/platform/deploy.go index ec8fb97f..aee0d67e 100644 --- a/cmd/platform/deploy.go +++ b/cmd/platform/deploy.go @@ -316,16 +316,12 @@ func printDeployHostingCompletion(clients *shared.ClientFactory, cmd *cobra.Comm func errorMissingDeployHook(clients *shared.ClientFactory) error { if !clients.SDKConfig.Hooks.Deploy.IsAvailable() { return slackerror.New(slackerror.ErrSDKHookNotFound). - WithMessage("Missing the `deploy` hook from the `%s` file", config.GetProjectHooksJSONFilePath()). + WithMessage("No deploy script found"). WithRemediation("%s", strings.Join([]string{ - "Provide a command or script to run with the deploy command by adding a new hook.", + "To start a local development server, use:", + fmt.Sprintf(" %s", style.Commandf("run", false)), "", - fmt.Sprintf("Example `%s` `deploy` hook:", config.GetProjectHooksJSONFilePath()), - "{", - ` "hooks": {`, - ` "deploy": "./deploy.sh"`, - " }", - "}", + "For deployment options, see: https://docs.slack.dev/deployment", }, "\n")) } return nil diff --git a/cmd/platform/deploy_test.go b/cmd/platform/deploy_test.go index 5dc5c71a..f4d0a5b6 100644 --- a/cmd/platform/deploy_test.go +++ b/cmd/platform/deploy_test.go @@ -195,6 +195,23 @@ func TestDeployCommand_HasValidDeploymentMethod(t *testing.T) { } } +func TestDeployCommand_ErrorMissingDeployHook(t *testing.T) { + clientsMock := shared.NewClientsMock() + clients := shared.NewClientFactory(clientsMock.MockClientFactory(), func(clients *shared.ClientFactory) { + clients.SDKConfig = hooks.NewSDKConfigMock() + clients.SDKConfig.Hooks.Deploy.Command = "" + }) + + err := errorMissingDeployHook(clients) + require.Error(t, err) + slackErr := slackerror.ToSlackError(err) + assert.Equal(t, slackerror.ErrSDKHookNotFound, slackErr.Code) + assert.Contains(t, slackErr.Message, "No deploy script found") + assert.Contains(t, slackErr.Remediation, "run") + assert.Contains(t, slackErr.Remediation, "local development server") + assert.Contains(t, slackErr.Remediation, "https://docs.slack.dev/deployment") +} + func TestDeployCommand_DeployHook(t *testing.T) { tests := map[string]struct { command string From d3b725666af9d9fc2336f35df6578f5aacb0515c Mon Sep 17 00:00:00 2001 From: Maria Alejandra <104795114+srtaalej@users.noreply.github.com> Date: Thu, 5 Feb 2026 15:15:13 -0500 Subject: [PATCH 2/8] Update cmd/platform/deploy.go Co-authored-by: Eden Zimbelman --- cmd/platform/deploy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/platform/deploy.go b/cmd/platform/deploy.go index aee0d67e..86402734 100644 --- a/cmd/platform/deploy.go +++ b/cmd/platform/deploy.go @@ -321,7 +321,7 @@ func errorMissingDeployHook(clients *shared.ClientFactory) error { "To start a local development server, use:", fmt.Sprintf(" %s", style.Commandf("run", false)), "", - "For deployment options, see: https://docs.slack.dev/deployment", + "For deployment options, see: https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy", }, "\n")) } return nil From 1f7430a6ac23424909f75e150f42a14adf56fdc0 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Thu, 5 Feb 2026 15:56:36 -0500 Subject: [PATCH 3/8] format deploy.go --- cmd/platform/deploy.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/platform/deploy.go b/cmd/platform/deploy.go index 86402734..7335302f 100644 --- a/cmd/platform/deploy.go +++ b/cmd/platform/deploy.go @@ -318,8 +318,7 @@ func errorMissingDeployHook(clients *shared.ClientFactory) error { return slackerror.New(slackerror.ErrSDKHookNotFound). WithMessage("No deploy script found"). WithRemediation("%s", strings.Join([]string{ - "To start a local development server, use:", - fmt.Sprintf(" %s", style.Commandf("run", false)), + "To start a local development server, use:", fmt.Sprintf(" %s", style.Commandf("run", false)), "", "For deployment options, see: https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy", }, "\n")) From 40b65e34456e8ac7c60b29ce19a5eecfe958d8d0 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Thu, 5 Feb 2026 16:18:29 -0500 Subject: [PATCH 4/8] test: update test to expect correct docs url --- cmd/platform/deploy_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/platform/deploy_test.go b/cmd/platform/deploy_test.go index f4d0a5b6..ac59c5d4 100644 --- a/cmd/platform/deploy_test.go +++ b/cmd/platform/deploy_test.go @@ -209,7 +209,7 @@ func TestDeployCommand_ErrorMissingDeployHook(t *testing.T) { assert.Contains(t, slackErr.Message, "No deploy script found") assert.Contains(t, slackErr.Remediation, "run") assert.Contains(t, slackErr.Remediation, "local development server") - assert.Contains(t, slackErr.Remediation, "https://docs.slack.dev/deployment") + assert.Contains(t, slackErr.Remediation, "https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy") } func TestDeployCommand_DeployHook(t *testing.T) { From 908477064cd82872ff241084fdace5c7dd19e750 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Fri, 6 Feb 2026 12:14:12 -0500 Subject: [PATCH 5/8] adjust print format to highlight cmd --- cmd/platform/deploy.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/platform/deploy.go b/cmd/platform/deploy.go index 7335302f..f11d85c3 100644 --- a/cmd/platform/deploy.go +++ b/cmd/platform/deploy.go @@ -318,9 +318,11 @@ func errorMissingDeployHook(clients *shared.ClientFactory) error { return slackerror.New(slackerror.ErrSDKHookNotFound). WithMessage("No deploy script found"). WithRemediation("%s", strings.Join([]string{ - "To start a local development server, use:", fmt.Sprintf(" %s", style.Commandf("run", false)), + "For deployment options, see:", + " https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy", "", - "For deployment options, see: https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy", + "To start a local development server, use:", + fmt.Sprintf(" %s", style.Commandf("run", false)), }, "\n")) } return nil From e2e46ecadc26f1fbb6d7978ff03d93179e9a4544 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Fri, 6 Feb 2026 12:29:29 -0500 Subject: [PATCH 6/8] tests: add errormissingdeployhook test to table test --- cmd/platform/deploy_test.go | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/cmd/platform/deploy_test.go b/cmd/platform/deploy_test.go index ac59c5d4..96f6584e 100644 --- a/cmd/platform/deploy_test.go +++ b/cmd/platform/deploy_test.go @@ -214,11 +214,20 @@ func TestDeployCommand_ErrorMissingDeployHook(t *testing.T) { func TestDeployCommand_DeployHook(t *testing.T) { tests := map[string]struct { - command string - expectedStderr []string - expectedStdout string - expectedError error + command string + emptyDeployHook bool + expectedStderr []string + expectedStdout string + expectedError error + expectedMessage string + expectedRemediation string }{ + "returns error when deploy hook is missing": { + emptyDeployHook: true, + expectedError: slackerror.New(slackerror.ErrSDKHookNotFound), + expectedMessage: "No deploy script found", + expectedRemediation: "run", + }, "fails to execute an unknown script path": { command: "./deployer.sh", expectedError: slackerror.New(slackerror.ErrSDKHookInvocationFailed), @@ -274,7 +283,11 @@ func TestDeployCommand_DeployHook(t *testing.T) { clientsMock.AddDefaultMocks() sdkConfigMock := hooks.NewSDKConfigMock() sdkConfigMock.Config.SupportedProtocols = []hooks.Protocol{hooks.HookProtocolDefault} - sdkConfigMock.Hooks.Deploy = hooks.HookScript{Name: "Deploy", Command: tc.command} + if tc.emptyDeployHook { + sdkConfigMock.Hooks.Deploy = hooks.HookScript{} + } else { + sdkConfigMock.Hooks.Deploy = hooks.HookScript{Name: "Deploy", Command: tc.command} + } stdoutLogger := log.Logger{} stdoutBuffer := bytes.Buffer{} @@ -298,6 +311,15 @@ func TestDeployCommand_DeployHook(t *testing.T) { cmd.PreRunE = func(cmd *cobra.Command, args []string) error { return nil } testutil.MockCmdIO(clients.IO, cmd) + if tc.emptyDeployHook { + err := errorMissingDeployHook(clients) + require.Error(t, err) + slackErr := slackerror.ToSlackError(err) + assert.Equal(t, tc.expectedError.(*slackerror.Error).Code, slackErr.Code) + assert.Contains(t, slackErr.Message, tc.expectedMessage) + assert.Contains(t, slackErr.Remediation, tc.expectedRemediation) + return + } err := cmd.ExecuteContext(ctx) assert.Contains(t, stdoutBuffer.String(), tc.command) if tc.expectedError != nil { From c93ada783a9ed8d52099cec521315613aa0ca998 Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Mon, 9 Feb 2026 11:30:04 -0500 Subject: [PATCH 7/8] tests: add test case to deploy table test --- cmd/platform/deploy_test.go | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/cmd/platform/deploy_test.go b/cmd/platform/deploy_test.go index 96f6584e..6e9e63c7 100644 --- a/cmd/platform/deploy_test.go +++ b/cmd/platform/deploy_test.go @@ -195,23 +195,6 @@ func TestDeployCommand_HasValidDeploymentMethod(t *testing.T) { } } -func TestDeployCommand_ErrorMissingDeployHook(t *testing.T) { - clientsMock := shared.NewClientsMock() - clients := shared.NewClientFactory(clientsMock.MockClientFactory(), func(clients *shared.ClientFactory) { - clients.SDKConfig = hooks.NewSDKConfigMock() - clients.SDKConfig.Hooks.Deploy.Command = "" - }) - - err := errorMissingDeployHook(clients) - require.Error(t, err) - slackErr := slackerror.ToSlackError(err) - assert.Equal(t, slackerror.ErrSDKHookNotFound, slackErr.Code) - assert.Contains(t, slackErr.Message, "No deploy script found") - assert.Contains(t, slackErr.Remediation, "run") - assert.Contains(t, slackErr.Remediation, "local development server") - assert.Contains(t, slackErr.Remediation, "https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy") -} - func TestDeployCommand_DeployHook(t *testing.T) { tests := map[string]struct { command string @@ -228,6 +211,12 @@ func TestDeployCommand_DeployHook(t *testing.T) { expectedMessage: "No deploy script found", expectedRemediation: "run", }, + "returns error with docs URL in remediation when deploy hook is missing": { + emptyDeployHook: true, + expectedError: slackerror.New(slackerror.ErrSDKHookNotFound), + expectedMessage: "No deploy script found", + expectedRemediation: "https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy", + }, "fails to execute an unknown script path": { command: "./deployer.sh", expectedError: slackerror.New(slackerror.ErrSDKHookInvocationFailed), From a9c3e29d4ecd4f43e4fcdb7bd790eb2f37d20e9f Mon Sep 17 00:00:00 2001 From: Ale Mercado Date: Mon, 9 Feb 2026 16:05:48 -0500 Subject: [PATCH 8/8] tests: fix deploy table tests --- cmd/platform/deploy_test.go | 45 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/cmd/platform/deploy_test.go b/cmd/platform/deploy_test.go index 6e9e63c7..7a8d1cff 100644 --- a/cmd/platform/deploy_test.go +++ b/cmd/platform/deploy_test.go @@ -111,12 +111,14 @@ func TestDeployCommand(t *testing.T) { func TestDeployCommand_HasValidDeploymentMethod(t *testing.T) { tests := map[string]struct { - app types.App - manifest types.SlackYaml - manifestError error - manifestSource config.ManifestSource - deployScript string - expectedError error + app types.App + manifest types.SlackYaml + manifestError error + manifestSource config.ManifestSource + deployScript string + expectedError error + expectedMessage string + expectedRemediation []string }{ "fails when no manifest exists": { manifestError: slackerror.New(slackerror.ErrInvalidManifest), @@ -142,8 +144,10 @@ func TestDeployCommand_HasValidDeploymentMethod(t *testing.T) { deployScript: "sleep 4", }, "fails if no deploy hook is provided": { - manifestSource: config.ManifestSourceLocal, - expectedError: slackerror.New(slackerror.ErrSDKHookNotFound), + manifestSource: config.ManifestSourceLocal, + expectedError: slackerror.New(slackerror.ErrSDKHookNotFound), + expectedMessage: "No deploy script found", + expectedRemediation: []string{"https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy", "run"}, }, "succeeds if the app exists and the manifest source is remote": { app: types.App{ @@ -183,11 +187,14 @@ func TestDeployCommand_HasValidDeploymentMethod(t *testing.T) { err := hasValidDeploymentMethod(ctx, clients, app, types.SlackAuth{}) if tc.expectedError != nil { require.Error(t, err) - assert.Equal( - t, - slackerror.ToSlackError(tc.expectedError).Code, - slackerror.ToSlackError(err).Code, - ) + slackErr := slackerror.ToSlackError(err) + assert.Equal(t, slackerror.ToSlackError(tc.expectedError).Code, slackErr.Code) + if tc.expectedMessage != "" { + assert.Contains(t, slackErr.Message, tc.expectedMessage) + } + for _, r := range tc.expectedRemediation { + assert.Contains(t, slackErr.Remediation, r) + } } else { require.NoError(t, err) } @@ -205,18 +212,6 @@ func TestDeployCommand_DeployHook(t *testing.T) { expectedMessage string expectedRemediation string }{ - "returns error when deploy hook is missing": { - emptyDeployHook: true, - expectedError: slackerror.New(slackerror.ErrSDKHookNotFound), - expectedMessage: "No deploy script found", - expectedRemediation: "run", - }, - "returns error with docs URL in remediation when deploy hook is missing": { - emptyDeployHook: true, - expectedError: slackerror.New(slackerror.ErrSDKHookNotFound), - expectedMessage: "No deploy script found", - expectedRemediation: "https://docs.slack.dev/tools/slack-cli/reference/hooks/#deploy", - }, "fails to execute an unknown script path": { command: "./deployer.sh", expectedError: slackerror.New(slackerror.ErrSDKHookInvocationFailed),