From a122598484bcd23183aefda4b8067dca246b33e2 Mon Sep 17 00:00:00 2001 From: Noah Date: Tue, 11 Jun 2024 14:00:32 -0500 Subject: [PATCH] Replace DeployErrors with a better system(?) (fix #42) --- deploy_error.go | 30 ------------------------ main.go | 46 ++++++++++++++++++------------------ matrix.go | 19 +++++++++++++-- matrix_commands.go | 17 ++++++-------- site.go | 58 ++++++++++++++++++++-------------------------- 5 files changed, 71 insertions(+), 99 deletions(-) delete mode 100644 deploy_error.go diff --git a/deploy_error.go b/deploy_error.go deleted file mode 100644 index 7916e78..0000000 --- a/deploy_error.go +++ /dev/null @@ -1,30 +0,0 @@ -// package main is the main package for the LapisDeploy program -package main - -import ( - "fmt" -) - -// DeployError contains important information about an error if something went wrong. -type DeployError struct { - code int - where string - details string - command_output string -} - -// SendOverMatrix provides an easy way to send the contents of a DeployError over Matrix -func (deploy_error *DeployError) SendOverMatrix() { - sendMessage(MatrixMessage{text: deploy_error.ToString()}) -} - -// ToString converts a DeployError into a human readable string. -func (deploy_error *DeployError) ToString() string { - return fmt.Sprintf("%sError in `%s`! (%s) Code: %d", - Circles["red"], deploy_error.where, deploy_error.details, deploy_error.code) -} - -// newDeployError creates a DeployError -func newDeployError(code int, where string, details string, command_output string) DeployError { - return DeployError{code: code, where: where, details: details, command_output: command_output} -} diff --git a/main.go b/main.go index 95045a6..68bb0ac 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" + "errors" "fmt" "log" "net/http" @@ -12,7 +13,7 @@ import ( "github.com/akamensky/argparse" ) -// Circle emoji storage. +// Circle emoji var Circles = map[string]string{ "white": "⚪️ ", "green": "🟢 ", @@ -21,9 +22,6 @@ var Circles = map[string]string{ "orange": "🟠 ", } -// Create a configuration struct -var configuration = Configuration{} - // fileExists returns whether the given file or directory exists. func fileExists(path string) (bool, error) { _, err := os.Stat(path) @@ -36,51 +34,51 @@ func fileExists(path string) (bool, error) { return false, err } +// Create a configuration struct +var configuration = Configuration{} + // handler is in charge of handling requests after the JSON has been parsed func handler(data map[string]interface{}) { repository := data["repository"].(map[string]interface{}) log.Default().Printf("Repo: %s", repository["full_name"]) - sendMessage(MatrixMessage{text: fmt.Sprintf("%sHandling webhook for `%s`...", - Circles["white"], repository["full_name"])}) + sendInfo(fmt.Sprintf("Handling webhook for `%s`...", repository["full_name"])) repo_name := repository["name"].(string) site, exists, err := getSite(repo_name) if err != nil { - deploy_error := newDeployError(1, "handler", fmt.Sprintf("Failed to check if site '%s' exists", repo_name), fmt.Sprint(err)) - deploy_error.SendOverMatrix() + sendError(errors.New(fmt.Sprintf("Failed to check if site '%s' exists: %s", repo_name, err))) return } if exists { - sendMessage(MatrixMessage{text: Circles["white"] + "Updating repository..."}) - if deploy_error := site.Update(); deploy_error.code != 0 { - deploy_error.SendOverMatrix() + sendInfo("Updating repository...") + if err := site.Update(); err != nil { + sendError(err) return } new_site, exists, err := getSite(site.name) if err != nil || !exists { - newDeployError(1, "main", "Failed to update site data on a site we just created!", fmt.Sprint(err)) + sendError(errors.New("Failed to update site data on a site we just updated: " + repo_name)) } site = new_site - sendMessage(MatrixMessage{text: Circles["white"] + "Restarting server..."}) - if deploy_error := site.Restart(); deploy_error.code != 0 { - deploy_error.SendOverMatrix() + sendInfo("Restarting server...") + if error := site.Restart(); error != nil { + sendError(error) return } } else { - sendMessage(MatrixMessage{text: Circles["white"] + "Cloning repository..."}) - if deploy_error := CloneSite(repository["ssh_url"].(string), repo_name); deploy_error.code != 0 { - deploy_error.SendOverMatrix() + sendInfo("Cloning repositiory...") + if error := CloneSite(repository["ssh_url"].(string), repo_name); error != nil { + sendError(error) return } - sendMessage(MatrixMessage{text: Circles["white"] + "Starting server..."}) + sendInfo("Starting server...") if site, exists, err = getSite(repo_name); err != nil { - deploy_error := newDeployError(1, "handler", - fmt.Sprintf("Failed to get site '%s' after creation!", repo_name), fmt.Sprint(err)) - deploy_error.SendOverMatrix() + sendError(err) + return } - if deploy_error := site.Start(); deploy_error.code != 0 { - deploy_error.SendOverMatrix() + if error := site.Start(); error != nil { + sendError(err) return } defer sendMessage(MatrixMessage{text: "🚀 Launched for the first time!"}) diff --git a/matrix.go b/matrix.go index 235fa9d..99c7944 100644 --- a/matrix.go +++ b/matrix.go @@ -3,6 +3,7 @@ package main import ( "context" + "fmt" "log" "strings" "time" @@ -29,15 +30,29 @@ type MatrixCommand struct { description string } -// Output queue +// Output queue. var MatrixOut []MatrixMessage -// sendMessage sends a message through Matrix +// sendMessage sends a message through Matrix. func sendMessage(msg MatrixMessage) { log.Print(msg.text) MatrixOut = append(MatrixOut, msg) } +// sendError sends an error through Matrix. +func sendError(err error) { + sendMessage(MatrixMessage{ + text: fmt.Sprintf("%s %s", Circles["red"], err), + }) +} + +// sendInfo sends a bit of info text through Matrix. +func sendInfo(text string) { + sendMessage(MatrixMessage{ + text: fmt.Sprintf("%s %s", Circles["white"], text), + }) +} + // initMatrix starts a Matrix bot. func initMatrix() { client, err := mautrix.NewClient(configuration.matrix.homeserver, "", "") diff --git a/matrix_commands.go b/matrix_commands.go index d6f8ab3..9b00c7c 100644 --- a/matrix_commands.go +++ b/matrix_commands.go @@ -16,9 +16,9 @@ func getSitesByString(text string) ([]Site, []string) { sites := []Site{} // sites holds every site we need // Determine which sites to get if text == "all" { // If we need to get all sites, (!restart all) - var err DeployError + var err error sites, err = getAllSites() // Get all sites - if err.code != 0 { // Check for errors + if err != nil { // Check for errors errors = append(errors, "Failed to get all sites!") } } else { // If we need to get a specific site, (!restart LapisDeploy-TestApp) @@ -53,7 +53,7 @@ func registerChatCommands() { callback: func(ctx context.Context, evt *event.Event, args []string) string { text := Circles["white"] + "Getting sites...\n" sites, err := getAllSites() - if err.code != 0 { + if err != nil { return text + Circles["red"] + "Failed to get sites!" } for _, site := range sites { @@ -82,9 +82,8 @@ func registerChatCommands() { text += Circles["red"] + error + "\n" } for _, site := range sites { // For every site queued to be restarted, - if err := site.Restart(); err.code != 0 { // Attempt to restart it + if err := site.Restart(); err != nil { // Attempt to restart it text += fmt.Sprintf("%sRestarting '%s'... failed!\n", Circles["red"], site.getName()) - text += err.ToString() } else { // Otherwise, success. text += fmt.Sprintf("%sRestarting '%s'... success", Circles["green"], site.getName()) } @@ -105,9 +104,8 @@ func registerChatCommands() { text += Circles["red"] + error + "\n" } for _, site := range sites { - if err := site.Start(); err.code != 0 { + if err := site.Start(); err != nil { text += fmt.Sprintf("%sStarting '%s'... failed!\n", Circles["red"], site.getName()) - text += err.ToString() } else { text += fmt.Sprintf("%sStarting '%s'... success!\n", Circles["green"], site.getName()) } @@ -128,9 +126,8 @@ func registerChatCommands() { text += Circles["red"] + error + "\n" } for _, site := range sites { - if err := site.Stop(); err.code != 0 { - text += fmt.Sprintf("%sStopping '%s'... failed!", Circles["red"], site.getName()) - text += err.ToString() + if err := site.Stop(); err != nil { + text += fmt.Sprintf("%sStopping '%s'... failed: %s", Circles["red"], site.getName(), err) } else { text += fmt.Sprintf("%sStopping '%s'... success", Circles["green"], site.getName()) } diff --git a/site.go b/site.go index 2dcdf7c..13ff9ff 100644 --- a/site.go +++ b/site.go @@ -98,13 +98,12 @@ func (site *Site) getName() string { } // getAllSites gets every site installed. -func getAllSites() ([]Site, DeployError) { +func getAllSites() ([]Site, error) { sites_dir := configuration.sites_dir files, err := os.ReadDir(sites_dir) var sites []Site if err != nil { - return sites, newDeployError(1, "startAllSites", - "Failed to read sites", fmt.Sprint(err)) + return sites, errors.New(fmt.Sprintf("Failed to read sites: %s", err)) } for _, file := range files { if !file.IsDir() { @@ -112,30 +111,30 @@ func getAllSites() ([]Site, DeployError) { } site, exists, err := getSite(file.Name()) if err != nil || !exists { - return sites, newDeployError(1, "getAllSites", "Failed to read sites", fmt.Sprint(err)) + return sites, errors.New(fmt.Sprintf("Failed to read sites: %s", err)) } sites = append(sites, site) } - return sites, DeployError{} + return sites, nil } // startAllSites attempts to start every site -func startAllSites() DeployError { +func startAllSites() error { sites, err := getAllSites() - if err.code != 0 { + if err != nil { return err } for _, site := range sites { err = site.Start() - if err.code != 0 { + if err != nil { return err } } - return DeployError{} + return nil } // Start attempts to start a Lapis server in the given repository. -func (site *Site) Start() DeployError { +func (site *Site) Start() error { log.Printf("Starting Lapis server in %s...", site.getName()) old_cwd, _ := os.Getwd() @@ -144,18 +143,17 @@ func (site *Site) Start() DeployError { cmd := exec.Command("lapis", "serve") if err := cmd.Start(); err != nil { - return newDeployError(1, "startSite", - fmt.Sprintf("Failed to start Lapis server in '%s'", site.getName()), "") + return errors.New(fmt.Sprintf("Failed to start Lapis server in '%s': %s", site.getName(), err)) } go func() { cmd.Wait() }() - return DeployError{} + return nil } // Stop attempts to stop a Lapis server in the given repository. -func (site *Site) Stop() DeployError { +func (site *Site) Stop() error { log.Printf("Stopping Lapis server %s...", site.getName()) old_cwd, _ := os.Getwd() @@ -164,17 +162,16 @@ func (site *Site) Stop() DeployError { cmd := exec.Command("lapis", "term") if err := cmd.Start(); err != nil { - return newDeployError(1, "stopSite", - fmt.Sprintf("Failed to stop Lapis server in '%s'", site.getName()), "") + return errors.New(fmt.Sprintf("Failed to stop Lapis server in '%s': %s", site.getName(), err)) } go func() { cmd.Wait() }() - return DeployError{} + return nil } // Restart attempts to restart the Lapis server in the given repository. -func (site *Site) Restart() DeployError { +func (site *Site) Restart() error { log.Printf("Restarting Lapis server in %s...", site.getName()) old_cwd, _ := os.Getwd() @@ -183,38 +180,33 @@ func (site *Site) Restart() DeployError { out, err := exec.Command("lapis", "build").CombinedOutput() if err != nil { - return newDeployError(1, "restartSite", - fmt.Sprintf("Failed to run 'lapis build' in '%s'", site.getName()), string(out)) + return errors.New(fmt.Sprintf("Failed to run 'lapis build' in '%s': %s", site.getName(), err)) } log.Printf("[lapis build] %s", out) if !strings.Contains(string(out), "HUP") { - return newDeployError(1, "restartSite", - "Failed to restart Lapis server! (Lapis not running?)", string(out)) + return errors.New(fmt.Sprintf("Failed to restart Lapis server! (Lapis not running?): %s", string(out))) } - return DeployError{} + return nil } // Update attempts to pull or clone a repository using the given name and url -func (site *Site) Update() DeployError { +func (site *Site) Update() error { log.Printf("Pulling down repository %s...", site.getName()) repo, err := git.Open(configuration.sites_dir + "/" + site.name) if err != nil { - return newDeployError(1, "updateSite", - fmt.Sprintf("Failed to open git repository '%s'", site.name), fmt.Sprint(err)) + return errors.New(fmt.Sprintf("Failed to open git repository '%s': %s", site.name, err)) } if err = repo.Pull(); err != nil { - return newDeployError(1, "updateSite", - fmt.Sprintf("Failed to pull down git repository '%s'", site.getName()), fmt.Sprint(err)) + return errors.New(fmt.Sprintf("Failed to pull down git repository '%s': %s", site.getName(), err)) } - return DeployError{} + return nil } // CloneSite will clone a site and put it in the configured 'sites_dir' -func CloneSite(url string, name string) DeployError { +func CloneSite(url string, name string) error { log.Printf("Cloning repository %s...", name) if err := git.Clone(url, configuration.sites_dir+"/"+name); err != nil { - return newDeployError(1, "cloneSite", - fmt.Sprintf("Failed to pull down repository '%s'", name), fmt.Sprint(err)) + return errors.New(fmt.Sprintf("Failed to pull down repository '%s': %s", name, err)) } - return DeployError{} + return nil }