feat(init): continue on template
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Matthieu 'JP' DERASSE 2022-08-10 15:40:37 +00:00
parent cf7901890c
commit 05ecb05132
Signed by: mderasse
GPG Key ID: 55141C777B16A705
17 changed files with 325 additions and 24 deletions

View File

@ -1,13 +0,0 @@
package base
import (
"github.com/juju/errors"
"git.home.m-and-m.ovh/mderasse/gouick/helpers"
"git.home.m-and-m.ovh/mderasse/gouick/models"
)
// GenerateMakefile will generate makefile based on the given config.
func (a APIType) GenerateMakefile(path string, config *models.Config) error {
return errors.NotImplementedf("%s not implemented for %s", helpers.GetCurrentFuncName(), a.GetName())
}

View File

@ -16,7 +16,11 @@ var standardDirectories = []string{
"cmd",
"models",
"pkg",
"pkg/api",
"pkg/helper",
"pkg/transform",
"restapi",
"restapi/operations",
"testdata",
}

View File

@ -20,13 +20,38 @@ func (a APIType) CreateProjectSkeleton(path string, config *models.Config) error
}
// Generate Makefile
err = a.GenerateMakefile(path, config)
err = a.generateMakefile(path, config)
if err != nil {
log.Error("Fail to generate Makefile")
return errors.Trace(err)
}
// Generate Readme
// Generate api.yaml
err = a.generateReadme(path, config)
if err != nil {
log.Error("Fail to generate Readme.md")
return errors.Trace(err)
}
// Generate api yaml files
err = a.generateAPIYamls(path, config)
if err != nil {
log.Error("Fail to generate API Yaml files")
return errors.Trace(err)
}
// init Go Module
err = a.initializeGoModule(path, config)
if err != nil {
log.Error("Fail to initialize Go Module")
return errors.Trace(err)
}
// Launch Go Swagger
err = a.executeGoSwagger(path, config)
if err != nil {
log.Error("Fail to Execute Go Swagger")
return errors.Trace(err)
}
return nil
}

View File

@ -0,0 +1,59 @@
package go_swagger
import (
"os"
"os/exec"
"path/filepath"
"github.com/juju/errors"
"git.home.m-and-m.ovh/mderasse/gouick/helpers"
"git.home.m-and-m.ovh/mderasse/gouick/models"
log "github.com/sirupsen/logrus"
)
// executeGoSwagger will merge api yaml files and launch go-swagger generator.
func (a APIType) executeGoSwagger(path string, config *models.Config) error {
log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName())
// making sure that we are in the project directory
if err := os.Chdir(path); err != nil {
log.Error("Fail to move to the path")
return errors.Trace(err)
}
// merge api files.
// TODO: use filepath.Glob and avoid an ugly bin sh.
cmd := exec.Command("/bin/sh", "-c", "swagger mixin --format=yaml --output=api-temp.yaml api.yaml api/*")
output, err := cmd.CombinedOutput()
if err != nil {
log.Error("fail to execute 'swagger mixin --format=yaml --output=api-temp.yaml api.yaml api/*'")
return errors.Trace(err)
}
log.Debugf("'swagger mixin --format=yaml --output=api-temp.yaml api.yaml api/*' returned the following output: %s", string(output))
// cleanup some directory to avoid issues.
for _, directory := range []string{"models", "restapi/operations"} {
err := helpers.RemoveDirectoryContent(filepath.Join(path, directory))
if err != nil {
log.Errorf("fail to delete content of directory '%s'", directory)
return errors.Trace(err)
}
}
// generate server files
cmd = exec.Command("swagger", "generate", "server", "--spec=api-temp.yaml")
output, err = cmd.CombinedOutput()
if err != nil {
log.Error("fail to execute 'swagger generate server --spec=api-temp.yaml'")
return errors.Trace(err)
}
log.Debugf("'swagger generate server --spec=api-temp.yaml' returned the following output: %s", string(output))
// TODO: execute 'go get ./...'
return nil
}

View File

@ -0,0 +1,60 @@
package go_swagger
import (
"path/filepath"
"github.com/juju/errors"
"git.home.m-and-m.ovh/mderasse/gouick/helpers"
"git.home.m-and-m.ovh/mderasse/gouick/models"
log "github.com/sirupsen/logrus"
)
type apiYamlTemplate struct {
ProjectDescription string
ProjectName string
ProjectOwner string
}
// generateAPIYamls will generate a readme based on the given config.
// Launched only at project init.
func (a APIType) generateAPIYamls(path string, config *models.Config) error {
log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName())
type templateFileStruct struct {
savePath string
templatePath string
}
templateFileList := []templateFileStruct{
{
savePath: filepath.Join(path, "api.yaml"),
templatePath: filepath.Join(templateDirectory, "api.yaml.tmpl"),
},
{
savePath: filepath.Join(path, "api/001-general.yaml"),
templatePath: filepath.Join(templateDirectory, "api/001-general.yaml.tmpl"),
},
{
savePath: filepath.Join(path, "api/001-monitoring.yaml"),
templatePath: filepath.Join(templateDirectory, "api/002-monitoring.yaml.tmpl"),
},
}
data := apiYamlTemplate{
ProjectDescription: config.ProjectDescription,
ProjectName: config.ProjectName,
ProjectOwner: config.ProjectOwner,
}
for _, templateFile := range templateFileList {
err := helpers.WriteTemplate(templateFile.templatePath, templateFile.savePath, data)
if err != nil {
return errors.Trace(err)
}
}
return nil
}

View File

