From e4ae62ad7b35eb5c0065ee470908e643b064eec2 Mon Sep 17 00:00:00 2001 From: Derek Stevens Date: Fri, 20 Oct 2023 22:46:37 -0600 Subject: [PATCH] support deployments --- README.md | 5 ++++- archetype/adapter.go | 5 +++++ archetype/eureka.go | 42 +++++++++++++++++++++++++++--------- lfo/middleware.go | 2 +- nirvash.go | 48 +++++++++++++++++++++++++++++++++++++++-- templates/deploy.html | 16 ++++++++++++++ templates/deployed.html | 17 +++++++++++++++ templates/header.html | 3 ++- templates/reverted.html | 17 +++++++++++++++ 9 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 templates/deploy.html create mode 100644 templates/deployed.html create mode 100644 templates/reverted.html diff --git a/README.md b/README.md index b596bb3..9a54be3 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,9 @@ Initially the user will be presented with the login screen; upon successful logi - `Pages`: the default page, shows a list of existing pages - clicking one enables editing that page; a button is also presented for adding a new page. Each `Adapter` will provide different formatting help and can allow editable slugs/URLs or not (eg, the `EurekaAdapter` builds slugs/URLs directly from the page title). - `Files`: provides an interface for managing statically hosted files. Files and directories can be added, moved, and deleted. -- `Build`: a simple form to build the site - build options configurable by `Adapter` are present under an accordion. - `Configuration`: interface to the configuration for the `Adapter`. Each `Adapter` provides its own configuration interface with associated data types (currently supported: `int`, `float`, `string`, and `multilinestring`) +- `Build`: a simple form to build the site - build options configurable by `Adapter` are present under an accordion. +- `Deploy`: a _very_ simple form to either deploy the site or revert the current state to the deployed state - `Logout`: logs the user out and returns to the login screen ## adapter interface @@ -61,6 +62,8 @@ The `Adapter` interface and associated data types can be found in the [adapter.g - `SavePage(oldSlug, newSlug, title, content string) error`: given all the proper arguments, save a page to the backing store (eg filesystem, db) - `DeletePage(slug string) error`: given a slug, delete the corresponding page source and possibly its generated HTML, depending on the `Adapter` - `Build(buildOptions map[string][]string) BuildStatus`: takes a map of build option names to their values and builds the site, returning a `BuildStatus` object containing the success or failure as a boolean and the detailed status (eg, the console ouptut of the build process) +- `Deploy() DeployStatus`: executes the deployment script and returns a `DeployStatus` object, analagous to a `BuildStatus` +- `Revert() RevertStatus`: executes the reversion script and returns a `RevertStatus` object, analagous to a `BuildStatus` ## license diff --git a/archetype/adapter.go b/archetype/adapter.go index 7b43da8..37328a0 100644 --- a/archetype/adapter.go +++ b/archetype/adapter.go @@ -9,6 +9,9 @@ type BuildStatus struct { Message string } +type DeployStatus BuildStatus +type RevertStatus BuildStatus + type Page struct { Title string Content string @@ -38,4 +41,6 @@ type Adapter interface { SavePage(oldSlug, newSlug, title, content string) error DeletePage(slug string) error Build(buildOptions map[BuildOption]string) BuildStatus + Deploy() DeployStatus + Revert() RevertStatus } diff --git a/archetype/eureka.go b/archetype/eureka.go index f60dd8d..4bfb2d0 100644 --- a/archetype/eureka.go +++ b/archetype/eureka.go @@ -29,7 +29,7 @@ func (self *EurekaAdapter) Init(cfg *Config) { err = self.readCfg() if err != nil { - fmt.Printf(err.Error()) + fmt.Printf(err.Error()) panic("config.h is malformed!") } } @@ -302,6 +302,28 @@ func (self *EurekaAdapter) Build(buildOptions map[BuildOption]string) BuildStatu } } +func (self *EurekaAdapter) Deploy() DeployStatus { + cmd := exec.Command("./deploy.sh") + cmd.Dir = self.Root + out, err := cmd.CombinedOutput() + + return DeployStatus{ + Success: err == nil, + Message: string(out), + } +} + +func (self *EurekaAdapter) Revert() RevertStatus { + cmd := exec.Command("./deploy.sh", "--resync") + cmd.Dir = self.Root + out, err := cmd.CombinedOutput() + + return RevertStatus{ + Success: err == nil, + Message: string(out), + } +} + func (self *EurekaAdapter) readCfg() error { configPath := filepath.Join(self.Root, "config.h") _, err := os.Stat(filepath.Join(self.Root, "config.h")) @@ -315,9 +337,9 @@ func (self *EurekaAdapter) readCfg() error { } fileData := strings.Replace( - strings.Replace( - string(f[:]), "/* clang-format on */", "", -1), - "/* clang-format off */", "", -1) + strings.Replace( + string(f[:]), "/* clang-format on */", "", -1), + "/* clang-format off */", "", -1) macros := strings.Split(fileData, "#define ")[1:] for _, macro := range macros { @@ -370,8 +392,8 @@ func (self *EurekaAdapter) readCfg() error { } cfgType := "int" if strings.HasPrefix(k, "IS_") { - cfgType = "bool" - } + cfgType = "bool" + } self.Config[ConfigOption{ Name: k, Type: cfgType, @@ -389,11 +411,11 @@ func (self *EurekaAdapter) writeCfg() error { defer f.Close() - f.WriteString("/* clang-format off */\n"); + f.WriteString("/* clang-format off */\n") for k, v := range self.Config { switch k.Type { case "int": - fallthrough + fallthrough case "bool": _, err := strconv.ParseInt(v, 10, 64) if err != nil { @@ -417,7 +439,7 @@ func (self *EurekaAdapter) writeCfg() error { fmt.Println("Unsupported config value type: " + k.Type) } } - - f.WriteString("/* clang-format on */\n"); + + f.WriteString("/* clang-format on */\n") return nil } diff --git a/lfo/middleware.go b/lfo/middleware.go index d8e8ac3..1fa00b0 100644 --- a/lfo/middleware.go +++ b/lfo/middleware.go @@ -2,8 +2,8 @@ package lfo import ( "context" - "net/http" core "hacklab.nilfm.cc/nirvash/archetype" + "net/http" "strings" ) diff --git a/nirvash.go b/nirvash.go index 4f46a8e..c00be60 100644 --- a/nirvash.go +++ b/nirvash.go @@ -1,14 +1,14 @@ package main import ( - "html/template" - "net/http" core "hacklab.nilfm.cc/nirvash/archetype" . "hacklab.nilfm.cc/nirvash/lfo" "hacklab.nilfm.cc/quartzgun/indentalUserDB" . "hacklab.nilfm.cc/quartzgun/middleware" "hacklab.nilfm.cc/quartzgun/renderer" "hacklab.nilfm.cc/quartzgun/router" + "html/template" + "net/http" "os" "path/filepath" ) @@ -161,6 +161,50 @@ func main() { udb, "/")) + rtr.Get( + `/deploy`, + Fortify( + Protected( + WithAdapter( + renderer.Template( + pathConcat(templateRoot, "deploy.html"), + pathConcat(templateRoot, "header.html"), + pathConcat(templateRoot, "footer.html")), + cfg.Adapter), + http.MethodGet, + udb, + "/login"))) + + rtr.Post( + `/deploy`, + Defend( + Protected( + WithAdapter( + renderer.Template( + pathConcat(templateRoot, "deployed.html"), + pathConcat(templateRoot, "header.html"), + pathConcat(templateRoot, "footer.html")), + cfg.Adapter), + http.MethodGet, + udb, + "/login"), + udb, + "/")) + rtr.Post( + `/revert`, + Defend( + Protected( + WithAdapter( + renderer.Template( + pathConcat(templateRoot, "reverted.html"), + pathConcat(templateRoot, "header.html"), + pathConcat(templateRoot, "footer.html")), + cfg.Adapter), + http.MethodGet, + udb, + "/login"), + udb, + "/")) rtr.Post( `/delete/(?P\S+)`, Defend( diff --git a/templates/deploy.html b/templates/deploy.html new file mode 100644 index 0000000..adc4462 --- /dev/null +++ b/templates/deploy.html @@ -0,0 +1,16 @@ +{{ $csrfToken := (.Context).Value "csrfToken" }} + +{{ template "header" . }} + +

