Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 39 additions & 60 deletions cmd/app/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,46 @@ func LinkCommandRunE(ctx context.Context, clients *shared.ClientFactory, app *ty
// Add empty line between executed command and first output
clients.IO.PrintInfo(ctx, false, "")

err = LinkExistingApp(ctx, clients, app, false)
// Header section
LinkAppHeaderSection(ctx, clients, false)

// App Manifest section
manifestSource, err := clients.Config.ProjectConfig.GetManifestSource(ctx)
if err != nil {
return err
}

configPath := filepath.Join(config.ProjectConfigDirName, config.ProjectConfigJSONFilename)
clients.IO.PrintInfo(ctx, false, "%s", style.Sectionf(style.TextSection{
Emoji: "books",
Text: "App Manifest",
Secondary: []string{
"Manifest source is gathered from " + style.Highlight(manifestSource.Human()),
"Manifest source is configured in " + style.Highlight(configPath),
},
}))

err = LinkExistingApp(ctx, clients, app)
if err != nil {
return err
}

// App summary section
clients.IO.PrintInfo(ctx, false, "%s", style.Sectionf(style.TextSection{
Emoji: "house",
Text: "App",
Secondary: FormatListSuccess([]types.App{*app}),
}))
Comment on lines +124 to +129

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏗️ question: I'm a fan of separating outputs and logic overall but am curious about including this within LinkExistingApp to keep the function signature minimal? I share another comment about ongoing refactor but am curious if this seems right or not:

func LinkCommandRunE(ctx context.Context, clients *shared.ClientFactory, app *types.App)

📣 ramble: So that we avoid conditional statements in these functions!


// Footer section
clients.IO.PrintInfo(ctx, false, "%s", style.Sectionf(style.TextSection{
Emoji: "house_with_garden",
Text: "App Link",
Secondary: []string{
"Added existing app to project",
},
}))

return nil
}

Expand All @@ -126,46 +161,9 @@ func LinkAppHeaderSection(ctx context.Context, clients *shared.ClientFactory, sh
}))
}

