func runLogin(cmd *cobra.Command, args []string) { if loginInfo := login.SavedLoginInfo(); loginInfo != nil { color.Red("You are already logged in as %s. To logout, type \"nestor logout\"\n", loginInfo.Email) os.Exit(1) } email := getEmail() password := getPassword() loginInfo, err := login.Login(email, password) if err != nil { color.Red(err.Error()) os.Exit(1) } err = loginInfo.Save() if err != nil { color.Red(unexpectedErrorWhileLoggingInErr.Error()) os.Exit(1) } color.Green("Successfully logged in as %s\n", email) // Make user pick a default team right at the beginning runTeam(cmd, args) }
func runTeam(cmd *cobra.Command, args []string) { var l *login.LoginInfo if l = login.SavedLoginInfo(); l == nil { color.Red("You are not logged in. To login, type \"nestor login\"\n") os.Exit(1) } teams, err := team.GetTeams(l) if err != nil { fmt.Println(unexpectedErrorWhileLoggingInErr.Error()) os.Exit(1) } if len(teams) == 1 { team := teams[0] err := team.Save(l) if err != nil { color.Red("Error saving default team\n") os.Exit(1) } else { color.Green("Saved %s as your default team\n", team.Name) } } else { table := team.TableizeTeams(teams, l.DefaultTeamId) fmt.Printf("\n") table.Render() fmt.Printf("\n") ok := false intIndex := 0 for !ok { index, promptErr := prompt.Basic(fmt.Sprintf("Pick which team you want to set as your default (1-%d): ", len(teams)), true) if promptErr != nil { os.Exit(1) } intIndex, err = strconv.Atoi(index) if err == nil && intIndex > 0 && intIndex <= len(teams) { ok = true } } team := teams[intIndex-1] err := team.Save(l) if err != nil { color.Red("Unexpected error saving your default team. Please try updating the app with `nestor update` or raise an issue at https://github.com/zerobotlabs/nestor-cli\n") os.Exit(1) } else { color.Green("Saved %s as your default team\n", team.Name) } } }
func runUpdate(cmd *cobra.Command, args []string) { newVersion, err := update.Update() switch { case err == update.NotAvailableErr: color.Green("No update available\n") os.Exit(0) case err != nil: color.Red("There was an error updating nestor. Please try again later or contact [email protected]\n") os.Exit(1) } color.Green("Updated nestor to new version: %s!\n", newVersion) }
func (a *App) CompileCoffeescript() error { coffeeFiles := []string{} if a.ArtifactPath == "" { return fmt.Errorf("ArtifactPath not set") } err := filepath.Walk(a.ArtifactPath, func(p string, info os.FileInfo, err error) error { if info.Mode().IsRegular() && strings.HasSuffix(p, ".coffee") { coffeeFiles = append(coffeeFiles, p) } return err }) if err != nil { return err } if len(coffeeFiles) == 0 { return nil } color.Green("+ Compiling Coffeescript...\n") binary, lookErr := exec.LookPath("coffee") if lookErr != nil { color.Red("- Could not find coffee in your $PATH. Please install coffee-script with 'npm install -g coffee-script'\n") return lookErr } for _, coffeeFile := range coffeeFiles { _, err := exec.Command(binary, "-c", coffeeFile).Output() if err != nil { return err } err = os.Remove(coffeeFile) if err != nil { return err } } return nil }
func runLogout(cmd *cobra.Command, args []string) { var l *login.LoginInfo if l = login.SavedLoginInfo(); l == nil { color.Red("You are not logged in. To login, type \"nestor login\"\n") os.Exit(1) } shouldLogout, err := prompt.Ask(fmt.Sprintf("Are you sure you want to log out as %s", l.Email)) if err != nil { os.Exit(1) } if shouldLogout { err = login.Delete() if err != nil { fmt.Println(unexpectedErrorWhileLoggingOutErr) os.Exit(1) } color.Green("Successfully logged out as %s\n", l.Email) } else { os.Exit(1) } }
func runSave(cmd *cobra.Command, args []string) { var l *login.LoginInfo var a app.App // Check if you are logged in first if l = login.SavedLoginInfo(); l == nil { color.Red("You are not logged in. To login, type \"nestor login\"\n") os.Exit(1) } // Check if you have a valid nestor.json file nestorJsonPath, err := pathToNestorJson(args) if err != nil { color.Red("Could not find nestor.json in the path specified\n") os.Exit(1) } a.ManifestPath = nestorJsonPath err = a.ParseManifest() if err != nil { color.Red("%s\n", err.Error()) os.Exit(1) } // Check if existing app exists and if so, then we should be making calls to the "UPDATE" function // We are ignoring the error for now but at some point we will have to show an error that is not annoying err = a.Hydrate(l) if err != nil { color.Red("- Error fetching details for power\n") } color.Green("+ Building deployment artifact...\n") err = a.BuildArtifact() if err != nil { color.Red("- Error while building deployment artifact for your power\n") } // Check if you need to do coffee compilation err = a.CompileCoffeescript() if err != nil { color.Red("- There was an error compiling coffeescript in your power\n") os.Exit(1) } err = a.CalculateLocalSha256() if err != nil { color.Red("- There was an error calculating whether your power needs to be uploaded\n") os.Exit(1) } if a.LocalSha256 != a.RemoteSha256 { color.Green("+ Generating zip...\n") zip, err := a.ZipBytes() if err != nil { color.Red("- Error creating a zip of your power's deployment artifact\n") os.Exit(1) } color.Green("+ Uploading zip...\n") // Upload app contents buffer := bytes.NewBuffer(zip) err = a.Upload(buffer, l) if err != nil { color.Red("- Error while uploading deployment artifact: %+v\n", err) os.Exit(1) } } // Make API call to Nestor with contents from JSON file along with S3 URL so that the API can create a functioning bot app color.Green("+ Saving power to Nestor...\n") err = a.SaveToNestor(l) if err != nil { color.Red("- Error while saving power to nestor: %+v\n", err) os.Exit(1) } color.Green("+ Successfully saved power to Nestor!\n") fmt.Printf("\nYou can test your power by running `nestor shell`\n") fmt.Printf("To deploy your power to Slack, run `nestor deploy --latest`\n") }
func runShell(cmd *cobra.Command, args []string) { var l *login.LoginInfo var a app.App // Check if you are logged in first if l = login.SavedLoginInfo(); l == nil { color.Red("You are not logged in. To login, type \"nestor login\"\n") os.Exit(1) } // Check if you have a valid nestor.json file nestorJsonPath, err := pathToNestorJson(args) if err != nil { color.Red("Could not find nestor.json in the path specified\n") os.Exit(1) } a.ManifestPath = nestorJsonPath err = a.ParseManifest() if err != nil { color.Red("%s\n", err.Error()) os.Exit(1) } // Check if existing app exists and if so, then we should be making calls to the "UPDATE" function // We are ignoring the error for now but at some point we will have to show an error that is not annoying err = a.Hydrate(l) if err != nil { color.Red("Error fetching details for power\n") } if a.Id == 0 { color.Red("You haven't saved your power yet. Run `nestor save` before you can test your power\n") os.Exit(1) } ok := false line := liner.NewLiner() line.SetCtrlCAborts(true) hf, err := os.OpenFile(historyFile, os.O_RDWR, 0644) if err != nil { color.Red("Unexpected error opening shell\n") line.Close() os.Exit(1) } line.ReadHistory(hf) for !ok { if command, err := line.Prompt("nestor> "); err == nil { command = strings.TrimSpace(command) if command != "" { line.AppendHistory(command) } switch { case quitPattern.MatchString(command): fmt.Println("Goodbye!") saveHistory(line, hf) os.Exit(1) case setEnvPattern.MatchString(command): matches := setEnvPattern.FindAllStringSubmatch(command, -1) resp, err := a.UpdateEnv(l, matches[0][1], matches[0][2]) if err != nil { color.Red("There was an error setting environment variable %s for your power", matches[0][1]) } else { fmt.Printf("Set %s to %s\n", matches[0][1], resp) } case getEnvPattern.MatchString(command): matches := getEnvPattern.FindAllStringSubmatch(command, -1) table, err := a.GetEnv(l, matches[0][1]) if err != nil { color.Red("There was an error getting environment variable %s for your power", matches[0][1]) } else { table.Render() fmt.Printf("\n") } case command == "": continue default: output := exec.Output{} err := output.Exec(&a, l, command) if err != nil { color.Red("unexpected error while running your power. Please try again later or contact [email protected]\n", err) } if output.Logs != "" { color.Yellow(output.Logs) } if len(output.ToSuggest) > 0 { suggestion := output.ToSuggest[0] fmt.Println("Oops, did you mean `" + suggestion + "`?") } else { for _, send := range output.ToSend { fmt.Println(send.ToString()) } } } } } saveHistory(line, hf) }
func runDeploy(cmd *cobra.Command, args []string) { var l *login.LoginInfo var a app.App // Check if you are logged in first if l = login.SavedLoginInfo(); l == nil { color.Red("You are not logged in. To login, type \"nestor login\"\n") os.Exit(1) } // Check if you have a valid nestor.json file nestorJsonPath, err := pathToNestorJson(args) if err != nil { color.Red("Could not find nestor.json in the path specified\n") os.Exit(1) } a.ManifestPath = nestorJsonPath err = a.ParseManifest() if err != nil { color.Red("%s\n", err.Error()) os.Exit(1) } // Check if existing app exists and if so, then we should be making calls to the "UPDATE" function // We are ignoring the error for now but at some point we will have to show an error that is not annoying err = a.Hydrate(l) if err != nil { color.Red("Error fetching details for this power\n") } if a.Id == 0 { color.Red("You haven't saved your power yet. Run `nestor save` before you can deploy your power\n") os.Exit(1) } versions, err := version.FetchVersions(a, l) if err != nil { color.Red("Error fetching versions for your power\n") os.Exit(1) } if latestDeploy { pickedVersion := versions[0] if pickedVersion.CurrentlyDeployed { color.Green("Version %s already deployed. Nothing to do here\n", pickedVersion.Ref) } else { err = pickedVersion.Deploy(a, l) if err != nil { color.Red(err.Error()) os.Exit(1) } color.Green("Deployed version %s successfully\n", pickedVersion.Ref) } } else { table := version.TableizeVersions(versions) fmt.Printf("\n") table.Render() fmt.Printf("\n") ok := false intIndex := 0 for !ok { index, promptErr := prompt.Basic(fmt.Sprintf("Pick a version to deploy (1-%d): ", len(versions)), true) if promptErr != nil { os.Exit(1) } intIndex, err = strconv.Atoi(index) if err == nil && intIndex > 0 && intIndex <= len(versions) { ok = true } } pickedVersion := versions[intIndex-1] if pickedVersion.CurrentlyDeployed { color.Green("Version %s already deployed. Nothing to do here\n", pickedVersion.Ref) } else { err = pickedVersion.Deploy(a, l) if err != nil { color.Red("Error deploying %s. Please try again later or contact [email protected]\n", pickedVersion.Ref) os.Exit(1) } color.Green("Deployed version %s successfully\n", pickedVersion.Ref) } } }
func runNew(cmd *cobra.Command, args []string) { if len(args) != 1 { color.Red("Usage: nestor new <power-name>") os.Exit(1) } appName := strings.TrimSpace(args[0]) permalink := strings.ToLower(strings.Replace(appName, " ", "-", -1)) permalink = strings.ToLower(strings.Replace(permalink, ".", "-", -1)) currentDir, err := os.Getwd() if err != nil { color.Red("Unexpected error occurred while creating your power: %+v", err) os.Exit(1) } base := path.Join(currentDir, permalink) if _, err = os.Stat(base); err == nil { color.Red("A power with this name already exists in this directory, pick another name or another directory to create your power") os.Exit(1) } color.Green("+ Creating directory...") err = os.Mkdir(base, 0755) if err != nil { color.Red("- Unexpected error occurred while creating your power: %+v", err) os.Exit(1) } binary, lookErr := exec.LookPath("npm") if lookErr != nil { color.Red("- Could not find npm in your $PATH. Please install nodejs from https://nodejs.org") os.Exit(1) } color.Green("+ Running npm init...") npmInitCommand := exec.Command(binary, "init", "-y") npmInitCommand.Dir = base err = npmInitCommand.Run() if err != nil { color.Red("- Unexpected Error while creating package.json for your power") os.Exit(1) } color.Green("+ Running npm install nestorbot...") npmInstallCommand := exec.Command(binary, "install", "nestorbot", "--save") npmInstallCommand.Dir = base err = npmInstallCommand.Run() if err != nil { color.Red("- Unexpected Error while downloading nestorbot") os.Exit(1) } color.Green("+ Creating nestor.json...") var app AppNestorJson app.Name = appName app.Description = appName app.Permalink = permalink marshaledApp, err := json.MarshalIndent(app, "", " ") if err != nil { color.Red("- Unexpected Error while creating nestor.json") os.Exit(1) } nestorJsonPath := path.Join(base, "nestor.json") err = ioutil.WriteFile(nestorJsonPath, marshaledApp, 0644) if err != nil { color.Red("- Unexpected Error while creating nestor.json: %+v", err) os.Exit(1) } color.Green("+ Creating example at index.js...") indexFilePath := path.Join(base, "index.js") err = ioutil.WriteFile(indexFilePath, []byte(defaultAppFile), 0644) if err != nil { color.Red("- Unexpected Error while creating index.js: %+v", err) os.Exit(1) } color.Green("+ Downloading README...") resp, err := http.Get(readmeUrl) if err != nil { color.Red("- Unexpected Error while fetching README: %+v", err) os.Exit(1) } defer resp.Body.Close() readmePath := path.Join(base, "README.md") readme, err := os.Create(readmePath) if err != nil { color.Red("- Unexpected Error while creating README: %+v", err) os.Exit(1) } defer readme.Close() _, err = io.Copy(readme, resp.Body) if err != nil { color.Red("- Unexpected Error while creating README: %+v", err) os.Exit(1) } color.Green("Successfully created power %s here: %s", appName, base) fmt.Printf("\ncd %s and run `nestor save` and `nestor shell` to start working on your power\n", base) }