From d3d11593bc996217be9ac9ea1b085002f1582d70 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 2 Jan 2025 16:24:37 +1100 Subject: [PATCH] Add `update cli` Terminal output refactor --- docs/public/sponsors/zsa.png | Bin 0 -> 16188 bytes docs/src/content/docs/changelog.mdx | 7 +- docs/src/content/docs/credits.mdx | 9 +- docs/src/content/docs/guides/cli.mdx | 23 ++- v3/cmd/wails3/main.go | 1 + v3/internal/commands/appimage.go | 5 +- v3/internal/commands/bindings.go | 19 +-- v3/internal/commands/generate_webview2.go | 5 +- v3/internal/commands/init.go | 10 +- v3/internal/commands/releasenotes.go | 15 +- v3/internal/commands/service.go | 5 +- v3/internal/commands/task.go | 5 +- v3/internal/commands/task_wrapper.go | 4 +- v3/internal/commands/update_cli.go | 177 ++++++++++++++++++++++ v3/internal/commands/version.go | 2 +- v3/internal/doctor/doctor.go | 25 ++- v3/internal/templates/templates.go | 2 +- v3/internal/term/term.go | 105 +++++++++++++ v3/internal/version/version.go | 18 ++- 19 files changed, 383 insertions(+), 54 deletions(-) create mode 100644 docs/public/sponsors/zsa.png create mode 100644 v3/internal/commands/update_cli.go create mode 100644 v3/internal/term/term.go diff --git a/docs/public/sponsors/zsa.png b/docs/public/sponsors/zsa.png new file mode 100644 index 0000000000000000000000000000000000000000..507e983fa58d02741cdb60a1f53d57ce563fff3f GIT binary patch literal 16188 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 + + ZSA + `. +### `update cli` +Updates the Wails CLI to a new version. + +```bash +wails3 update cli [flags] +``` + +#### Flags +| Flag | Description | Default | +|-------------|---------------------------------|---------| +| `-pre` | Update to latest pre-release | `false` | +| `-version` | Update to specific version | | +| `-nocolour` | Disable colored output | `false` | + +The update cli command allows you to update your Wails CLI installation. By default, it updates to the latest stable release. +You can use the `-pre` flag to update to the latest pre-release version, or specify a particular version using the `-version` flag. + +After updating, remember to update your project's go.mod file to use the same version: +```bash +require github.com/wailsapp/wails/v3 v3.x.x +``` + ### `update build-assets` Updates the build assets using the given config file. @@ -413,4 +435,3 @@ Opens the Wails sponsorship page in your default browser. ```bash wails3 sponsor - diff --git a/v3/cmd/wails3/main.go b/v3/cmd/wails3/main.go index a1684cc33..56017cf49 100644 --- a/v3/cmd/wails3/main.go +++ b/v3/cmd/wails3/main.go @@ -57,6 +57,7 @@ func main() { update := app.NewSubCommand("update", "Update tools") update.NewSubCommandFunction("build-assets", "Updates the build assets using the given config file", commands.UpdateBuildAssets) + update.NewSubCommandFunction("cli", "Updates the Wails CLI", commands.UpdateCLI) bindgen := generate.NewSubCommand("bindings", "Generate bindings + models") var bindgenFlags flags.GenerateBindingsOptions diff --git a/v3/internal/commands/appimage.go b/v3/internal/commands/appimage.go index b2a148651..7c43ba856 100644 --- a/v3/internal/commands/appimage.go +++ b/v3/internal/commands/appimage.go @@ -4,6 +4,7 @@ import ( _ "embed" "errors" "fmt" + "github.com/wailsapp/wails/v3/internal/term" "os" "path/filepath" "runtime" @@ -19,7 +20,7 @@ var gtkPlugin []byte func log(p *pterm.ProgressbarPrinter, message string) { p.UpdateTitle(message) - pterm.Info.Println(message) + term.Infof(message) p.Increment() } @@ -61,7 +62,7 @@ func GenerateAppImage(options *GenerateAppImageOptions) error { return err } - pterm.Println(pterm.LightYellow("AppImage Generator v1.0.0")) + term.Header("AppImage Generator") return generateAppImage(options) } diff --git a/v3/internal/commands/bindings.go b/v3/internal/commands/bindings.go index 94833f881..89ce70376 100644 --- a/v3/internal/commands/bindings.go +++ b/v3/internal/commands/bindings.go @@ -3,28 +3,29 @@ package commands import ( "errors" "fmt" - "os" "path/filepath" "github.com/pterm/pterm" - "golang.org/x/term" "github.com/wailsapp/wails/v3/internal/flags" "github.com/wailsapp/wails/v3/internal/generator" "github.com/wailsapp/wails/v3/internal/generator/config" + "github.com/wailsapp/wails/v3/internal/term" ) func GenerateBindings(options *flags.GenerateBindingsOptions, patterns []string) error { DisableFooter = true if options.Silent { - pterm.DisableOutput() - defer pterm.EnableOutput() + term.DisableOutput() + defer term.EnableOutput() } else if options.Verbose { pterm.EnableDebugMessages() defer pterm.DisableDebugMessages() } + term.Header("Generate Bindings") + if len(patterns) == 0 { // No input pattern, load package from current directory. patterns = []string{"."} @@ -44,7 +45,7 @@ func GenerateBindings(options *flags.GenerateBindingsOptions, patterns []string) // Start a spinner for progress messages. var spinner *pterm.SpinnerPrinter - if term.IsTerminal(int(os.Stdout.Fd())) && (os.Getenv("CI") != "true") { + if term.IsTerminal() { spinner, _ = pterm.DefaultSpinner.Start("Initialising...") } @@ -68,11 +69,11 @@ func GenerateBindings(options *flags.GenerateBindingsOptions, patterns []string) if spinner != nil { spinner.Info(resultMessage) } else { - pterm.Info.Println(resultMessage) + term.Infofln(resultMessage) } // Report output directory. - pterm.Info.Printfln("Output directory: %s", absPath) + term.Infofln("Output directory: %s", absPath) // Process generator error. if err != nil { @@ -80,14 +81,14 @@ func GenerateBindings(options *flags.GenerateBindingsOptions, patterns []string) switch { case errors.Is(err, generator.ErrNoPackages): // Convert to warning message. - pterm.Warning.Println(err) + term.Warning(err) case errors.As(err, &report): if report.HasErrors() { // Report error count. return err } else if report.HasWarnings() { // Report warning count. - pterm.Warning.Println(report) + term.Warning(report) } default: // Report error. diff --git a/v3/internal/commands/generate_webview2.go b/v3/internal/commands/generate_webview2.go index affbb4519..146f72bff 100644 --- a/v3/internal/commands/generate_webview2.go +++ b/v3/internal/commands/generate_webview2.go @@ -3,10 +3,9 @@ package commands import ( _ "embed" "fmt" + "github.com/wailsapp/wails/v3/internal/term" "os" "path/filepath" - - "github.com/pterm/pterm" ) //go:embed webview2/MicrosoftEdgeWebview2Setup.exe @@ -35,6 +34,6 @@ func GenerateWebView2Bootstrapper(options *GenerateWebView2Options) error { return fmt.Errorf("failed to write WebView2 bootstrapper: %w", err) } - pterm.Success.Printf("Generated WebView2 bootstrapper at: %s\n", targetPath) + term.Success("Generated WebView2 bootstrapper at: " + targetPath + "\n") return nil } diff --git a/v3/internal/commands/init.go b/v3/internal/commands/init.go index c9aa42e4b..8a346f888 100644 --- a/v3/internal/commands/init.go +++ b/v3/internal/commands/init.go @@ -3,6 +3,7 @@ package commands import ( "fmt" "github.com/go-git/go-git/v5/config" + "github.com/wailsapp/wails/v3/internal/term" "os" "path/filepath" "regexp" @@ -103,12 +104,14 @@ func initGitRepository(projectDir string, gitURL string) error { func Init(options *flags.Init) error { if options.List { + term.Header("Available templates") return printTemplates() } if options.Quiet { - pterm.DisableOutput() + term.DisableOutput() } + term.Header("Init project") // Check if the template is a typescript template isTypescript := false @@ -158,7 +161,7 @@ func Init(options *flags.Init) error { return err } if !options.Quiet { - pterm.Info.Printf("Initialized git repository with remote: %s\n", options.Git) + term.Infof("Initialized git repository with remote: %s\n", options.Git) } } return nil @@ -167,8 +170,7 @@ func Init(options *flags.Init) error { func printTemplates() error { defaultTemplates := templates.GetDefaultTemplates() - pterm.DefaultSection.Println("Available templates") - + pterm.Println() table := pterm.TableData{{"Name", "Description"}} for _, template := range defaultTemplates { table = append(table, []string{template.Name, template.Description}) diff --git a/v3/internal/commands/releasenotes.go b/v3/internal/commands/releasenotes.go index 6dbb5a6cf..a90c7cb1b 100644 --- a/v3/internal/commands/releasenotes.go +++ b/v3/internal/commands/releasenotes.go @@ -1,8 +1,8 @@ package commands import ( - "github.com/pterm/pterm" "github.com/wailsapp/wails/v3/internal/github" + "github.com/wailsapp/wails/v3/internal/term" "github.com/wailsapp/wails/v3/internal/version" ) @@ -13,15 +13,22 @@ type ReleaseNotesOptions struct { func ReleaseNotes(options *ReleaseNotesOptions) error { if options.NoColour { - pterm.DisableColor() + term.DisableColor() } - currentVersion := version.VersionString + term.Header("Release Notes") + + if version.IsDev() { + term.Println("Release notes are not available for development builds") + return nil + } + + currentVersion := version.String() if options.Version != "" { currentVersion = options.Version } releaseNotes := github.GetReleaseNotes(currentVersion, options.NoColour) - pterm.Println(releaseNotes) + term.Println(releaseNotes) return nil } diff --git a/v3/internal/commands/service.go b/v3/internal/commands/service.go index 8babf87f3..8f5a6bd0a 100644 --- a/v3/internal/commands/service.go +++ b/v3/internal/commands/service.go @@ -3,9 +3,8 @@ package commands import ( "github.com/wailsapp/wails/v3/internal/flags" "github.com/wailsapp/wails/v3/internal/service" + "github.com/wailsapp/wails/v3/internal/term" "strings" - - "github.com/pterm/pterm" ) func toCamelCasePlugin(s string) string { @@ -34,7 +33,7 @@ func toCamelCasePlugin(s string) string { func ServiceInit(options *flags.ServiceInit) error { if options.Quiet { - pterm.DisableOutput() + term.DisableOutput() } if options.PackageName == "" { diff --git a/v3/internal/commands/task.go b/v3/internal/commands/task.go index 5b1743134..9672b2f27 100644 --- a/v3/internal/commands/task.go +++ b/v3/internal/commands/task.go @@ -3,13 +3,12 @@ package commands import ( "context" "fmt" + "github.com/wailsapp/wails/v3/internal/term" "os" "path/filepath" "strings" "time" - "github.com/pterm/pterm" - "github.com/wailsapp/task/v3" "github.com/wailsapp/task/v3/taskfile/ast" ) @@ -18,7 +17,7 @@ import ( var BuildSettings = map[string]string{} func fatal(message string) { - pterm.Error.Println(message) + term.Error(message) os.Exit(1) } diff --git a/v3/internal/commands/task_wrapper.go b/v3/internal/commands/task_wrapper.go index 896be3550..c4e55855e 100644 --- a/v3/internal/commands/task_wrapper.go +++ b/v3/internal/commands/task_wrapper.go @@ -1,9 +1,9 @@ package commands import ( + "github.com/wailsapp/wails/v3/internal/term" "os" - "github.com/pterm/pterm" "github.com/wailsapp/wails/v3/internal/flags" ) @@ -16,7 +16,7 @@ func Package(_ *flags.Package) error { } func wrapTask(command string) error { - pterm.Warning.Printf("`wails3 %s` is an alias for `wails3 task %s`. Use `wails task` for better control and more options.\n", command, command) + term.Warningf("`wails3 %s` is an alias for `wails3 task %s`. Use `wails task` for better control and more options.\n", command, command) os.Args = []string{"wails3", "task", command} return RunTask(&RunTaskOptions{}, []string{}) } diff --git a/v3/internal/commands/update_cli.go b/v3/internal/commands/update_cli.go new file mode 100644 index 000000000..a910622b4 --- /dev/null +++ b/v3/internal/commands/update_cli.go @@ -0,0 +1,177 @@ +package commands + +import ( + "fmt" + "github.com/pterm/pterm" + "github.com/wailsapp/wails/v3/internal/debug" + "github.com/wailsapp/wails/v3/internal/github" + "github.com/wailsapp/wails/v3/internal/term" + "github.com/wailsapp/wails/v3/internal/version" + "os" + "os/exec" + "path/filepath" +) + +type UpdateCLIOptions struct { + NoColour bool `name:"n" description:"Disable colour output"` + PreRelease bool `name:"pre" description:"Update to the latest pre-release (eg beta)"` + Version string `name:"version" description:"Update to a specific version (eg v3.0.0)"` + Latest bool `name:"latest" description:"Install the latest stable release"` +} + +func UpdateCLI(options *UpdateCLIOptions) error { + if options.NoColour { + term.DisableColor() + } + + term.Header("Update CLI") + + // Check if this CLI has been installed from vcs + if debug.LocalModulePath != "" && !options.Latest { + v3Path := filepath.ToSlash(debug.LocalModulePath + "/v3") + term.Println("This Wails CLI has been installed from source. To update to the latest stable release, run the following commands in the `" + v3Path + "` directory:") + term.Println(" - git pull") + term.Println(" - go install") + term.Println("") + term.Println("If you want to install the latest release, please run `wails update cli -latest`") + return nil + } + + if options.Latest { + latestVersion, err := github.GetLatestStableRelease() + if err != nil { + return err + } + return updateToVersion(latestVersion, true, version.String()) + } + + term.Println("Checking for updates...") + + var desiredVersion *github.SemanticVersion + var err error + var valid bool + + if len(options.Version) > 0 { + // Check if this is a valid version + valid, err = github.IsValidTag(options.Version) + if err == nil { + if !valid { + err = fmt.Errorf("version '%s' is invalid", options.Version) + } else { + desiredVersion, err = github.NewSemanticVersion(options.Version) + } + } + } else { + if options.PreRelease { + desiredVersion, err = github.GetLatestPreRelease() + } else { + desiredVersion, err = github.GetLatestStableRelease() + if err != nil { + pterm.Println("") + pterm.Println("No stable release found for this major version. To update to the latest pre-release (eg beta), run:") + pterm.Println(" wails update -pre") + return nil + } + } + } + if err != nil { + return err + } + pterm.Println() + + currentVersion := version.String() + pterm.Printf(" Current Version : %s\n", currentVersion) + + if len(options.Version) > 0 { + fmt.Printf(" Desired Version : v%s\n", desiredVersion) + } else { + if options.PreRelease { + fmt.Printf(" Latest Prerelease : v%s\n", desiredVersion) + } else { + fmt.Printf(" Latest Release : v%s\n", desiredVersion) + } + } + + return updateToVersion(desiredVersion, len(options.Version) > 0, currentVersion) +} + +func updateToVersion(targetVersion *github.SemanticVersion, force bool, currentVersion string) error { + targetVersionString := "v" + targetVersion.String() + + if targetVersionString == currentVersion { + pterm.Println("\nLooks like you're up to date!") + return nil + } + + var desiredVersion string + + if !force { + compareVersion := currentVersion + + currentVersion, err := github.NewSemanticVersion(compareVersion) + if err != nil { + return err + } + + var success bool + + // Release -> Pre-Release = Massage current version to prerelease format + if targetVersion.IsPreRelease() && currentVersion.IsRelease() { + testVersion, err := github.NewSemanticVersion(compareVersion + "-0") + if err != nil { + return err + } + success, _ = targetVersion.IsGreaterThan(testVersion) + } + // Pre-Release -> Release = Massage target version to prerelease format + if targetVersion.IsRelease() && currentVersion.IsPreRelease() { + mainversion := currentVersion.MainVersion() + targetVersion, err = github.NewSemanticVersion(targetVersion.String()) + if err != nil { + return err + } + success, _ = targetVersion.IsGreaterThanOrEqual(mainversion) + } + + // Release -> Release = Standard check + if (targetVersion.IsRelease() && currentVersion.IsRelease()) || + (targetVersion.IsPreRelease() && currentVersion.IsPreRelease()) { + success, _ = targetVersion.IsGreaterThan(currentVersion) + } + + // Compare + if !success { + pterm.Println("Error: The requested version is lower than the current version.") + pterm.Printf("If this is what you really want to do, use `wails update -version %s`\n", targetVersionString) + return nil + } + + desiredVersion = "v" + targetVersion.String() + } else { + desiredVersion = "v" + targetVersion.String() + } + + pterm.Println() + pterm.Print("Installing Wails CLI " + desiredVersion + "...") + + // Run command in non module directory + homeDir, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("cannot find home directory: %w", err) + } + + cmd := exec.Command("go", "install", "github.com/wailsapp/wails/v3/cmd/wails@"+desiredVersion) + cmd.Dir = homeDir + sout, serr := cmd.CombinedOutput() + if err := cmd.Run(); err != nil { + pterm.Println("Failed.") + pterm.Error.Println(string(sout) + "\n" + serr.Error()) + return err + } + pterm.Println("Done.") + pterm.Println("\nMake sure you update your project go.mod file to use " + desiredVersion + ":") + pterm.Println(" require github.com/wailsapp/wails/v3 " + desiredVersion) + pterm.Println("\nTo view the release notes, please run `wails3 releasenotes`") + + return nil +} diff --git a/v3/internal/commands/version.go b/v3/internal/commands/version.go index 6ff58879b..65bf66113 100644 --- a/v3/internal/commands/version.go +++ b/v3/internal/commands/version.go @@ -9,6 +9,6 @@ type VersionOptions struct{} func Version(_ *VersionOptions) error { DisableFooter = true - println(version.VersionString) + println(version.String()) return nil } diff --git a/v3/internal/doctor/doctor.go b/v3/internal/doctor/doctor.go index dcf4dd7ac..234c33ec5 100644 --- a/v3/internal/doctor/doctor.go +++ b/v3/internal/doctor/doctor.go @@ -3,6 +3,7 @@ package doctor import ( "bytes" "fmt" + "github.com/wailsapp/wails/v3/internal/term" "os/exec" "path/filepath" "regexp" @@ -30,13 +31,7 @@ func Run() (err error) { } _ = get - pterm.DefaultSection = *pterm.DefaultSection. - WithBottomPadding(0). - WithStyle(pterm.NewStyle(pterm.FgBlue, pterm.Bold)) - - pterm.Println() // Spacer - pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgLightBlue)).WithMargin(10).Println("Wails Doctor") - pterm.Println() // Spacer + term.Header("Wails Doctor") spinner, _ := pterm.DefaultSpinner.WithRemoveWhenDone().Start("Scanning system - Please wait (this may take a long time)...") @@ -68,7 +63,7 @@ func Run() (err error) { // Get system info info, err := operatingsystem.Info() if err != nil { - pterm.Error.Println("Failed to get system information") + term.Error("Failed to get system information") return err } @@ -77,7 +72,7 @@ func Run() (err error) { return dep.Path == "github.com/wailsapp/wails/v3" }) - wailsVersion := strings.TrimSpace(version.VersionString) + wailsVersion := strings.TrimSpace(version.String()) if wailsPackage != nil && wailsPackage.Replace != nil { wailsVersion = "(local) => " + filepath.ToSlash(wailsPackage.Replace.Path) // Get the latest commit hash @@ -99,7 +94,7 @@ func Run() (err error) { /** Output **/ - pterm.DefaultSection.Println("System") + term.Section("System") systemTabledata := pterm.TableData{ {pterm.Sprint("Name"), info.Name}, @@ -195,7 +190,7 @@ func Run() (err error) { // Build Environment - pterm.DefaultSection.Println("Build Environment") + term.Section("Build Environment") tableData := pterm.TableData{ {"Wails CLI", wailsVersion}, @@ -228,7 +223,7 @@ func Run() (err error) { } // Dependencies - pterm.DefaultSection.Println("Dependencies") + term.Section("Dependencies") dependenciesBox := pterm.DefaultBox.WithTitleBottomCenter().WithTitle(pterm.Gray("*") + " - Optional Dependency") dependencyTableData := pterm.TableData{} if len(dependencies) == 0 { @@ -248,11 +243,11 @@ func Run() (err error) { dependenciesBox.Println(dependenciesTableString) } - pterm.DefaultSection.Println("Diagnosis") + term.Section("Diagnosis") if !ok { - pterm.Warning.Println("There are some items above that need addressing!") + term.Warning("There are some items above that need addressing!") } else { - pterm.Success.Println("Your system is ready for Wails development!") + term.Success("Your system is ready for Wails development!") } return nil diff --git a/v3/internal/templates/templates.go b/v3/internal/templates/templates.go index 62206d2e3..5d9aa49d2 100644 --- a/v3/internal/templates/templates.go +++ b/v3/internal/templates/templates.go @@ -260,7 +260,7 @@ func Install(options *flags.Init) error { Init: options, LocalModulePath: localModulePath, UseTypescript: UseTypescript, - WailsVersion: version.VersionString, + WailsVersion: version.String(), } defer func() { diff --git a/v3/internal/term/term.go b/v3/internal/term/term.go new file mode 100644 index 000000000..f973bc667 --- /dev/null +++ b/v3/internal/term/term.go @@ -0,0 +1,105 @@ +package term + +import ( + "fmt" + "github.com/pterm/pterm" + "github.com/wailsapp/wails/v3/internal/generator/config" + "github.com/wailsapp/wails/v3/internal/version" + "golang.org/x/term" + "os" +) + +func Header(header string) { + // Print Wails with the current version in white on red background with the header in white with a green background + pterm.BgLightRed.Print(pterm.LightWhite(" Wails (" + version.String() + ") ")) + pterm.BgLightGreen.Println(pterm.LightWhite(" " + header + " ")) +} + +func Infof(format string, args ...interface{}) { + pterm.Info.Printf(format, args...) +} +func Infofln(format string, args ...interface{}) { + pterm.Info.Printfln(format, args...) +} + +func IsTerminal() bool { + return term.IsTerminal(int(os.Stdout.Fd())) && (os.Getenv("CI") != "true") +} + +type Spinner struct { + spinner *pterm.SpinnerPrinter +} + +func (s *Spinner) Logger() config.Logger { + if s == nil { + return nil + } + return config.DefaultPtermLogger(s.spinner) +} + +func StartSpinner(text string) *Spinner { + if !IsTerminal() { + return nil + } + spin, err := pterm.DefaultSpinner.Start(text) + if err != nil { + return nil + } + return &Spinner{ + spinner: spin, + } +} + +func StopSpinner(s *Spinner) { + if s == nil { + return + } + _ = s.spinner.Stop() +} + +func output(input any, printer pterm.PrefixPrinter, args ...any) { + switch v := input.(type) { + case string: + printer.Println(fmt.Sprintf(input.(string), args...)) + case error: + printer.Println(v.Error()) + default: + printer.Printfln("%v", v) + } +} + +func Warning(input any) { + output(input, pterm.Warning) +} + +func Warningf(input any, args ...any) { + output(input, pterm.Warning, args) +} + +func Error(input any) { + output(input, pterm.Error) +} + +func Success(input any) { + output(input, pterm.Success) +} + +func Section(s string) { + style := pterm.NewStyle(pterm.BgDefault, pterm.FgLightBlue, pterm.Bold) + style.Println("\n# " + s + " \n") +} + +func DisableColor() { + pterm.DisableColor() +} +func EnableOutput() { + pterm.EnableOutput() +} + +func DisableOutput() { + pterm.DisableOutput() +} + +func Println(s string) { + pterm.Println(s) +} diff --git a/v3/internal/version/version.go b/v3/internal/version/version.go index d8b4b0c2b..048fe1378 100644 --- a/v3/internal/version/version.go +++ b/v3/internal/version/version.go @@ -2,7 +2,23 @@ package version import ( _ "embed" + "github.com/wailsapp/wails/v3/internal/debug" ) //go:embed version.txt -var VersionString string +var versionString string + +func String() string { + if !IsDev() { + return versionString + } + return "v3 dev" +} + +func LatestStable() string { + return versionString +} + +func IsDev() bool { + return debug.LocalModulePath != "" +}