✨ CLI Deploy
This commit is contained in:
@ -8,14 +8,17 @@ import (
|
||||
"code.smartsheep.studio/goatworks/roadsign/pkg/sign"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func doPublish(ctx *fiber.Ctx) error {
|
||||
func doPublish(c *fiber.Ctx) error {
|
||||
var upstream *sign.UpstreamConfig
|
||||
var site *sign.SiteConfig
|
||||
for _, item := range sign.App.Sites {
|
||||
if item.ID == ctx.Params("site") {
|
||||
if item.ID == c.Params("site") {
|
||||
site = item
|
||||
for _, stream := range item.Upstreams {
|
||||
if stream.ID == ctx.Params("upstream") {
|
||||
if stream.ID == c.Params("upstream") {
|
||||
upstream = stream
|
||||
break
|
||||
}
|
||||
@ -30,35 +33,39 @@ func doPublish(ctx *fiber.Ctx) error {
|
||||
return fiber.ErrUnprocessableEntity
|
||||
}
|
||||
|
||||
for _, process := range site.Processes {
|
||||
process.StopProcess()
|
||||
}
|
||||
|
||||
workdir, _ := upstream.GetRawURI()
|
||||
|
||||
if ctx.Query("overwrite", "yes") == "yes" {
|
||||
if c.Query("overwrite", "yes") == "yes" {
|
||||
files, _ := filepath.Glob(filepath.Join(workdir, "*"))
|
||||
for _, file := range files {
|
||||
_ = os.Remove(file)
|
||||
}
|
||||
}
|
||||
|
||||
if form, err := ctx.MultipartForm(); err == nil {
|
||||
if form, err := c.MultipartForm(); err == nil {
|
||||
files := form.File["attachments"]
|
||||
for _, file := range files {
|
||||
mimetype := file.Header["Content-Type"][0]
|
||||
mimetype := lo.Ternary(len(c.Query("mimetype")) > 0, c.Query("mimetype"), file.Header["Content-Type"][0])
|
||||
switch mimetype {
|
||||
case "application/zip":
|
||||
dst := filepath.Join(os.TempDir(), uuid.NewString()+".zip")
|
||||
if err := ctx.SaveFile(file, dst); err != nil {
|
||||
if err := c.SaveFile(file, dst); err != nil {
|
||||
return err
|
||||
} else {
|
||||
_ = filesystem.Unzip(dst, workdir)
|
||||
}
|
||||
default:
|
||||
dst := filepath.Join(workdir, file.Filename)
|
||||
if err := ctx.SaveFile(file, dst); err != nil {
|
||||
if err := c.SaveFile(file, dst); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ctx.SendStatus(fiber.StatusOK)
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
17
pkg/cmd/rds/conn/directory.go
Normal file
17
pkg/cmd/rds/conn/directory.go
Normal file
@ -0,0 +1,17 @@
|
||||
package conn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func GetConnection(id string) (CliConnection, bool) {
|
||||
var servers []CliConnection
|
||||
raw, _ := json.Marshal(viper.Get("servers"))
|
||||
_ = json.Unmarshal(raw, &servers)
|
||||
return lo.Find(servers, func(item CliConnection) bool {
|
||||
return item.ID == id
|
||||
})
|
||||
}
|
85
pkg/cmd/rds/deploy/commands.go
Normal file
85
pkg/cmd/rds/deploy/commands.go
Normal file
@ -0,0 +1,85 @@
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"code.smartsheep.studio/goatworks/roadsign/pkg/cmd/rds/conn"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
"github.com/mholt/archiver/v4"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var DeployCommands = []*cli.Command{
|
||||
{
|
||||
Name: "deploy",
|
||||
Aliases: []string{"dp"},
|
||||
ArgsUsage: "<server> <site> <upstream> [path]",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
if ctx.Args().Len() < 3 {
|
||||
return fmt.Errorf("must have three arguments: <server> <site> <upstream> [path]")
|
||||
}
|
||||
|
||||
server, ok := conn.GetConnection(ctx.Args().Get(0))
|
||||
if !ok {
|
||||
return fmt.Errorf("server was not found, use \"rds connect\" add one first")
|
||||
}
|
||||
|
||||
// Prepare file to upload
|
||||
log.Info().Msg("Preparing file to upload, please stand by...")
|
||||
|
||||
filelist, err := archiver.FilesFromDisk(nil, map[string]string{
|
||||
lo.Ternary(ctx.Args().Len() > 3, ctx.Args().Get(4), "."): "",
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare file: %q", err)
|
||||
}
|
||||
|
||||
workdir, _ := os.Getwd()
|
||||
filename := filepath.Join(workdir, fmt.Sprintf("rds-deploy-cache-%s.zip", uuid.NewString()))
|
||||
out, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare file: %q", err)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
if err := (archiver.Zip{}).Archive(context.Background(), out, filelist); err != nil {
|
||||
return fmt.Errorf("failed to prepare file: %q", err)
|
||||
}
|
||||
|
||||
// Send request
|
||||
log.Info().Msg("Now publishing to remote server...")
|
||||
|
||||
url := fmt.Sprintf("/webhooks/publish/%s/%s?mimetype=%s", ctx.Args().Get(1), ctx.Args().Get(2), "application/zip")
|
||||
client := fiber.Put(server.Url+url).
|
||||
SendFile(filename, "attachments").
|
||||
MultipartForm(nil).
|
||||
BasicAuth("RoadSign CLI", server.Credential)
|
||||
|
||||
var mistake error
|
||||
if status, _, err := client.Bytes(); len(err) > 0 {
|
||||
mistake = fmt.Errorf("failed to publish to remote: %q", err)
|
||||
} else if status != 200 {
|
||||
mistake = fmt.Errorf("server rejected request, may cause by invalid credential")
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
log.Info().Msg("Cleaning up...")
|
||||
os.Remove(filename)
|
||||
|
||||
if mistake != nil {
|
||||
return mistake
|
||||
}
|
||||
|
||||
// Well done!
|
||||
log.Info().Msg("Well done! Your site is successfully published! 🎉")
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
roadsign "code.smartsheep.studio/goatworks/roadsign/pkg"
|
||||
"code.smartsheep.studio/goatworks/roadsign/pkg/cmd/rds/conn"
|
||||
"code.smartsheep.studio/goatworks/roadsign/pkg/cmd/rds/deploy"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
@ -37,7 +38,7 @@ func main() {
|
||||
Name: "RoadSign CLI",
|
||||
Version: roadsign.AppVersion,
|
||||
Suggest: true,
|
||||
Commands: append([]*cli.Command{}, conn.CliCommands...),
|
||||
Commands: append(append([]*cli.Command{}, conn.CliCommands...), deploy.DeployCommands...),
|
||||
}
|
||||
|
||||
// Run CLI
|
||||
|
@ -2,11 +2,9 @@ package filesystem
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Unzip(src, dest string) error {
|
||||
@ -35,10 +33,6 @@ func Unzip(src, dest string) error {
|
||||
|
||||
path := filepath.Join(dest, f.Name)
|
||||
|
||||
if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) {
|
||||
return fmt.Errorf("illegal file path: %s", path)
|
||||
}
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
_ = os.MkdirAll(path, f.Mode())
|
||||
} else {
|
||||
|
@ -68,5 +68,9 @@ func (v *ProcessConfig) StartProcess() error {
|
||||
}
|
||||
|
||||
func (v *ProcessConfig) StopProcess() error {
|
||||
return v.Cmd.Process.Signal(os.Interrupt)
|
||||
if v.Cmd != nil && v.Cmd.Process != nil {
|
||||
return v.Cmd.Process.Signal(os.Interrupt)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user