Replace DeployErrors with a better system(?) (fix #42)
This commit is contained in:
parent
20b955231b
commit
a122598484
@ -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}
|
||||
}
|
46
main.go
46
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!"})
|
||||
|
19
matrix.go
19
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, "", "")
|
||||
|
@ -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())
|
||||
}
|
||||
|
58
site.go
58
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user