From f560c46b76892b83faa1a8a9277fe77f3eb32d3f Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 7 Jul 2022 14:44:35 -0700 Subject: [PATCH 1/5] unify colors --- cli/azd/cmd/deploy.go | 20 +++++++++++--------- cli/azd/cmd/infra_create.go | 13 ++++++++----- cli/azd/cmd/util.go | 21 +++++++++++++++++++++ cli/azd/pkg/spin/run.go | 14 +++++--------- cli/azd/pkg/spin/run_test.go | 2 +- go.mod | 2 +- 6 files changed, 47 insertions(+), 25 deletions(-) diff --git a/cli/azd/cmd/deploy.go b/cli/azd/cmd/deploy.go index 109ca758192..08cf8fdbc96 100644 --- a/cli/azd/cmd/deploy.go +++ b/cli/azd/cmd/deploy.go @@ -17,8 +17,6 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/project" "github.com/azure/azure-dev/cli/azd/pkg/spin" "github.com/azure/azure-dev/cli/azd/pkg/tools" - "github.com/fatih/color" - "github.com/mattn/go-colorable" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/theckman/yacspin" @@ -160,10 +158,8 @@ func (d *deployAction) Run(ctx context.Context, cmd *cobra.Command, args []strin err = spin.RunWithUpdater( fmt.Sprintf("Deploying service %s ", svc.Config.Name), deployAndReportProgress, - func(s *yacspin.Spinner, successDeploy bool) { - if successDeploy { - reportServiceDeploymentResultInteractive(s, svc, &svcDeploymentResult) - } + func(s *yacspin.Spinner) { + reportServiceDeploymentResultInteractive(s, svc, &svcDeploymentResult) }) } else { err = deployAndReportProgress(nil) @@ -190,8 +186,14 @@ func (d *deployAction) Run(ctx context.Context, cmd *cobra.Command, args []strin } for _, resourceGroup := range resourceGroups { - resourcesGroupsURL := color.HiBlueString("https://portal.azure.com/#@/resource/subscriptions/%s/resourceGroups/%s/overview", env.GetSubscriptionId(), resourceGroup) - fmt.Fprintf(colorable.NewColorableStdout(), "View the resources created under the resource group %s in Azure Portal:\n%s", color.CyanString(resourceGroup), resourcesGroupsURL) + resourcesGroupsURL := withLinkFormat( + "https://portal.azure.com/#@/resource/subscriptions/%s/resourceGroups/%s/overview", + env.GetSubscriptionId(), + resourceGroup) + printWithStyling( + "View the resources created under the resource group %s in Azure Portal:\n%s", + withHighLightFormat(resourceGroup), + resourcesGroupsURL) } return nil @@ -201,7 +203,7 @@ func reportServiceDeploymentResultInteractive(s *yacspin.Spinner, svc *project.S var builder strings.Builder for _, endpoint := range sdr.Endpoints { - builder.WriteString(fmt.Sprintf(" - Endpoint: %s\n", color.HiBlueString(endpoint))) + builder.WriteString(fmt.Sprintf(" - Endpoint: %s\n", withLinkFormat(endpoint))) } stopMessage := fmt.Sprintf("\nDeployed service %s\n%s", svc.Config.Name, builder.String()) diff --git a/cli/azd/cmd/infra_create.go b/cli/azd/cmd/infra_create.go index 17477617b7d..255c2298370 100644 --- a/cli/azd/cmd/infra_create.go +++ b/cli/azd/cmd/infra_create.go @@ -19,8 +19,6 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/spin" "github.com/azure/azure-dev/cli/azd/pkg/tools" "github.com/drone/envsubst" - "github.com/fatih/color" - "github.com/mattn/go-colorable" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/theckman/yacspin" @@ -229,11 +227,16 @@ func (ica *infraCreateAction) Run(ctx context.Context, cmd *cobra.Command, args if interactive { deploymentSlug := azure.SubscriptionDeploymentRID(env.GetSubscriptionId(), env.GetEnvName()) - deploymentURL := color.HiBlueString("https://portal.azure.com/#blade/HubsExtension/DeploymentDetailsBlade/overview/id/%s\n\n", url.PathEscape(deploymentSlug)) - fmt.Fprintf(colorable.NewColorableStdout(), "Provisioning Azure resources can take some time.\n\nYou can view detailed progress in the Azure Portal:\n%s", deploymentURL) + deploymentURL := withLinkFormat( + "https://portal.azure.com/#blade/HubsExtension/DeploymentDetailsBlade/overview/id/%s\n\n", + url.PathEscape(deploymentSlug)) + printWithStyling( + "Provisioning Azure resources can take some time.\n\nYou can view detailed progress in the Azure Portal:\n%s", + deploymentURL) + //fmt.Fprintf(colorable.NewColorableStdout(), "Provisioning Azure resources can take some time.\n\nYou can view detailed progress in the Azure Portal:\n%s", deploymentURL) err = spin.RunWithUpdater("Creating Azure resources ", deployAndReportProgress, - func(s *yacspin.Spinner, deploySuccess bool) { + func(s *yacspin.Spinner) { s.StopMessage("Created Azure resources\n") }) } else { diff --git a/cli/azd/cmd/util.go b/cli/azd/cmd/util.go index 77b74a31fac..679b87aa508 100644 --- a/cli/azd/cmd/util.go +++ b/cli/azd/cmd/util.go @@ -20,7 +20,9 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/environment" "github.com/azure/azure-dev/cli/azd/pkg/templates" "github.com/azure/azure-dev/cli/azd/pkg/tools" + "github.com/fatih/color" "github.com/mattn/go-isatty" + "github.com/mgutz/ansi" ) type Asker func(p survey.Prompt, response interface{}) error @@ -550,3 +552,22 @@ func ensureProject(path string) error { return nil } + +// withLinkFormat creates string with hyperlink-looking color +func withLinkFormat(link string, a ...interface{}) string { + // See ansi colors: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors + // ansi code `30` is the one that matches the survey selection + return ansi.Color(fmt.Sprintf(link, a...), "30") +} + +// withHighLightFormat creates string with highlight-looking color +func withHighLightFormat(text string, a ...interface{}) string { + return color.CyanString(text, a...) +} + +// printWithStyling prints text to stdout and handles Windows terminals to support +// escape chars from the text for adding style (color, font, etc) +func printWithStyling(text string, a ...interface{}) { + colorTerminal := color.New() + colorTerminal.Printf(text, a...) +} diff --git a/cli/azd/pkg/spin/run.go b/cli/azd/pkg/spin/run.go index 11864c6be2e..5946922ed35 100644 --- a/cli/azd/pkg/spin/run.go +++ b/cli/azd/pkg/spin/run.go @@ -14,7 +14,7 @@ type RunWithUpdateFunc = func(func(string)) error type RunFunc func() error // Run is the equivalent of RunWithUpdater with no updater specified -func Run(prefix string, runFn RunFunc, finalFuncs ...func(*yacspin.Spinner, bool)) error { +func Run(prefix string, runFn RunFunc, finalFuncs ...func(*yacspin.Spinner)) error { return RunWithUpdater( prefix, func(func(string)) error { @@ -26,9 +26,8 @@ func Run(prefix string, runFn RunFunc, finalFuncs ...func(*yacspin.Spinner, bool // RunWithUpdater runs runFn with a spinner. The prefix of the spinner is set to prefix, // and when runFn is complete, each function in finalFuncs is executed in serial, regardless -// of whether runFn errored, but each finalFunction gets a boolean argument indicating if -// main function succeeded. -func RunWithUpdater(prefix string, runFn RunWithUpdateFunc, finalFuncs ...func(*yacspin.Spinner, bool)) error { +// of whether runFn errored. +func RunWithUpdater(prefix string, runFn RunWithUpdateFunc, finalFuncs ...func(*yacspin.Spinner)) error { spin, _ := yacspin.New(yacspin.Config{ Frequency: time.Millisecond * 500, CharSet: yacspin.CharSets[9], @@ -49,18 +48,15 @@ func RunWithUpdater(prefix string, runFn RunWithUpdateFunc, finalFuncs ...func(* // When `runFn` completes (which causes this function to return), run // all the final functions. NOTE: Since go processes `defers` in LIFO // order, all of these final functions will run before `Stop` is called. - var result error defer func() { for _, finalFunc := range finalFuncs { - finalFunc(spin, result == nil) + finalFunc(spin) } }() - result = runFn(func(newPrefix string) { + return runFn(func(newPrefix string) { if newPrefix != "" { spin.Prefix(newPrefix) } }) - - return result } diff --git a/cli/azd/pkg/spin/run_test.go b/cli/azd/pkg/spin/run_test.go index 54c84a86231..219f8127e37 100644 --- a/cli/azd/pkg/spin/run_test.go +++ b/cli/azd/pkg/spin/run_test.go @@ -11,7 +11,7 @@ import ( func Test_Run(t *testing.T) { t.Run("FinalFuncs Are Called", func(t *testing.T) { runCount := 0 - increment := func(s *yacspin.Spinner, noError bool) { + increment := func(s *yacspin.Spinner) { assert.NotNil(t, s, "spinner should be passed to final functions") runCount++ } diff --git a/go.mod b/go.mod index bef992780c5..07281502ab3 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/joho/godotenv v1.4.0 github.com/magefile/mage v1.12.1 github.com/mattn/go-isatty v0.0.14 + github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b github.com/otiai10/copy v1.7.0 github.com/pbnj/go-open v0.1.1 github.com/sethvargo/go-retry v0.2.3 @@ -28,7 +29,6 @@ require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/pkg/errors v0.8.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect From 0446cc3e5537b6d2fb558b39bfb43bf7d733ae8e Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Fri, 8 Jul 2022 00:43:08 -0700 Subject: [PATCH 2/5] rebase issues --- cli/azd/cmd/deploy.go | 6 ++++-- cli/azd/cmd/infra_create.go | 2 +- cli/azd/pkg/spin/run.go | 11 +++++++---- go.mod | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cli/azd/cmd/deploy.go b/cli/azd/cmd/deploy.go index 08cf8fdbc96..406a2fde6b4 100644 --- a/cli/azd/cmd/deploy.go +++ b/cli/azd/cmd/deploy.go @@ -158,8 +158,10 @@ func (d *deployAction) Run(ctx context.Context, cmd *cobra.Command, args []strin err = spin.RunWithUpdater( fmt.Sprintf("Deploying service %s ", svc.Config.Name), deployAndReportProgress, - func(s *yacspin.Spinner) { - reportServiceDeploymentResultInteractive(s, svc, &svcDeploymentResult) + func(s *yacspin.Spinner, successDeploy bool) { + if successDeploy { + reportServiceDeploymentResultInteractive(s, svc, &svcDeploymentResult) + } }) } else { err = deployAndReportProgress(nil) diff --git a/cli/azd/cmd/infra_create.go b/cli/azd/cmd/infra_create.go index 255c2298370..6566fb4af7f 100644 --- a/cli/azd/cmd/infra_create.go +++ b/cli/azd/cmd/infra_create.go @@ -236,7 +236,7 @@ func (ica *infraCreateAction) Run(ctx context.Context, cmd *cobra.Command, args //fmt.Fprintf(colorable.NewColorableStdout(), "Provisioning Azure resources can take some time.\n\nYou can view detailed progress in the Azure Portal:\n%s", deploymentURL) err = spin.RunWithUpdater("Creating Azure resources ", deployAndReportProgress, - func(s *yacspin.Spinner) { + func(s *yacspin.Spinner, deploySuccess bool) { s.StopMessage("Created Azure resources\n") }) } else { diff --git a/cli/azd/pkg/spin/run.go b/cli/azd/pkg/spin/run.go index 5946922ed35..8ab05d2cf2a 100644 --- a/cli/azd/pkg/spin/run.go +++ b/cli/azd/pkg/spin/run.go @@ -14,7 +14,7 @@ type RunWithUpdateFunc = func(func(string)) error type RunFunc func() error // Run is the equivalent of RunWithUpdater with no updater specified -func Run(prefix string, runFn RunFunc, finalFuncs ...func(*yacspin.Spinner)) error { +func Run(prefix string, runFn RunFunc, finalFuncs ...func(*yacspin.Spinner, bool)) error { return RunWithUpdater( prefix, func(func(string)) error { @@ -27,7 +27,7 @@ func Run(prefix string, runFn RunFunc, finalFuncs ...func(*yacspin.Spinner)) err // RunWithUpdater runs runFn with a spinner. The prefix of the spinner is set to prefix, // and when runFn is complete, each function in finalFuncs is executed in serial, regardless // of whether runFn errored. -func RunWithUpdater(prefix string, runFn RunWithUpdateFunc, finalFuncs ...func(*yacspin.Spinner)) error { +func RunWithUpdater(prefix string, runFn RunWithUpdateFunc, finalFuncs ...func(*yacspin.Spinner, bool)) error { spin, _ := yacspin.New(yacspin.Config{ Frequency: time.Millisecond * 500, CharSet: yacspin.CharSets[9], @@ -48,15 +48,18 @@ func RunWithUpdater(prefix string, runFn RunWithUpdateFunc, finalFuncs ...func(* // When `runFn` completes (which causes this function to return), run // all the final functions. NOTE: Since go processes `defers` in LIFO // order, all of these final functions will run before `Stop` is called. + var result error defer func() { for _, finalFunc := range finalFuncs { - finalFunc(spin) + finalFunc(spin, result == nil) } }() - return runFn(func(newPrefix string) { + result = runFn(func(newPrefix string) { if newPrefix != "" { spin.Prefix(newPrefix) } }) + + return result } diff --git a/go.mod b/go.mod index b7f5448b8ff..23726b5d148 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/fatih/color v1.13.0 github.com/joho/godotenv v1.4.0 github.com/magefile/mage v1.12.1 - github.com/mattn/go-colorable v0.1.12 github.com/mattn/go-isatty v0.0.14 github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b github.com/otiai10/copy v1.7.0 @@ -29,6 +28,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/pkg/errors v0.8.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect From fa3e944405717ab8c3ce100cb14b86f306ccf8b1 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Fri, 8 Jul 2022 00:45:40 -0700 Subject: [PATCH 3/5] other issue --- cli/azd/pkg/spin/run.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli/azd/pkg/spin/run.go b/cli/azd/pkg/spin/run.go index 8ab05d2cf2a..11864c6be2e 100644 --- a/cli/azd/pkg/spin/run.go +++ b/cli/azd/pkg/spin/run.go @@ -26,7 +26,8 @@ func Run(prefix string, runFn RunFunc, finalFuncs ...func(*yacspin.Spinner, bool // RunWithUpdater runs runFn with a spinner. The prefix of the spinner is set to prefix, // and when runFn is complete, each function in finalFuncs is executed in serial, regardless -// of whether runFn errored. +// of whether runFn errored, but each finalFunction gets a boolean argument indicating if +// main function succeeded. func RunWithUpdater(prefix string, runFn RunWithUpdateFunc, finalFuncs ...func(*yacspin.Spinner, bool)) error { spin, _ := yacspin.New(yacspin.Config{ Frequency: time.Millisecond * 500, From 7d7d6b6b9bf29983eaa14d919fc3e8d3caf49df7 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Fri, 8 Jul 2022 00:46:22 -0700 Subject: [PATCH 4/5] more --- cli/azd/pkg/spin/run_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/azd/pkg/spin/run_test.go b/cli/azd/pkg/spin/run_test.go index 219f8127e37..54c84a86231 100644 --- a/cli/azd/pkg/spin/run_test.go +++ b/cli/azd/pkg/spin/run_test.go @@ -11,7 +11,7 @@ import ( func Test_Run(t *testing.T) { t.Run("FinalFuncs Are Called", func(t *testing.T) { runCount := 0 - increment := func(s *yacspin.Spinner) { + increment := func(s *yacspin.Spinner, noError bool) { assert.NotNil(t, s, "spinner should be passed to final functions") runCount++ } From f374e3e38bf28cdec0d2e5cce18cb7c69bc034f7 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Fri, 8 Jul 2022 00:48:07 -0700 Subject: [PATCH 5/5] cspell --- cli/azd/.vscode/cspell-azd-dictionary.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/azd/.vscode/cspell-azd-dictionary.txt b/cli/azd/.vscode/cspell-azd-dictionary.txt index 3b42afecb61..ec26a8a1c1f 100644 --- a/cli/azd/.vscode/cspell-azd-dictionary.txt +++ b/cli/azd/.vscode/cspell-azd-dictionary.txt @@ -28,6 +28,7 @@ godotenv golangci ldflags mgmt +mgutz nodeapp nolint omitempty