Skip to content

Commit

Permalink
feat(jzero): init serverless feature
Browse files Browse the repository at this point in the history
feat(jzero): init serverless feature
  • Loading branch information
jaronnie committed Dec 2, 2024
1 parent 526cf0c commit a425aec
Show file tree
Hide file tree
Showing 6 changed files with 337 additions and 0 deletions.
70 changes: 70 additions & 0 deletions cmd/serverless.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright © 2024 jaronnie <[email protected]>
*/

package cmd

import (
"github.com/spf13/cobra"

"github.com/jzero-io/jzero/config"
"github.com/jzero-io/jzero/internal/serverless/serverlessbuild"
"github.com/jzero-io/jzero/internal/serverless/serverlessdelete"
"github.com/jzero-io/jzero/internal/serverless/serverlessnew"
)

// serverlessCmd represents the serverless command
var serverlessCmd = &cobra.Command{
Use: "serverless",
Short: "jzero serverless",
Long: `jzero serverless.`,
}

var serverlessNewCmd = &cobra.Command{
Use: "new",
Short: "jzero serverless new",
Long: `jzero serverless new.`,
RunE: func(cmd *cobra.Command, args []string) error {
if config.C.Serverless.New.Module == "" {
config.C.Serverless.New.Module = args[0]
}
return serverlessnew.Run(args)
},
Args: cobra.ExactArgs(1),
}

var serverlessBuildCmd = &cobra.Command{
Use: "build",
Short: "jzero serverless build",
Long: `jzero serverless build.`,
RunE: func(cmd *cobra.Command, args []string) error {
return serverlessbuild.Run()
},
}

var serverlessDeleteCmd = &cobra.Command{
Use: "delete",
Short: "jzero serverless delete",
Long: `jzero serverless delete.`,
RunE: func(cmd *cobra.Command, args []string) error {
return serverlessdelete.Run()
},
}

func init() {
rootCmd.AddCommand(serverlessCmd)
serverlessCmd.AddCommand(serverlessBuildCmd)
serverlessCmd.AddCommand(serverlessDeleteCmd)
serverlessCmd.AddCommand(serverlessNewCmd)

serverlessNewCmd.Flags().BoolP("core", "", false, "is core serverless")
serverlessNewCmd.Flags().StringP("module", "m", "", "set go module")
serverlessNewCmd.Flags().StringP("home", "", "", "set templates path")
serverlessNewCmd.Flags().StringP("remote", "r", "https://github.com/jzero-io/templates", "remote templates repo")
serverlessNewCmd.Flags().StringP("branch", "b", "", "remote templates repo branch")
serverlessNewCmd.Flags().StringP("frame", "", "api", "use frame")
serverlessNewCmd.Flags().StringP("local", "", "", "local templates")
serverlessNewCmd.Flags().StringP("style", "", "gozero", "The file naming format, see [https://github.com/zeromicro/go-zero/blob/master/tools/goctl/config/readme.md]")

serverlessDeleteCmd.Flags().StringSliceP("plugin", "p", nil, "plugin name")
}
22 changes: 22 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ type Config struct {
// upgrade command
Upgrade UpgradeConfig `mapstructure:"upgrade"`

// serverless command
Serverless ServerlessConfig `mapstructure:"serverless"`

/*
==============================command flags end=========================================
*/
}