// LinkExistingApp prompts for an existing App ID and saves the details to the project.
// When shouldConfirm is true, a confirmation prompt will ask the user if they want to
// link an existing app and additional information is included in the header.
// The shouldConfirm option is encouraged for third-party callers.
func LinkExistingApp(ctx context.Context, clients *shared.ClientFactory, app *types.App, shouldConfirm bool) (err error) {
// Header section
LinkAppHeaderSection(ctx, clients, shouldConfirm)

// Confirm to add an existing app; useful for third-party callers
if shouldConfirm {
proceed, err := clients.IO.ConfirmPrompt(ctx, LinkAppConfirmPromptText, true)
if err != nil {
clients.IO.PrintDebug(ctx, "Error prompting to add an existing app: %s", err)
return err
}

// Add newline to match the trailing newline inserted from the footer section
clients.IO.PrintInfo(ctx, false, "")

if !proceed {
return nil
}
}

// App Manifest section
manifestSource, err := clients.Config.ProjectConfig.GetManifestSource(ctx)
if err != nil {
return err
}

configPath := filepath.Join(config.ProjectConfigDirName, config.ProjectConfigJSONFilename)
clients.IO.PrintInfo(ctx, false, "%s", style.Sectionf(style.TextSection{
Emoji: "books",
Text: "App Manifest",
Secondary: []string{
"Manifest source is gathered from " + style.Highlight(manifestSource.Human()),
"Manifest source is configured in " + style.Highlight(configPath),
},
}))

// LinkExistingApp resolves app details, validates the app, and saves it to the
// project. It produces no output — callers handle their own display.
func LinkExistingApp(ctx context.Context, clients *shared.ClientFactory, app *types.App) (err error) {
// Prompt to get app details
var auth *types.SlackAuth
*app, auth, err = promptExistingApp(ctx, clients)
Expand All @@ -186,28 +184,9 @@ func LinkExistingApp(ctx context.Context, clients *shared.ClientFactory, app *ty
return err
}

// Footer section
LinkAppFooterSection(ctx, clients, app)

return nil
}

// LinkAppFooterSection displays the details of app that was added to the project.
func LinkAppFooterSection(ctx context.Context, clients *shared.ClientFactory, app *types.App) {
clients.IO.PrintInfo(ctx, false, "\n%s", style.Sectionf(style.TextSection{
Emoji: "house",
Text: "App",
Secondary: formatListSuccess([]types.App{*app}),
}))
clients.IO.PrintInfo(ctx, false, "%s", style.Sectionf(style.TextSection{
Emoji: "house_with_garden",
Text: "App Link",
Secondary: []string{
"Added existing app to project",
},
}))
}

// promptExistingApp gathers details to represent app information
func promptExistingApp(ctx context.Context, clients *shared.ClientFactory) (types.App, *types.SlackAuth, error) {
slackAuth, err := prompts.PromptTeamSlackAuth(ctx, clients, "Select the existing app team", nil)
Expand Down
6 changes: 3 additions & 3 deletions cmd/app/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ func runListCommand(cmd *cobra.Command, clients *shared.ClientFactory) error {
clients.IO.PrintInfo(ctx, false, "\n%s", style.Sectionf(style.TextSection{
Emoji: "house_buildings",
Text: "Apps",
Secondary: formatListSuccess(envs),
Secondary: FormatListSuccess(envs),
}))
return nil
}

// formatListSuccess formats details about the list of project apps
func formatListSuccess(apps []types.App) (secondaryText []string) {
// FormatListSuccess formats details about the list of project apps
func FormatListSuccess(apps []types.App) (secondaryText []string) {
for _, app := range apps {
if app.AppID == "" {
continue
Expand Down
2 changes: 1 addition & 1 deletion cmd/app/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func TestAppsListFormat(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
listFlags = tc.Flags
formattedList := formatListSuccess(tc.Apps)
formattedList := FormatListSuccess(tc.Apps)
for ii, value := range formattedList {
formattedList[ii] = strings.TrimRight(value, ":")
}
Expand Down
8 changes: 7 additions & 1 deletion cmd/project/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,15 @@ func runCreateCommand(clients *shared.ClientFactory, cmd *cobra.Command, args []
defer func() {
_ = os.Chdir(originalDir)
}()
if err := app.LinkExistingApp(ctx, clients, &types.App{}, false); err != nil {
linkedApp := &types.App{}
if err := app.LinkExistingApp(ctx, clients, linkedApp); err != nil {
return err
}
clients.IO.PrintInfo(ctx, false, "%s", style.Sectionf(style.TextSection{
Emoji: "house",
Text: "App",
Secondary: app.FormatListSuccess([]types.App{*linkedApp}),
}))
}

printCreateSuccess(ctx, clients, appDirPath)
Expand Down
22 changes: 18 additions & 4 deletions cmd/project/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,25 @@ func projectInitCommandRunE(clients *shared.ClientFactory, cmd *cobra.Command, a
// Existing projects initialized always default to config.ManifestSourceLocal.
_ = create.InstallProjectDependencies(ctx, clients, projectDirPath)

// Add an existing app to the project
err = app.LinkExistingApp(ctx, clients, &types.App{}, true)
// Prompt to add an existing app to the project
app.LinkAppHeaderSection(ctx, clients, true)
proceed, err := clients.IO.ConfirmPrompt(ctx, app.LinkAppConfirmPromptText, true)
if err != nil {
// Display the error but continue to init
clients.IO.PrintError(ctx, "%s", err.Error())
clients.IO.PrintDebug(ctx, "Error prompting to add an existing app: %s", err)
}
if proceed {
linkedApp := &types.App{}
err = app.LinkExistingApp(ctx, clients, linkedApp)
if err != nil {
// Display the error but continue to init
clients.IO.PrintError(ctx, "%s", err.Error())
} else {
clients.IO.PrintInfo(ctx, false, "%s", style.Sectionf(style.TextSection{
Emoji: "house",
Text: "App",
Secondary: app.FormatListSuccess([]types.App{*linkedApp}),
}))
}
}

printNextStepSection(ctx, clients, projectDirPath)
Expand Down
Loading