Skip to content

Commit b1699bb

Browse files
committed
Merge branch 'main' of https://github.com/slackapi/slack-cli into evegeris-sandbox-integration-create-delete
2 parents cea2bcd + 7b3e445 commit b1699bb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2352
-598
lines changed

cmd/app/add.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"github.com/slackapi/slack-cli/internal/app"
2121
"github.com/slackapi/slack-cli/internal/cmdutil"
2222
"github.com/slackapi/slack-cli/internal/config"
23-
"github.com/slackapi/slack-cli/internal/experiment"
2423
"github.com/slackapi/slack-cli/internal/pkg/apps"
2524
"github.com/slackapi/slack-cli/internal/prompts"
2625
"github.com/slackapi/slack-cli/internal/shared"
@@ -83,9 +82,6 @@ func preRunAddCommand(ctx context.Context, clients *shared.ClientFactory, cmd *c
8382
if err != nil {
8483
return err
8584
}
86-
if !clients.Config.WithExperimentOn(experiment.BoltFrameworks) {
87-
return nil
88-
}
8985
clients.Config.SetFlags(cmd)
9086
return nil
9187
}

cmd/app/add_test.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"github.com/slackapi/slack-cli/internal/cache"
2424
"github.com/slackapi/slack-cli/internal/cmdutil"
2525
"github.com/slackapi/slack-cli/internal/config"
26-
"github.com/slackapi/slack-cli/internal/experiment"
2726
"github.com/slackapi/slack-cli/internal/iostreams"
2827
"github.com/slackapi/slack-cli/internal/prompts"
2928
"github.com/slackapi/slack-cli/internal/shared"
@@ -85,25 +84,21 @@ func TestAppAddCommandPreRun(t *testing.T) {
8584
cf.SDKConfig.WorkingDirectory = "."
8685
},
8786
},
88-
"proceeds if manifest.source is local with the bolt experiment": {
87+
"proceeds if manifest.source is local": {
8988
ExpectedError: nil,
9089
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
9190
cf.SDKConfig.WorkingDirectory = "."
9291
cm.AddDefaultMocks()
93-
cm.Config.ExperimentsFlag = append(cm.Config.ExperimentsFlag, string(experiment.BoltFrameworks))
94-
cm.Config.LoadExperiments(ctx, cm.IO.PrintDebug)
9592
mockProjectConfig := config.NewProjectConfigMock()
9693
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
9794
cm.Config.ProjectConfig = mockProjectConfig
9895
},
9996
},
100-
"proceeds if manifest.source is remote with the bolt experiment": {
97+
"proceeds if manifest.source is remote": {
10198
ExpectedError: nil,
10299
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
103100
cf.SDKConfig.WorkingDirectory = "."
104101
cm.AddDefaultMocks()
105-
cm.Config.ExperimentsFlag = append(cm.Config.ExperimentsFlag, string(experiment.BoltFrameworks))
106-
cm.Config.LoadExperiments(ctx, cm.IO.PrintDebug)
107102
mockProjectConfig := config.NewProjectConfigMock()
108103
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceRemote, nil)
109104
cm.Config.ProjectConfig = mockProjectConfig
@@ -207,6 +202,7 @@ func TestAppAddCommand(t *testing.T) {
207202
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
208203
Return(nil)
209204
mockProjectConfig := config.NewProjectConfigMock()
205+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
210206
mockProjectConfig.On("Cache").Return(mockProjectCache)
211207
cm.Config.ProjectConfig = mockProjectConfig
212208
},
@@ -279,6 +275,7 @@ func TestAppAddCommand(t *testing.T) {
279275
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
280276
Return(nil)
281277
mockProjectConfig := config.NewProjectConfigMock()
278+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
282279
mockProjectConfig.On("Cache").Return(mockProjectCache)
283280
cm.Config.ProjectConfig = mockProjectConfig
284281
},
@@ -343,7 +340,7 @@ func TestAppAddCommand(t *testing.T) {
343340
nil,
344341
)
345342

346-
// Mock existing and updated cache
343+
// Mock existing and updated cache - hashes must match for update to proceed
347344
cm.API.On(
348345
"ExportAppManifest",
349346
mock.Anything,
@@ -357,10 +354,11 @@ func TestAppAddCommand(t *testing.T) {
357354
mockProjectCache.On("GetManifestHash", mock.Anything, mock.Anything).
358355
Return(cache.Hash("b4b4"), nil)
359356
mockProjectCache.On("NewManifestHash", mock.Anything, mock.Anything).
360-
Return(cache.Hash("xoxo"), nil)
357+
Return(cache.Hash("b4b4"), nil) // matching hash allows update to proceed
361358
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
362359
Return(nil)
363360
mockProjectConfig := config.NewProjectConfigMock()
361+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
364362
mockProjectConfig.On("Cache").Return(mockProjectCache)
365363
cm.Config.ProjectConfig = mockProjectConfig
366364
},
@@ -428,6 +426,7 @@ func TestAppAddCommand(t *testing.T) {
428426
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
429427
Return(nil)
430428
mockProjectConfig := config.NewProjectConfigMock()
429+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
431430
mockProjectConfig.On("Cache").Return(mockProjectCache)
432431
cm.Config.ProjectConfig = mockProjectConfig
433432
},
@@ -515,6 +514,7 @@ func TestAppAddCommand(t *testing.T) {
515514
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
516515
Return(nil)
517516
mockProjectConfig := config.NewProjectConfigMock()
517+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
518518
mockProjectConfig.On("Cache").Return(mockProjectCache)
519519
cm.Config.ProjectConfig = mockProjectConfig
520520
},
@@ -599,6 +599,7 @@ func TestAppAddCommand(t *testing.T) {
599599
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
600600
Return(nil)
601601
mockProjectConfig := config.NewProjectConfigMock()
602+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
602603
mockProjectConfig.On("Cache").Return(mockProjectCache)
603604
cm.Config.ProjectConfig = mockProjectConfig
604605
},
@@ -685,6 +686,7 @@ func TestAppAddCommand(t *testing.T) {
685686
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
686687
Return(nil)
687688
mockProjectConfig := config.NewProjectConfigMock()
689+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
688690
mockProjectConfig.On("Cache").Return(mockProjectCache)
689691
cm.Config.ProjectConfig = mockProjectConfig
690692
},
@@ -760,6 +762,7 @@ func TestAppAddCommand(t *testing.T) {
760762
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
761763
Return(nil)
762764
mockProjectConfig := config.NewProjectConfigMock()
765+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
763766
mockProjectConfig.On("Cache").Return(mockProjectCache)
764767
cm.Config.ProjectConfig = mockProjectConfig
765768
},
@@ -816,6 +819,7 @@ func TestAppAddCommand(t *testing.T) {
816819
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
817820
Return(nil)
818821
mockProjectConfig := config.NewProjectConfigMock()
822+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
819823
mockProjectConfig.On("Cache").Return(mockProjectCache)
820824
cm.Config.ProjectConfig = mockProjectConfig
821825
},
@@ -872,6 +876,7 @@ func TestAppAddCommand(t *testing.T) {
872876
mockProjectCache.On("SetManifestHash", mock.Anything, mock.Anything, mock.Anything).
873877
Return(nil)
874878
mockProjectConfig := config.NewProjectConfigMock()
879+
mockProjectConfig.On("GetManifestSource", mock.Anything).Return(config.ManifestSourceLocal, nil)
875880
mockProjectConfig.On("Cache").Return(mockProjectCache)
876881
cm.Config.ProjectConfig = mockProjectConfig
877882
},

cmd/help/help.go

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func HelpFunc(
3535
if help, _ := clients.Config.Flags.GetBool("help"); help {
3636
clients.Config.LoadExperiments(ctx, clients.IO.PrintDebug)
3737
}
38+
style.ToggleCharm(clients.Config.WithExperimentOn(experiment.Charm))
3839
experiments := []string{}
3940
for _, exp := range clients.Config.GetExperiments() {
4041
if experiment.Includes(exp) {
@@ -66,15 +67,64 @@ func PrintHelpTemplate(cmd *cobra.Command, data style.TemplateData) {
6667
cmd.PrintErrln(err)
6768
}
6869
cmd.Long = cmdLongF.String()
69-
tmpl := helpTemplate
70+
tmpl := legacyHelpTemplate
71+
if style.IsCharmEnabled() {
72+
tmpl = charmHelpTemplate
73+
}
7074
err = style.PrintTemplate(cmd.OutOrStdout(), tmpl, templateInfo{cmd, data})
7175
if err != nil {
7276
cmd.PrintErrln(err)
7377
}
7478
}
7579

76-
// helpTemplate formats values and information for a helpful output
77-
const helpTemplate string = `{{.Long}}
80+
// ════════════════════════════════════════════════════════════════════════════════
81+
// Charm help template — lipgloss styling
82+
// ════════════════════════════════════════════════════════════════════════════════
83+
84+
const charmHelpTemplate string = `{{.Long | ToDescription}}
85+
86+
{{Header "Usage"}}{{if .Runnable}}
87+
{{ToPrompt "$ "}}{{ToCommandText .UseLine}}{{end}}{{if gt (len .Aliases) 0}}
88+
89+
{{Header "Aliases"}}
90+
{{.NameAndAliases | ToCommandText}}{{end}}{{if .HasAvailableSubCommands}}
91+
92+
{{if eq .Name (GetProcessName)}}{{Header "Commands"}}{{range .Commands}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}
93+
{{.Name | ToGroupName }}{{range .Commands}}{{if (not .Hidden)}}
94+
{{rpad .Name .NamePadding | ToCommandText}} {{.Short | ToDescription}}{{end}}{{end}}{{end}}{{end}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}{{range .Commands}}{{if and (not .HasAvailableSubCommands) (not .Hidden)}}{{if not (IsAlias .Name $.Data.Aliases)}}
95+
{{(rpad .Name .NamePadding) | ToGroupName }}{{.Short | ToDescription}}{{end}}{{end}}{{end}}{{end}}{{else}}{{Header "Subcommands"}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}{{range .Commands}}{{if not .HasAvailableSubCommands}}
96+
{{(rpad .Name .NamePadding) | ToCommandText }} {{.Short | ToDescription}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
97+
98+
{{Header "Flags"}}
99+
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces | ToFlags}}{{end}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}{{if or (HasAliasSubcommands .Name .Data.Aliases) (eq .Name (GetProcessName))}}
100+
101+
{{Header "Global aliases"}}{{range .Commands}}{{if and (IsAlias .Name $.Data.Aliases) (not .Hidden)}}
102+
{{(rpad .Name .NamePadding) | ToGroupName }} {{rpad (AliasParent .Name $.Data.Aliases) AliasPadding | ToAliasParent}} {{ToPrompt "❱"}} {{.Name | ToGroupName}}{{end}}{{end}}{{end}}{{end}}{{if .HasAvailableInheritedFlags}}
103+
104+
{{Header "Global flags"}}
105+
{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces | ToFlags}}{{end}}{{if .HasExample}}
106+
107+
{{Header "Example"}}
108+
{{ Examples .Example}}{{end}}{{if and (.HasAvailableSubCommands) (not .Hidden)}}
109+
110+
{{Header "Experiments"}}
111+
{{ Experiments .Data.Experiments }}
112+
113+
{{Header "Additional help"}}
114+
{{ToSecondary "For more information about a specific command, run:"}}
115+
{{ToPrompt "$ "}}{{ToCommandText .CommandPath}}{{if eq .Name (GetProcessName)}}{{ToCommandText " <command>"}}{{end}}{{ToCommandText " <subcommand> --help"}}
116+
117+
{{ToSecondary "For guides and documentation, head over to "}}{{LinkText "https://docs.slack.dev/tools/slack-cli"}}{{end}}
118+
119+
`
120+
121+
// ════════════════════════════════════════════════════════════════════════════════
122+
// DEPRECATED: Legacy help template — aurora styling
123+
//
124+
// Delete this entire block when the charm experiment is permanently enabled.
125+
// ════════════════════════════════════════════════════════════════════════════════
126+
127+
const legacyHelpTemplate string = `{{.Long}}
78128
79129
{{Header "Usage"}}{{if .Runnable}}
80130
$ {{.UseLine}}{{end}}{{if gt (len .Aliases) 0}}

cmd/manifest/validate.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,14 @@ func NewValidateCommand(clients *shared.ClientFactory) *cobra.Command {
8989
cmd.Printf(
9090
"\n%s: %s\n",
9191
style.Bold("App Manifest Validation Result"),
92-
style.Styler().Green("Valid"),
92+
style.Green("Valid"),
9393
)
9494
clients.IO.PrintTrace(ctx, slacktrace.ManifestValidateSuccess)
9595
} else {
9696
cmd.Printf(
9797
"\n%s: %s\n",
9898
style.Bold("App Manifest Validation Result"),
99-
style.Styler().Red("InValid"),
99+
style.Red("InValid"),
100100
)
101101
}
102102
return nil

cmd/manifest/validate_test.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ type ManifestValidatePkgMock struct {
3737
}
3838

3939
func (m *ManifestValidatePkgMock) ManifestValidate(ctx context.Context, clients *shared.ClientFactory, app types.App, token string) (bool, slackerror.Warnings, error) {
40-
m.Called(ctx, clients, app, token)
41-
return true, nil, nil
40+
args := m.Called(ctx, clients, app, token)
41+
return args.Bool(0), args.Get(1).(slackerror.Warnings), args.Error(2)
4242
}
4343

4444
func TestManifestValidateCommand(t *testing.T) {
@@ -63,7 +63,7 @@ func TestManifestValidateCommand(t *testing.T) {
6363
manifestValidatePkgMock := new(ManifestValidatePkgMock)
6464
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate
6565

66-
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
66+
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, slackerror.Warnings{}, nil)
6767
err := cmd.ExecuteContext(ctx)
6868
if err != nil {
6969
assert.Fail(t, "cmd.Execute had unexpected error")
@@ -138,7 +138,7 @@ func TestManifestValidateCommand_HandleMissingAppInstallError_OneUserAuth(t *tes
138138
// Mock the manifest validate package
139139
manifestValidatePkgMock := new(ManifestValidatePkgMock)
140140
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate
141-
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
141+
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, slackerror.Warnings{}, nil)
142142

143143
// Should execute without error
144144
err := cmd.ExecuteContext(ctx)
@@ -200,14 +200,38 @@ func TestManifestValidateCommand_HandleMissingAppInstallError_MoreThanOneUserAut
200200
// Mock the manifest validate package
201201
manifestValidatePkgMock := new(ManifestValidatePkgMock)
202202
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate
203-
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
203+
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true, slackerror.Warnings{}, nil)
204204

205205
// Should execute without error
206206
err := cmd.ExecuteContext(ctx)
207207
require.NoError(t, err)
208208
clientsMock.Auth.AssertCalled(t, "SetSelectedAuth", mock.Anything, mock.Anything, mock.Anything, mock.Anything)
209209
}
210210

211+
func TestManifestValidateCommand_InvalidManifest(t *testing.T) {
212+
ctx := slackcontext.MockContext(t.Context())
213+
clientsMock := shared.NewClientsMock()
214+
clientsMock.AddDefaultMocks()
215+
216+
clients := shared.NewClientFactory(clientsMock.MockClientFactory(), func(clients *shared.ClientFactory) {
217+
clients.SDKConfig = hooks.NewSDKConfigMock()
218+
})
219+
220+
cmd := NewValidateCommand(clients)
221+
testutil.MockCmdIO(clients.IO, cmd)
222+
223+
appSelectMock := prompts.NewAppSelectMock()
224+
appSelectPromptFunc = appSelectMock.AppSelectPrompt
225+
appSelectMock.On("AppSelectPrompt", mock.Anything, mock.Anything, prompts.ShowAllEnvironments, prompts.ShowInstalledAppsOnly).Return(prompts.SelectedApp{}, nil)
226+
227+
manifestValidatePkgMock := new(ManifestValidatePkgMock)
228+
manifestValidateFunc = manifestValidatePkgMock.ManifestValidate
229+
manifestValidatePkgMock.On("ManifestValidate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(false, slackerror.Warnings{}, nil)
230+
231+
err := cmd.ExecuteContext(ctx)
232+
require.NoError(t, err)
233+
}
234+
211235
func TestManifestValidateCommand_HandleOtherErrors(t *testing.T) {
212236
// Create mocks
213237
ctx := slackcontext.MockContext(t.Context())

cmd/project/create_template_charm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
"context"
1919
"strings"
2020

21-
"github.com/charmbracelet/huh"
21+
huh "charm.land/huh/v2"
2222
"github.com/slackapi/slack-cli/internal/shared"
2323
"github.com/slackapi/slack-cli/internal/slackerror"
2424
"github.com/slackapi/slack-cli/internal/slacktrace"

0 commit comments

Comments
 (0)