type NewConfig struct {
Core bool `mapstructure:"core"`
Home string `mapstructure:"home"` // 新建项目使用的模板文件目录
Module string `mapstructure:"module"` // 新建的项目的 go module
Mono bool `mapstructure:"mono"` // 是否是 mono 项目(即在一个mod项目之下, 但该项目本身无 go.mod 文件)
Expand Down Expand Up @@ -195,6 +199,24 @@ type UpgradeConfig struct {
Channel string `mapstructure:"channel"`
}

type ServerlessConfig struct {
New NewConfig `mapstructure:"new"`
Delete ServerlessDeleteConfig `mapstructure:"delete"`
}

type ServerlessNewConfig struct {
Module string `mapstructure:"module"` // 新建的项目的 go module
Remote string `mapstructure:"remote"` // 远程仓库地址
Frame string `mapstructure:"frame"` // 使用 jzero 内置的框架
Branch string `mapstructure:"branch"` // 使用远程模板仓库的某个分支
Local string `mapstructure:"local"` // 使用本地模板与 branch 对应
Style string `mapstructure:"style"` // 项目代码风格
}

type ServerlessDeleteConfig struct {
Plugin []string `mapstructure:"plugin"`
}

type HooksConfig struct {
Before []string `mapstructure:"before"`
After []string `mapstructure:"after"`
Expand Down
50 changes: 50 additions & 0 deletions internal/serverless/serverless.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package serverless

import (
"os"
"path/filepath"

"github.com/jzero-io/jzero-contrib/modx"
)

type Plugin struct {
Path string
Module string
}

var PluginsTemplate = `package plugins
import (
"github.com/zeromicro/go-zero/rest"
{{range $v := .Plugins}}{{ $v.Path | base }} "{{ $v.Module }}/serverless"
{{end}}
)
func LoadPlugins(server *rest.Server) {
{{ range $v := .Plugins }}server.AddRoutes({{ $v.Path | base }}.Routes())
{{end}}
}`

func GetPlugins() ([]Plugin, error) {
wd, _ := os.Getwd()

var plugins []Plugin
dir, err := os.ReadDir("plugins")
if err != nil {
return nil, err
}
for _, p := range dir {
if p.IsDir() {
goMod, err := modx.GetGoMod(filepath.Join(wd, "plugins", p.Name()))
if err != nil {
return nil, err
}
plugins = append(plugins, Plugin{
Path: filepath.ToSlash(filepath.Join("plugins", p.Name())),
Module: goMod.Path,
})
}
}
return plugins, nil
}
73 changes: 73 additions & 0 deletions internal/serverless/serverlessbuild/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package serverlessbuild

import (
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/jzero-io/jzero-contrib/templatex"
"github.com/pkg/errors"
"golang.org/x/mod/modfile"

"github.com/jzero-io/jzero/internal/serverless"
)

func Run() error {
wd, _ := os.Getwd()

plugins, err := serverless.GetPlugins()
if err != nil {
return err
}

if _, err := os.Stat("go.work"); err == nil {
goWork, _ := os.ReadFile("go.work")
work, err := modfile.ParseWork("", goWork, nil)
if err != nil {
return err
}
for _, p := range plugins {
if !strings.HasPrefix(p.Module, "./") {
p.Path = "./" + p.Path
}
if err = work.DropUse(p.Path); err != nil {
return err
}
}
for _, p := range plugins {
if !strings.HasPrefix(p.Module, "./") {
p.Path = "./" + p.Path
}
if err = work.AddUse(p.Path, ""); err != nil {
return err
}
}
if err = os.WriteFile("go.work", modfile.Format(work.Syntax), 0o644); err != nil {
return err
}
} else {
initArgs := []string{"work", "init", "."}
for _, p := range plugins {
initArgs = append(initArgs, p.Path)
}
ec := exec.Command("go", initArgs...)
ec.Dir = wd
output, err := ec.CombinedOutput()
if err != nil {
return errors.Wrapf(err, "go work init meet error %s", string(output))
}
}

// write plugins/plugins.go
pluginsGoBytes, err := templatex.ParseTemplate(map[string]any{
"Plugins": plugins,
}, []byte(serverless.PluginsTemplate))
if err != nil {
return err
}
if err := os.WriteFile(filepath.Join("plugins", "plugins.go"), pluginsGoBytes, 0o644); err != nil {
return err
}
return nil
}
67 changes: 67 additions & 0 deletions internal/serverless/serverlessdelete/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package serverlessdelete

import (
"os"
"path/filepath"
"strings"

"github.com/jzero-io/jzero-contrib/templatex"
"github.com/samber/lo"
"golang.org/x/mod/modfile"

"github.com/jzero-io/jzero/config"
"github.com/jzero-io/jzero/internal/serverless"
"github.com/jzero-io/jzero/internal/serverless/serverlessbuild"
)

func Run() error {
plugins, err := serverless.GetPlugins()
if err != nil {
return err
}

for _, p := range config.C.Serverless.Delete.Plugin {
plugins = lo.Reject(plugins, func(item serverless.Plugin, index int) bool {
return item.Path != filepath.ToSlash(filepath.Join("plugins", p))
})
}

if _, err := os.Stat("go.work"); err == nil {
goWork, _ := os.ReadFile("go.work")
work, err := modfile.ParseWork("", goWork, nil)
if err != nil {
return err
}
for _, p := range plugins {
if !strings.HasPrefix(p.Module, "./") {
p.Path = "./" + p.Path
}
if err = work.DropUse(p.Path); err != nil {
return err
}
}
if err = os.WriteFile("go.work", modfile.Format(work.Syntax), 0o644); err != nil {
return err
}
}

for _, p := range plugins {
if _, err := os.Stat(p.Path); err == nil {
if err = os.RemoveAll(p.Path); err != nil {
return err
}
}
}

// write plugins/plugins.go
pluginsGoBytes, err := templatex.ParseTemplate(map[string]any{
"Plugins": plugins,
}, []byte(serverless.PluginsTemplate))
if err != nil {
return err
}
if err := os.WriteFile(filepath.Join("plugins", "plugins.go"), pluginsGoBytes, 0o644); err != nil {
return err
}
return serverlessbuild.Run()
}
55 changes: 55 additions & 0 deletions internal/serverless/serverlessnew/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package serverlessnew

import (
"os"
"path/filepath"

"golang.org/x/mod/modfile"

"github.com/jzero-io/jzero/config"
"github.com/jzero-io/jzero/internal/new"
"github.com/jzero-io/jzero/internal/serverless/serverlessbuild"
)

func Run(args []string) error {
config.C.New = config.NewConfig{
Home: config.C.Serverless.New.Home,
Module: config.C.Serverless.New.Module,
Output: filepath.Join("plugins", args[0]),
Remote: config.C.Serverless.New.Remote,
Frame: config.C.Serverless.New.Frame,
Branch: config.C.Serverless.New.Branch,
Local: config.C.Serverless.New.Local,
Style: config.C.Serverless.New.Style,
Features: []string{"serverless"},
}
if config.C.Serverless.New.Core {
config.C.New.Features = append(config.C.New.Features, "serverless_core")
config.C.New.Output = args[0]
}
err := new.Run(config.C, args[0])
if err != nil {
return err
}

if config.C.Serverless.New.Core {
return nil
}
path := "./" + "plugins/" + args[0]

if _, err := os.Stat("go.work"); err == nil {
goWork, _ := os.ReadFile("go.work")
work, err := modfile.ParseWork("", goWork, nil)
if err != nil {
return err
}
err = work.AddUse(path, "")
if err != nil {
return err
}
if err = os.WriteFile("go.work", modfile.Format(work.Syntax), 0o644); err != nil {
return err
}
}
return serverlessbuild.Run()
}

0 comments on commit a425aec

Please sign in to comment.