support deployments
This commit is contained in:
parent
8f600b21fb
commit
e4ae62ad7b
9 changed files with 140 additions and 15 deletions
|
@ -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).
|
- `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.
|
- `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`)
|
- `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
|
- `Logout`: logs the user out and returns to the login screen
|
||||||
|
|
||||||
## adapter interface
|
## 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)
|
- `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`
|
- `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)
|
- `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
|
## license
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ type BuildStatus struct {
|
||||||
Message string
|
Message string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeployStatus BuildStatus
|
||||||
|
type RevertStatus BuildStatus
|
||||||
|
|
||||||
type Page struct {
|
type Page struct {
|
||||||
Title string
|
Title string
|
||||||
Content string
|
Content string
|
||||||
|
@ -38,4 +41,6 @@ type Adapter interface {
|
||||||
SavePage(oldSlug, newSlug, title, content string) error
|
SavePage(oldSlug, newSlug, title, content string) error
|
||||||
DeletePage(slug string) error
|
DeletePage(slug string) error
|
||||||
Build(buildOptions map[BuildOption]string) BuildStatus
|
Build(buildOptions map[BuildOption]string) BuildStatus
|
||||||
|
Deploy() DeployStatus
|
||||||
|
Revert() RevertStatus
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (self *EurekaAdapter) Init(cfg *Config) {
|
||||||
|
|
||||||
err = self.readCfg()
|
err = self.readCfg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(err.Error())
|
fmt.Printf(err.Error())
|
||||||
panic("config.h is malformed!")
|
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 {
|
func (self *EurekaAdapter) readCfg() error {
|
||||||
configPath := filepath.Join(self.Root, "config.h")
|
configPath := filepath.Join(self.Root, "config.h")
|
||||||
_, err := os.Stat(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(
|
fileData := strings.Replace(
|
||||||
strings.Replace(
|
strings.Replace(
|
||||||
string(f[:]), "/* clang-format on */", "", -1),
|
string(f[:]), "/* clang-format on */", "", -1),
|
||||||
"/* clang-format off */", "", -1)
|
"/* clang-format off */", "", -1)
|
||||||
|
|
||||||
macros := strings.Split(fileData, "#define ")[1:]
|
macros := strings.Split(fileData, "#define ")[1:]
|
||||||
for _, macro := range macros {
|
for _, macro := range macros {
|
||||||
|
@ -370,8 +392,8 @@ func (self *EurekaAdapter) readCfg() error {
|
||||||
}
|
}
|
||||||
cfgType := "int"
|
cfgType := "int"
|
||||||
if strings.HasPrefix(k, "IS_") {
|
if strings.HasPrefix(k, "IS_") {
|
||||||
cfgType = "bool"
|
cfgType = "bool"
|
||||||
}
|
}
|
||||||
self.Config[ConfigOption{
|
self.Config[ConfigOption{
|
||||||
Name: k,
|
Name: k,
|
||||||
Type: cfgType,
|
Type: cfgType,
|
||||||
|
@ -389,11 +411,11 @@ func (self *EurekaAdapter) writeCfg() error {
|
||||||
|
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
f.WriteString("/* clang-format off */\n");
|
f.WriteString("/* clang-format off */\n")
|
||||||
for k, v := range self.Config {
|
for k, v := range self.Config {
|
||||||
switch k.Type {
|
switch k.Type {
|
||||||
case "int":
|
case "int":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "bool":
|
case "bool":
|
||||||
_, err := strconv.ParseInt(v, 10, 64)
|
_, err := strconv.ParseInt(v, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -418,6 +440,6 @@ func (self *EurekaAdapter) writeCfg() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.WriteString("/* clang-format on */\n");
|
f.WriteString("/* clang-format on */\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ package lfo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
|
||||||
core "hacklab.nilfm.cc/nirvash/archetype"
|
core "hacklab.nilfm.cc/nirvash/archetype"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
48
nirvash.go
48
nirvash.go
|
@ -1,14 +1,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
|
||||||
"net/http"
|
|
||||||
core "hacklab.nilfm.cc/nirvash/archetype"
|
core "hacklab.nilfm.cc/nirvash/archetype"
|
||||||
. "hacklab.nilfm.cc/nirvash/lfo"
|
. "hacklab.nilfm.cc/nirvash/lfo"
|
||||||
"hacklab.nilfm.cc/quartzgun/indentalUserDB"
|
"hacklab.nilfm.cc/quartzgun/indentalUserDB"
|
||||||
. "hacklab.nilfm.cc/quartzgun/middleware"
|
. "hacklab.nilfm.cc/quartzgun/middleware"
|
||||||
"hacklab.nilfm.cc/quartzgun/renderer"
|
"hacklab.nilfm.cc/quartzgun/renderer"
|
||||||
"hacklab.nilfm.cc/quartzgun/router"
|
"hacklab.nilfm.cc/quartzgun/router"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
@ -161,6 +161,50 @@ func main() {
|
||||||
udb,
|
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(
|
rtr.Post(
|
||||||
`/delete/(?P<Slug>\S+)`,
|
`/delete/(?P<Slug>\S+)`,
|
||||||
Defend(
|
Defend(
|
||||||
|
|
16
templates/deploy.html
Normal file
16
templates/deploy.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{{ $csrfToken := (.Context).Value "csrfToken" }}
|
||||||
|
|
||||||
|
{{ template "header" . }}
|
||||||
|
|
||||||
|
<h2>Deployment</h2>
|
||||||
|
|
||||||
|
<form class="build" method="POST" action="/deploy">
|
||||||
|
<input hidden name="csrfToken" value="{{$csrfToken}}"/>
|
||||||
|
<input type="submit" value="Deploy"/>
|
||||||
|
</form>
|
||||||
|
<form class="build" method="POST" action="/revert">
|
||||||
|
<input hidden name="csrfToken" value="{{$csrfToken}}"/>
|
||||||
|
<input type="submit" value="Revert"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{{ template "footer" . }}
|
17
templates/deployed.html
Normal file
17
templates/deployed.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{{ $status := ((.Context).Value "adapter").Deploy }}
|
||||||
|
|
||||||
|
{{ template "header" . }}
|
||||||
|
|
||||||
|
{{ if ne ($status).Success true }}
|
||||||
|
|
||||||
|
<h2>Deployment Error</h2>
|
||||||
|
<span class="adapter-error"><pre>{{($status).Message}}</pre></span>
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
|
||||||
|
<h2>Deployment Successful</h2>
|
||||||
|
<span class="adapter-success"><pre>{{($status).Message}}</pre></span>
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ template "footer" . }}
|
|
@ -14,8 +14,9 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/">Pages</a></li>
|
<li><a href="/">Pages</a></li>
|
||||||
<li><a href="/file-mgr">Files</a></li>
|
<li><a href="/file-mgr">Files</a></li>
|
||||||
<li><a href="/build">Build</a></li>
|
|
||||||
<li><a href="/config">Configuration</a></li>
|
<li><a href="/config">Configuration</a></li>
|
||||||
|
<li><a href="/build">Build</a></li>
|
||||||
|
<li><a href="/deploy">Deployment</a></li>
|
||||||
<li><a href="/logout">Logout</a></li>
|
<li><a href="/logout">Logout</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
17
templates/reverted.html
Normal file
17
templates/reverted.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{{ $status := ((.Context).Value "adapter").Revert }}
|
||||||
|
|
||||||
|
{{ template "header" . }}
|
||||||
|
|
||||||
|
{{ if ne ($status).Success true }}
|
||||||
|
|
||||||
|
<h2>Revert Error</h2>
|
||||||
|
<span class="adapter-error"><pre>{{($status).Message}}</pre></span>
|
||||||
|
|
||||||
|
{{ else }}
|
||||||
|
|
||||||
|
<h2>Revert Successful</h2>
|
||||||
|
<span class="adapter-success"><pre>{{($status).Message}}</pre></span>
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ template "footer" . }}
|
Loading…
Reference in a new issue