@ -12,18 +12,19 @@ import (
log "github.com/sirupsen/logrus"
)
type makefile struct {
type makefileTemplate struct {
AppNameKebabCase string
}
// GenerateMakefile will generate makefile based on the given config.
func (a APIType) GenerateMakefile(path string, config *models.Config) error {
// generateMakefile will generate makefile based on the given config.
// Launched only at project init or on force.
func (a APIType) generateMakefile(path string, config *models.Config) error {
log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName())
templatePath := filepath.Join(templateDirectory, "Makefile.tmpl")
savePath := filepath.Join(path, "Makefile")
data := makefile{
data := makefileTemplate{
AppNameKebabCase: strcase.ToKebab(config.ProjectName),
}

View File

@ -0,0 +1,38 @@
package go_swagger
import (
"path/filepath"
"github.com/juju/errors"
"git.home.m-and-m.ovh/mderasse/gouick/helpers"
"git.home.m-and-m.ovh/mderasse/gouick/models"
log "github.com/sirupsen/logrus"
)
type readmeTemplate struct {
ProjectDescription string
ProjectName string
}
// generateReadme will generate a readme based on the given config.
// Launched only at project init.
func (a APIType) generateReadme(path string, config *models.Config) error {
log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName())
templatePath := filepath.Join(templateDirectory, "Readme.md.tmpl")
savePath := filepath.Join(path, "Readme.md")
data := readmeTemplate{
ProjectDescription: config.ProjectDescription,
ProjectName: config.ProjectName,
}
err := helpers.WriteTemplate(templatePath, savePath, data)
if err != nil {
return errors.Trace(err)
}
return nil
}

View File

@ -32,8 +32,8 @@ func (a APIType) GetInitializeUserInput(params *models.Config) (*models.Config,
if !isInGoPath {
log.Debug("We are not in GoPath, ask extra info")
goModulePath := helpers.StringInput()
log.Info("Go Module name:")
params.ModuleName = &goModulePath
log.Info("Go Module path:")
params.ModulePath = &goModulePath
}
log.Info("Do you want to enable database models auto generation ?")

View File

@ -0,0 +1,39 @@
package go_swagger
import (
"os"
"os/exec"
"github.com/juju/errors"
"git.home.m-and-m.ovh/mderasse/gouick/helpers"
"git.home.m-and-m.ovh/mderasse/gouick/models"
log "github.com/sirupsen/logrus"
)
// initializeGoModule will launch a go mod init.
func (a APIType) initializeGoModule(path string, config *models.Config) error {
log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName())
if err := os.Chdir(path); err != nil {
log.Error("Fail to move to the path")
return errors.Trace(err)
}
modulePath := ""
if config.ModulePath != nil {
modulePath = *config.ModulePath
}
cmd := exec.Command("go", "mod", "init", modulePath)
output, err := cmd.CombinedOutput()
if err != nil {
log.Errorf("fail to execute go mod init %s", modulePath)
return errors.Trace(err)
}
log.Debugf("go mod init %s returned the following output: %s", modulePath, string(output))
return nil
}

View File

@ -6,7 +6,6 @@ import "git.home.m-and-m.ovh/mderasse/gouick/models"
type APITypeInterface interface {
CheckInitialize() error
CreateProjectSkeleton(path string, config *models.Config) error
GenerateMakefile(path string, config *models.Config) error
GetInitializeUserInput(params *models.Config) (*models.Config, error)
GetName() models.APITypeName
}

View File

@ -6,7 +6,7 @@ type Config struct {
ProjectDescription string `yaml:"project_description"`
ProjectOwner string `yaml:"project_owner"`
ProjectType APITypeName `yaml:"project_type"`
ModuleName *string `yaml:"module_name"`
ModulePath *string `yaml:"module_name"`
Features FeaturesConfig `yaml:"features"`
}

View File

@ -3,7 +3,7 @@ package models
// UserInputParams is a struct containing all fields that can be useful for project generation.
type UserInputParams struct {
DatabaseModels bool
GoModuleName *string
GoModulePath *string
ProjectDescription string
ProjectDirectory string
ProjectName string

View File

@ -0,0 +1,3 @@
# {{ .ProjectName }}
{{ .ProjectDescription }}

View File

@ -0,0 +1,13 @@
---
swagger: "2.0"
info:
version: "1.0"
title: "{{ .ProjectName }}"
description: "{{ .ProjectDescription }}"
contact:
email: "{{ .ProjectOwner }}"
consumes:
- "application/json"
produces:
- "application/json"
basePath: "/"

View File

@ -0,0 +1,25 @@
---
definitions:
#
# GENERAL TYPEs
#
Error:
type: object
properties:
code:
type: integer
format: int64
message:
type: string
Metadata:
type: object
required:
- this
- total
properties:
total:
type: integer
format: int64
this:
type: integer
format: int64

View File

@ -0,0 +1,48 @@
---
tags:
- name: Monitoring
description: Monitoring routes
definitions:
MonPing:
type: object
properties:
status:
type: object
x-nullable: true
properties:
database:
type: boolean
description: State of the database
application:
type: boolean
description: State of the application
details:
type: object
x-nullable: true
properties:
app_version:
type: string
description: Application version
git_hash:
type: string
description: Git hash of the last commit
paths:
#
# SECTION : MONITORING
#
/mon/ping:
get:
tags:
- Monitoring
summary: Health check
description: Return Health status of the app with additionnal info such as the version
operationId: getMonPing
responses:
200:
description: Health OK
schema:
$ref: "#/definitions/MonPing"
default:
description: Default error message
schema:
$ref: "#/definitions/Error"