-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new command discover to generate goac configs file
- Loading branch information
Showing
3 changed files
with
507 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package cmd | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/kperreau/goac/pkg/project" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
// discoverCmd represents the discover command | ||
var discoverCmd = &cobra.Command{ | ||
Use: "discover", | ||
Example: "goac discover", | ||
Short: "List discovered projects", | ||
Long: `Use it to discovering projects and create default config files.`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
if len(args) > 0 { | ||
return errors.New("bad args number") | ||
} | ||
|
||
err := project.Discover(&project.DiscoverOptions{ | ||
Force: force, | ||
Create: create, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
var create bool | ||
|
||
func init() { | ||
rootCmd.AddCommand(discoverCmd) | ||
|
||
discoverCmd.Flags().BoolVarP(&force, "force", "f", false, "Force creation file if already exist") | ||
discoverCmd.Flags().BoolVarP(&create, "create", "c", false, "Create project config files") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
package project | ||
|
||
import ( | ||
"fmt" | ||
"go/ast" | ||
"go/parser" | ||
"go/token" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/fatih/color" | ||
"github.com/kperreau/goac/pkg/printer" | ||
|
||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
var PahToSearch = "." | ||
|
||
type DiscoverOptions struct { | ||
Force bool | ||
Create bool | ||
} | ||
|
||
func Discover(opts *DiscoverOptions) error { | ||
filesPath, err := searchProjects() | ||
if err != nil { | ||
return fmt.Errorf("failed to discover projects: %w", err) | ||
} | ||
|
||
printer.Printf("Discovered %s potential projects\n", color.YellowString("%d", len(filesPath))) | ||
for _, filePath := range filesPath { | ||
path := filepath.Clean(strings.Replace(filePath, "main.go", "", 1)) | ||
name := pathToName(path) | ||
if !opts.Create { | ||
printer.Printf("%s %s %s\n", color.BlueString(name), color.YellowString("=>"), path) | ||
} else { | ||
statusResult, err := createConfigFile(filepath.Join(path, configFileName), name, opts.Force) | ||
if err != nil { | ||
printer.Printf("Failed to create project %s %s %s | Error: %s\n", color.BlueString(name), color.YellowString("=>"), path, color.RedString(err.Error())) | ||
continue | ||
} | ||
|
||
printer.Printf("%s %s %s [%s]\n", color.BlueString(name), color.YellowString("=>"), path, printDiscoverStatus(statusResult)) | ||
} | ||
} | ||
|
||
return err | ||
} | ||
|
||
func searchProjects() ([]string, error) { | ||
// create tokens | ||
fset := token.NewFileSet() | ||
|
||
var dirs []string | ||
err := filepath.Walk(PahToSearch, func(path string, info os.FileInfo, err error) error { | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if strings.HasSuffix(path, ".go") { | ||
// Parse go file | ||
f, parseErr := parser.ParseFile(fset, path, nil, 0) | ||
if parseErr != nil { | ||
fmt.Println(parseErr) | ||
return nil | ||
} | ||
|
||
// Check if main package w/ main func exist | ||
if f.Name.Name == "main" { | ||
for _, decl := range f.Decls { | ||
if funcDecl, ok := decl.(*ast.FuncDecl); ok { | ||
if funcDecl.Name.Name == "main" { | ||
dirs = append(dirs, path) | ||
break | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return nil | ||
}) | ||
|
||
return dirs, err | ||
} | ||
|
||
func pathToName(path string) string { | ||
name := strings.ReplaceAll(path, "/", "-") | ||
|
||
if name == "" || name == "." { | ||
dir, err := os.Getwd() | ||
if err != nil { | ||
return "unknown" | ||
} | ||
return filepath.Base(dir) | ||
} | ||
|
||
return name | ||
} | ||
|
||
type status string | ||
|
||
const ( | ||
statusCreated status = "created" | ||
statusAlreadyExist status = "already-exist" | ||
statusFailed status = "failed" | ||
) | ||
|
||
func (s status) String() string { return string(s) } | ||
|
||
func createConfigFile(path string, name string, force bool) (status, error) { | ||
_, err := os.Stat(path) | ||
fileExist := !os.IsNotExist(err) | ||
|
||
if fileExist && !force { | ||
return statusAlreadyExist, nil | ||
} | ||
|
||
file, err := os.Create(path) | ||
if err != nil { | ||
return statusFailed, err | ||
} | ||
defer func() { _ = file.Close() }() | ||
|
||
// default project config | ||
config := Project{ | ||
Version: "1.0", | ||
Name: name, | ||
Target: map[Target]*TargetConfig{ | ||
TargetBuild: { | ||
Exec: &Exec{ | ||
CMD: "go", | ||
Params: []string{ | ||
"build", | ||
"-ldflags=-s -w", | ||
"-o", | ||
"{{project-path}}/{{project-name}}", | ||
"{{project-path}}", | ||
}, | ||
}, | ||
}, | ||
TargetBuildImage: { | ||
Envs: []Env{ | ||
{Key: "PROJECT_PATH", Value: "{{project-path}}"}, | ||
}, | ||
Exec: &Exec{ | ||
CMD: "./_scripts/build-image.sh", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
// Encoder la structure Project en YAML et écrire dans le fichier | ||
encoder := yaml.NewEncoder(file) | ||
encoder.SetIndent(2) | ||
if err := encoder.Encode(config); err != nil { | ||
return statusFailed, err | ||
} | ||
_ = encoder.Close() | ||
|
||
return statusCreated, nil | ||
} | ||
|
||
func printDiscoverStatus(s status) string { | ||
switch s { | ||
case statusCreated: | ||
return color.GreenString("Created") | ||
case statusAlreadyExist: | ||
return color.HiBlackString("Already Exist") | ||
} | ||
return color.RedString("Failed") | ||
} |
Oops, something went wrong.