Skip to content

Commit 783db56

Browse files
authored
feat: error if the runtime is not found with a missing hook (#167)
1 parent bed795a commit 783db56

File tree

5 files changed

+60
-24
lines changed

5 files changed

+60
-24
lines changed

cmd/root.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -376,20 +376,23 @@ func ExecuteContext(ctx context.Context, rootCmd *cobra.Command, clients *shared
376376

377377
// The cleanup() method in the root command will invoke via `defer` from within Execute.
378378
if err := rootCmd.ExecuteContext(ctx); err != nil {
379-
errMsg := err.Error()
380-
clients.EventTracker.SetErrorMessage(errMsg)
381-
if slackErr, ok := err.(*slackerror.Error); ok {
382-
clients.EventTracker.SetErrorCode(slackErr.Code)
383-
}
384379
if slackerror.Is(err, slackerror.ErrProcessInterrupted) {
385380
clients.IO.SetExitCode(iostreams.ExitCancel)
386-
clients.IO.PrintDebug(ctx, errMsg)
381+
clients.IO.PrintDebug(ctx, err.Error())
387382
} else {
383+
if slackerror.Is(err, slackerror.ErrSDKHookNotFound) && clients.SDKConfig.Runtime == "" {
384+
err = slackerror.New(slackerror.ErrRuntimeNotFound).
385+
WithRootCause(slackerror.ToSlackError(err).WithRemediation(""))
386+
}
388387
switch clients.IO.GetExitCode() {
389388
case iostreams.ExitOK:
390389
clients.IO.SetExitCode(iostreams.ExitError)
391390
}
392-
clients.IO.PrintError(ctx, errMsg)
391+
clients.IO.PrintError(ctx, err.Error())
392+
}
393+
clients.EventTracker.SetErrorMessage(err.Error())
394+
if slackErr, ok := err.(*slackerror.Error); ok {
395+
clients.EventTracker.SetErrorCode(slackErr.Code)
393396
}
394397
defer clients.Os.Exit(int(clients.IO.GetExitCode()))
395398
completedChan <- true

cmd/root_test.go

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/slackapi/slack-cli/internal/iostreams"
2525
"github.com/slackapi/slack-cli/internal/shared"
2626
"github.com/slackapi/slack-cli/internal/slackcontext"
27+
"github.com/slackapi/slack-cli/internal/slackerror"
2728
"github.com/slackapi/slack-cli/test/testutil"
2829
"github.com/spf13/cobra"
2930
"github.com/stretchr/testify/assert"
@@ -81,21 +82,43 @@ func TestRootCommand(t *testing.T) {
8182

8283
func TestExecuteContext(t *testing.T) {
8384
tests := map[string]struct {
84-
expectedErr error
85-
expectedExitCode iostreams.ExitCode
86-
expectedOutputs []string
85+
mockErr error
86+
mockRuntime string
87+
expectedExitCode iostreams.ExitCode
88+
expectedOutputs []string
89+
unexpectedOutputs []string
8790
}{
8891
"Command successfully executes": {
89-
expectedErr: nil,
92+
mockErr: nil,
9093
expectedExitCode: iostreams.ExitOK,
9194
},
9295
"Command fails execution and returns an error": {
93-
expectedErr: fmt.Errorf("command failed"),
96+
mockErr: fmt.Errorf("command failed"),
9497
expectedExitCode: iostreams.ExitError,
9598
expectedOutputs: []string{
9699
"command failed",
97100
},
98101
},
102+
"Command fails execution with a missing hook and missing runtime": {
103+
mockErr: slackerror.New(slackerror.ErrSDKHookNotFound),
104+
expectedExitCode: iostreams.ExitError,
105+
expectedOutputs: []string{
106+
slackerror.New(slackerror.ErrRuntimeNotFound).
107+
WithRootCause(slackerror.New(slackerror.ErrSDKHookNotFound).WithRemediation("")).
108+
Error(),
109+
},
110+
},
111+
"Command fails execution with a missing hook and existing runtime": {
112+
mockErr: slackerror.New(slackerror.ErrSDKHookNotFound),
113+
mockRuntime: "sh",
114+
expectedExitCode: iostreams.ExitError,
115+
expectedOutputs: []string{
116+
slackerror.New(slackerror.ErrSDKHookNotFound).Error(),
117+
},
118+
unexpectedOutputs: []string{
119+
slackerror.ErrRuntimeNotFound,
120+
},
121+
},
99122
}
100123
for name, tt := range tests {
101124
t.Run(name, func(t *testing.T) {
@@ -105,15 +128,18 @@ func TestExecuteContext(t *testing.T) {
105128
clientsMock := shared.NewClientsMock()
106129
clientsMock.AddDefaultMocks()
107130
clientsMock.EventTracker.On("FlushToLogstash", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
108-
clients := shared.NewClientFactory(clientsMock.MockClientFactory())
131+
clients := shared.NewClientFactory(clientsMock.MockClientFactory(), func(clients *shared.ClientFactory) {
132+
clients.SDKConfig.Runtime = tt.mockRuntime
133+
})
109134

110135
// Mock command
111136
cmd := &cobra.Command{
112137
Use: "mock [flags]",
113138
RunE: func(cmd *cobra.Command, args []string) error {
114-
return tt.expectedErr
139+
return tt.mockErr
115140
},
116141
}
142+
testutil.MockCmdIO(clientsMock.IO, cmd)
117143

118144
// Execute the command
119145
ExecuteContext(ctx, cmd, clients)
@@ -126,6 +152,9 @@ func TestExecuteContext(t *testing.T) {
126152
for _, expectedOutput := range tt.expectedOutputs {
127153
require.Contains(t, output, expectedOutput)
128154
}
155+
for _, unexpectedOutputs := range tt.unexpectedOutputs {
156+
require.NotContains(t, output, unexpectedOutputs)
157+
}
129158
})
130159
}
131160
}

cmd/triggers/create.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"encoding/json"
2020
"fmt"
21+
"path/filepath"
2122
"strings"
2223

2324
"github.com/opentracing/opentracing-go"
@@ -306,7 +307,9 @@ func triggerRequestFromFlags(flags createCmdFlags, isDev bool) api.TriggerReques
306307

307308
func triggerRequestViaHook(ctx context.Context, clients *shared.ClientFactory, path string, isDev bool) (api.TriggerRequest, error) {
308309
if !clients.SDKConfig.Hooks.GetTrigger.IsAvailable() {
309-
return api.TriggerRequest{}, slackerror.New(slackerror.ErrSDKHookGetTriggerNotFound)
310+
return api.TriggerRequest{}, slackerror.New(slackerror.ErrSDKHookNotFound).
311+
WithMessage("The `get-trigger` hook script in `%s` was not found", filepath.Join(".slack", "hooks.json")).
312+
WithRemediation("Try defining your trigger by specifying a json file instead.")
310313
}
311314

312315
hookExecOpts := hooks.HookExecOpts{

cmd/triggers/create_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/slackapi/slack-cli/internal/shared"
2828
"github.com/slackapi/slack-cli/internal/shared/types"
2929
"github.com/slackapi/slack-cli/internal/slackcontext"
30+
"github.com/slackapi/slack-cli/internal/slackerror"
3031
"github.com/slackapi/slack-cli/test/testutil"
3132
"github.com/spf13/afero"
3233
"github.com/spf13/cobra"
@@ -293,7 +294,7 @@ func TestTriggersCreateCommand(t *testing.T) {
293294
},
294295
"--trigger-def, not json, `get-trigger` hook missing": {
295296
CmdArgs: []string{"--trigger-def", "triggers/shortcut.ts"},
296-
ExpectedErrorStrings: []string{"sdk_hook_get_trigger_not_found"},
297+
ExpectedErrorStrings: []string{slackerror.ErrSDKHookNotFound},
297298
Setup: func(t *testing.T, ctx context.Context, clientsMock *shared.ClientsMock, clients *shared.ClientFactory) {
298299
appSelectTeardown = setupMockCreateAppSelection(installedProdApp)
299300
// TODO: testing chicken and egg: we need the default mocks in place before we can use any of the `clients` methods

internal/slackerror/errors.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,11 @@ const (
210210
ErrRequestIDOrAppIDIsRequired = "request_id_or_app_id_is_required"
211211
ErrRatelimited = "ratelimited"
212212
ErrRestrictedPlanLevel = "restricted_plan_level"
213+
ErrRuntimeNotFound = "runtime_not_found"
213214
ErrRuntimeNotSupported = "runtime_not_supported"
214215
ErrSDKConfigLoad = "sdk_config_load_error"
215216
ErrSDKHookInvocationFailed = "sdk_hook_invocation_failed"
216217
ErrSDKHookNotFound = "sdk_hook_not_found"
217-
ErrSDKHookGetTriggerNotFound = "sdk_hook_get_trigger_not_found"
218218
ErrSampleCreate = "sample_create_error"
219219
ErrServiceLimitsExceeded = "service_limits_exceeded"
220220
ErrSharedChannelDenied = "shared_channel_denied"
@@ -1291,9 +1291,15 @@ Otherwise start your app for local development with: %s`,
12911291
Message: "Your Slack plan does not have access to the requested feature",
12921292
},
12931293

1294+
ErrRuntimeNotFound: {
1295+
Code: ErrRuntimeNotFound,
1296+
Message: "The hook runtime executable was not found",
1297+
Remediation: "Make sure the required runtime has been installed to run hook scripts.",
1298+
},
1299+
12941300
ErrRuntimeNotSupported: {
12951301
Code: ErrRuntimeNotSupported,
1296-
Message: "The SDK language's executable (deno, node, python, etc) was not found to be installed on the system",
1302+
Message: "The SDK runtime is not supported by the CLI",
12971303
},
12981304

12991305
ErrSampleCreate: {
@@ -1340,12 +1346,6 @@ Otherwise start your app for local development with: %s`,
13401346
}, "\n"),
13411347
},
13421348

1343-
ErrSDKHookGetTriggerNotFound: {
1344-
Code: ErrSDKHookGetTriggerNotFound,
1345-
Message: fmt.Sprintf("The `get-trigger` hook script in `%s` was not found", filepath.Join(".slack", "hooks.json")),
1346-
Remediation: `Try defining your trigger by specifying a json file instead.`,
1347-
},
1348-
13491349
ErrSlackAuth: {
13501350
Code: ErrSlackAuth,
13511351
Message: "You are not logged into a team or have not installed an app",

0 commit comments

Comments
 (0)