diff --git a/config.go b/config.go new file mode 100644 index 0000000..ff33fcc --- /dev/null +++ b/config.go @@ -0,0 +1,26 @@ +// package main is the main package for the LapisDeploy program +package main + +import ( + "os" + "encoding/json" + "log" +) + +// Configuration stores information retrieved from a configuration file +type Configuration struct { + sites_dir string +} + +// parseConfig parses the JSON configuration file at 'path' and stores the contents in 'config' +func parseConfig(path string, config *Configuration) { + file, _ := os.Open(path) + var data map[string]interface{} + err := json.NewDecoder(file).Decode(&data) + if err != nil { + log.Panic("Failed to parse config:", err) + } + file.Close() + config.sites_dir = data["sites_dir"].(string) +} + diff --git a/deploy_error.go b/deploy_error.go new file mode 100644 index 0000000..c326768 --- /dev/null +++ b/deploy_error.go @@ -0,0 +1,15 @@ +package main + +// DeployError contains important information about an error if something went wrong. +type DeployError struct { + code int + where string + details string + command_output string +} + +// 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/go.mod b/go.mod index 0a07817..1251d98 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,6 @@ go 1.22.0 require ( github.com/gogs/git-module v1.8.3 // indirect github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/tools v0.19.0 // indirect ) diff --git a/go.sum b/go.sum index 5a32350..0f7de59 100644 --- a/go.sum +++ b/go.sum @@ -11,7 +11,22 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 6a93906..9404809 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,4 @@ +// package main is the main package for the LapisDeploy program package main import ( @@ -6,28 +7,11 @@ import ( "log" "net/http" "os" - "os/exec" - "strings" - "syscall" - - "github.com/gogs/git-module" ) -type Configuration struct { - sites_dir string -} +// Create a configuration struct var configuration = Configuration{} -type DeployError struct { - code int - where string - details string - command_output string -} -func newDeployError(code int, where string, details string, command_output string) DeployError { - return DeployError{ code: code, where: where, details: details } -} - // fileExists returns whether the given file or directory exists. func fileExists(path string) (bool, error) { _, err := os.Stat(path) @@ -36,60 +20,7 @@ func fileExists(path string) (bool, error) { return false, err } -// startServer attempts to start a Lapis server in the given repository. -func restartServer(name string) DeployError { - log.Printf("Restarting Lapis server on repository %s...", name) - - old_cwd, _ := os.Getwd() - defer syscall.Chdir(old_cwd) - syscall.Chdir(configuration.sites_dir+"/"+name) - - out, err := exec.Command("lapis", "build").CombinedOutput() - if err != nil { - return newDeployError(1, "restartServer", fmt.Sprintf("Failed to run 'lapis build' in repository '%s'", name), string(out)) - } - log.Printf("[lapis build] %s", out) - if !strings.Contains(string(out), "HUP") { - return newDeployError(1, "restartServer", "'lapis build' command returned unexpected value!", string(out)) - } - return DeployError{} -} - -// pullRepo attempts to pull or clone a repository using the given name and url -func pullRepo(url string, name string) DeployError { - exists, err := fileExists(configuration.sites_dir+"/"+name) - if err != nil { - return newDeployError(1, "fileExists", - fmt.Sprintf("Failed to check whether folder '%s' exists while pulling down repository '%s'!", name, name), "") - } - if !exists { - log.Printf("Cloning repository %s...", name) - if err = git.Clone(url, configuration.sites_dir+"/"+name); err != nil { - return newDeployError(1, "pullRepo", fmt.Sprintf("Failed to pull down repository '%s'", name), "") - } - } else { - log.Printf("Pulling down repository %s...", name) - repo,err := git.Open(configuration.sites_dir+"/"+name) - if err != nil { - return newDeployError(1, "pullRepo", fmt.Sprintf("Failed to open git repository '%s'", name), "") - } - repo.Pull() - } - return DeployError{} -} - -// parseConfig parses the JSON configuration file at 'path' and stores the contents in 'config' -func parseConfig(path string, config *Configuration) { - file, _ := os.Open(path) - var data map[string]interface{} - err := json.NewDecoder(file).Decode(&data) - if err != nil { - log.Panic("Failed to parse config:", err) - } - file.Close() - config.sites_dir = data["sites_dir"].(string) -} - +// 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"]) @@ -105,6 +36,7 @@ func handler(data map[string]interface{}) { } } +// main is the starting point of the program func main() { parseConfig("config.json", &configuration) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){ @@ -118,5 +50,5 @@ func main() { go handler(data) fmt.Fprint(w, "Received!") }) - log.Fatal(http.ListenAndServe(":7575", nil)) + go log.Fatal(http.ListenAndServe(":7575", nil)) } diff --git a/site.go b/site.go new file mode 100644 index 0000000..8ebfab2 --- /dev/null +++ b/site.go @@ -0,0 +1,55 @@ +// package main is the main package for the LapisDeploy program +package main + +import ( + "os/exec" + "strings" + "syscall" + "log" + "os" + "fmt" + + "github.com/gogs/git-module" +) + +// startServer attempts to start a Lapis server in the given repository. +func restartServer(name string) DeployError { + log.Printf("Restarting Lapis server on repository %s...", name) + + old_cwd, _ := os.Getwd() + defer syscall.Chdir(old_cwd) + syscall.Chdir(configuration.sites_dir+"/"+name) + + out, err := exec.Command("lapis", "build").CombinedOutput() + if err != nil { + return newDeployError(1, "restartServer", fmt.Sprintf("Failed to run 'lapis build' in repository '%s'", name), string(out)) + } + log.Printf("[lapis build] %s", out) + if !strings.Contains(string(out), "HUP") { + return newDeployError(1, "restartServer", "'lapis build' command returned unexpected value!", string(out)) + } + return DeployError{} +} + +// pullRepo attempts to pull or clone a repository using the given name and url +func pullRepo(url string, name string) DeployError { + exists, err := fileExists(configuration.sites_dir+"/"+name) + if err != nil { + return newDeployError(1, "fileExists", + fmt.Sprintf("Failed to check whether folder '%s' exists while pulling down repository '%s'!", name, name), "") + } + if !exists { + log.Printf("Cloning repository %s...", name) + if err = git.Clone(url, configuration.sites_dir+"/"+name); err != nil { + return newDeployError(1, "pullRepo", fmt.Sprintf("Failed to pull down repository '%s'", name), "") + } + } else { + log.Printf("Pulling down repository %s...", name) + repo,err := git.Open(configuration.sites_dir+"/"+name) + if err != nil { + return newDeployError(1, "pullRepo", fmt.Sprintf("Failed to open git repository '%s'", name), "") + } + repo.Pull() + } + return DeployError{} +}