Skip to content

Commit 9053f2b

Browse files
authored
Merge branch 'main' into mwbrooks-manifest-is_mcp_enabled
2 parents 57428ae + f99323b commit 9053f2b

6 files changed

Lines changed: 139 additions & 6 deletions

File tree

cmd/project/create_template.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,15 @@ func getAdapterOptions(framework string) []promptObject {
168168
func getSelectionOptionsForCategory(clients *shared.ClientFactory) []promptObject {
169169
return []promptObject{
170170
{
171-
Title: fmt.Sprintf("Starter app %s", style.Secondary("Getting started Slack app")),
171+
Title: fmt.Sprintf("Starter App %s", style.Secondary("Getting started Slack app")),
172172
Repository: "slack-cli#getting-started",
173173
},
174174
{
175-
Title: fmt.Sprintf("AI Agent app %s", style.Secondary("Slack agents and assistants")),
175+
Title: fmt.Sprintf("AI Agent App %s", style.Secondary("Slack agents and assistants")),
176176
Repository: "slack-cli#ai-apps",
177177
},
178178
{
179-
Title: fmt.Sprintf("Automation app %s", style.Secondary("Custom steps and workflows")),
179+
Title: fmt.Sprintf("Automation App %s", style.Secondary("Custom steps and workflows")),
180180
Repository: "slack-cli#automation-apps",
181181
},
182182
{

cmd/sandbox/list.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ func printSandboxes(cmd *cobra.Command, clients *shared.ClientFactory, token str
116116
clients.IO.PrintInfo(ctx, false, " %s", style.Secondary(fmt.Sprintf("URL: https://%s.slack.com", s.Domain)))
117117
}
118118

119+
if s.IsPartner {
120+
clients.IO.PrintInfo(ctx, false, " %s", style.Secondary("Type: Partner"))
121+
}
122+
119123
if s.Status != "" {
120124
status := style.Secondary(fmt.Sprintf("Status: %s", strings.ToTitle(s.Status)))
121125
if strings.EqualFold(s.Status, "archived") {

cmd/sandbox/list_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/slackapi/slack-cli/internal/shared/types"
2525
"github.com/slackapi/slack-cli/test/testutil"
2626
"github.com/spf13/cobra"
27+
"github.com/stretchr/testify/assert"
2728
"github.com/stretchr/testify/mock"
2829
)
2930

@@ -76,6 +77,7 @@ func TestListCommand(t *testing.T) {
7677
ExpectedStdoutOutputs: []string{"my-sandbox", "T123", "https://my-sandbox.slack.com", "Status: ACTIVE"},
7778
ExpectedAsserts: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock) {
7879
cm.API.AssertCalled(t, "ListSandboxes", mock.Anything, "xoxb-test-token", "")
80+
assert.NotContains(t, cm.GetStdoutOutput(), "Type:")
7981
},
8082
},
8183
"with archived sandbox": {
@@ -107,6 +109,42 @@ func TestListCommand(t *testing.T) {
107109
cm.API.AssertCalled(t, "ListSandboxes", mock.Anything, "xoxb-test-token", "")
108110
},
109111
},
112+
"with partner sandbox shows type for all sandboxes": {
113+
CmdArgs: []string{"--experiment=sandboxes", "--token", "xoxb-test-token"},
114+
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {
115+
testToken := "xoxb-test-token"
116+
cm.Auth.On("AuthWithToken", mock.Anything, testToken).Return(types.SlackAuth{Token: testToken}, nil)
117+
cm.Auth.On("ResolveAPIHost", mock.Anything, mock.Anything, mock.Anything).Return("https://api.slack.com")
118+
cm.Auth.On("ResolveLogstashHost", mock.Anything, mock.Anything, mock.Anything).Return("https://slackb.com/events/cli")
119+
sandboxes := []types.Sandbox{
120+
{
121+
TeamID: "T123",
122+
Name: "regular-sandbox",
123+
Domain: "regular-sandbox",
124+
Status: "active",
125+
DateCreated: 1700000000,
126+
},
127+
{
128+
TeamID: "T789",
129+
Name: "partner-sandbox",
130+
Domain: "partner-sandbox",
131+
Status: "active",
132+
DateCreated: 1700000000,
133+
IsPartner: true,
134+
},
135+
}
136+
cm.API.On("ListSandboxes", mock.Anything, testToken, "").Return(sandboxes, nil)
137+
cm.API.On("UsersInfo", mock.Anything, mock.Anything, mock.Anything).Return(&types.UserInfo{Profile: types.UserProfile{}}, nil)
138+
139+
cm.AddDefaultMocks()
140+
cm.Config.ExperimentsFlag = []string{string(experiment.Sandboxes)}
141+
cm.Config.LoadExperiments(ctx, cm.IO.PrintDebug)
142+
},
143+
ExpectedStdoutOutputs: []string{"regular-sandbox", "partner-sandbox", "Type: Partner"},
144+
ExpectedAsserts: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock) {
145+
cm.API.AssertCalled(t, "ListSandboxes", mock.Anything, "xoxb-test-token", "")
146+
},
147+
},
110148
"with status": {
111149
CmdArgs: []string{"--experiment=sandboxes", "--token", "xoxb-test-token", "--status", "active"},
112150
Setup: func(t *testing.T, ctx context.Context, cm *shared.ClientsMock, cf *shared.ClientFactory) {

internal/pkg/apps/install.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func Install(ctx context.Context, clients *shared.ClientFactory, auth types.Slac
226226
}
227227
}
228228
if iconPath != "" {
229-
err = updateIcon(ctx, clients, iconPath, app.AppID, token)
229+
err = updateIcon(ctx, clients, iconPath, app.AppID, token, manifest.IsFunctionRuntimeSlackHosted())
230230
if err != nil {
231231
clients.IO.PrintDebug(ctx, "icon error: %s", err)
232232
_, _ = clients.IO.WriteOut().Write([]byte(style.SectionSecondaryf("Error updating app icon: %s", err)))
@@ -650,16 +650,19 @@ func appendLocalToDisplayName(manifest *types.AppManifest) {
650650
}
651651

652652
// updateIcon will upload the new icon to the Slack API
653-
func updateIcon(ctx context.Context, clients *shared.ClientFactory, iconPath, appID string, token string) error {
653+
func updateIcon(ctx context.Context, clients *shared.ClientFactory, iconPath, appID string, token string, isHosted bool) error {
654654
var span opentracing.Span
655655
span, ctx = opentracing.StartSpanFromContext(ctx, "updateIcon")
656656
defer span.Finish()
657657

658658
var err error
659659
if clients.Config.WithExperimentOn(experiment.SetIcon) {
660660
_, err = clients.API().IconSet(ctx, clients.Fs, token, appID, iconPath)
661-
} else {
661+
} else if isHosted {
662+
// DEPRECATED: Prefer IconSet once the SetIcon experiment concludes
662663
_, err = clients.API().Icon(ctx, clients.Fs, token, appID, iconPath)
664+
} else {
665+
return nil
663666
}
664667
if err != nil {
665668
// TODO: separate the icon upload into a different function because if an error is returned

internal/pkg/apps/install_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ package apps
1616

1717
import (
1818
"bytes"
19+
"context"
20+
"fmt"
1921
"testing"
2022

2123
"github.com/slackapi/slack-cli/internal/api"
2224
"github.com/slackapi/slack-cli/internal/app"
2325
"github.com/slackapi/slack-cli/internal/cache"
2426
"github.com/slackapi/slack-cli/internal/config"
27+
"github.com/slackapi/slack-cli/internal/experiment"
2528
"github.com/slackapi/slack-cli/internal/shared"
2629
"github.com/slackapi/slack-cli/internal/shared/types"
2730
"github.com/slackapi/slack-cli/internal/slackcontext"
@@ -1724,3 +1727,87 @@ func TestContinueDespiteWarning(t *testing.T) {
17241727
})
17251728
}
17261729
}
1730+
1731+
func Test_updateIcon(t *testing.T) {
1732+
tests := map[string]struct {
1733+
isHosted bool
1734+
experimentOn bool
1735+
expectIconSet bool
1736+
expectIcon bool
1737+
expectSkip bool
1738+
mockError error
1739+
expectedError bool
1740+
}{
1741+
"experiment on + hosted app uses IconSet": {
1742+
isHosted: true,
1743+
experimentOn: true,
1744+
expectIconSet: true,
1745+
},
1746+
"experiment on + non-hosted app uses IconSet": {
1747+
isHosted: false,
1748+
experimentOn: true,
1749+
expectIconSet: true,
1750+
},
1751+
"experiment off + hosted app uses Icon": {
1752+
isHosted: true,
1753+
experimentOn: false,
1754+
expectIcon: true,
1755+
},
1756+
"experiment off + non-hosted app skips upload": {
1757+
isHosted: false,
1758+
experimentOn: false,
1759+
expectSkip: true,
1760+
},
1761+
"returns error from IconSet": {
1762+
isHosted: false,
1763+
experimentOn: true,
1764+
expectIconSet: true,
1765+
mockError: fmt.Errorf("api error"),
1766+
expectedError: true,
1767+
},
1768+
"returns error from Icon": {
1769+
isHosted: true,
1770+
experimentOn: false,
1771+
expectIcon: true,
1772+
mockError: fmt.Errorf("api error"),
1773+
expectedError: true,
1774+
},
1775+
}
1776+
for name, tc := range tests {
1777+
t.Run(name, func(t *testing.T) {
1778+
ctx := slackcontext.MockContext(t.Context())
1779+
clientsMock := shared.NewClientsMock()
1780+
clientsMock.AddDefaultMocks()
1781+
1782+
if tc.experimentOn {
1783+
clientsMock.Config.ExperimentsFlag = []string{string(experiment.SetIcon)}
1784+
clientsMock.Config.LoadExperiments(ctx, func(_ context.Context, _ string, _ ...interface{}) {})
1785+
}
1786+
1787+
clientsMock.API.On("IconSet", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
1788+
Return(api.IconResult{}, tc.mockError)
1789+
clientsMock.API.On("Icon", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
1790+
Return(api.IconResult{}, tc.mockError)
1791+
1792+
clients := shared.NewClientFactory(clientsMock.MockClientFactory())
1793+
err := updateIcon(ctx, clients, "icon.png", "A001", "xoxe-token", tc.isHosted)
1794+
1795+
if tc.expectedError {
1796+
require.Error(t, err)
1797+
} else {
1798+
require.NoError(t, err)
1799+
}
1800+
1801+
if tc.expectIconSet {
1802+
clientsMock.API.AssertCalled(t, "IconSet", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything)
1803+
clientsMock.API.AssertNotCalled(t, "Icon")
1804+
} else if tc.expectIcon {
1805+
clientsMock.API.AssertCalled(t, "Icon", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything)
1806+
clientsMock.API.AssertNotCalled(t, "IconSet")
1807+
} else if tc.expectSkip {
1808+
clientsMock.API.AssertNotCalled(t, "Icon")
1809+
clientsMock.API.AssertNotCalled(t, "IconSet")
1810+
}
1811+
})
1812+
}
1813+
}

internal/shared/types/sandbox.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ type Sandbox struct {
2222
Name string `json:"sandbox_name"`
2323
TeamID string `json:"sandbox_team_id"`
2424
Status string `json:"status"`
25+
IsPartner bool `json:"is_partner"`
2526
}

0 commit comments

Comments
 (0)