Deployment

+ +
+ + +
+
+ + +
+ +{{ template "footer" . }} \ No newline at end of file diff --git a/templates/deployed.html b/templates/deployed.html new file mode 100644 index 0000000..f0c81ce --- /dev/null +++ b/templates/deployed.html @@ -0,0 +1,17 @@ +{{ $status := ((.Context).Value "adapter").Deploy }} + +{{ template "header" . }} + +{{ if ne ($status).Success true }} + +

Deployment Error

+
{{($status).Message}}
+ +{{ else }} + +

Deployment Successful

+
{{($status).Message}}
+ +{{ end }} + +{{ template "footer" . }} diff --git a/templates/header.html b/templates/header.html index 8b0f849..66750c0 100644 --- a/templates/header.html +++ b/templates/header.html @@ -14,8 +14,9 @@ diff --git a/templates/reverted.html b/templates/reverted.html new file mode 100644 index 0000000..00b36cd --- /dev/null +++ b/templates/reverted.html @@ -0,0 +1,17 @@ +{{ $status := ((.Context).Value "adapter").Revert }} + +{{ template "header" . }} + +{{ if ne ($status).Success true }} + +

Revert Error

+
{{($status).Message}}
+ +{{ else }} + +

Revert Successful

+
{{($status).Message}}
+ +{{ end }} + +{{ template "footer" . }}