diff --git a/.gitmodules b/.gitmodules index 3f9ecbcf9..91a2e79e9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,4 +25,7 @@ [submodule "core/templates/compage-template-typescript"] path = core/templates/compage-template-typescript url = https://github.com/intelops/compage-template-typescript.git - branch = template-v1 \ No newline at end of file + branch = template-v1 +[submodule "core/templates/compage-template-dotnet"] + path = core/templates/compage-template-dotnet + url = https://github.com/intelops/compage-template-dotnet.git diff --git a/app/README.md b/app/README.md index 127a0212c..a8b0a385b 100644 --- a/app/README.md +++ b/app/README.md @@ -5,7 +5,7 @@ related details. - It's an Express.js based REST server and gRPC client to a core component. - The sqlite is used as a database for development. To use cassandra, you need to set the following environment - variables in your terminal along with a `environment DB_TYPE='cassandra'`. + variables in your terminal along with a `export DB_TYPE='cassandra'`. #### Use cassandra as a database diff --git a/app/src/integrations/simple-git/common.ts b/app/src/integrations/simple-git/common.ts index 34944dee4..8312faff9 100644 --- a/app/src/integrations/simple-git/common.ts +++ b/app/src/integrations/simple-git/common.ts @@ -42,19 +42,22 @@ export const gitOperations = async (git: SimpleGit, repositoryBranch?: string, p branchName = repositoryBranch + '-' + projectVersion; } - // checkoutLocalBranch checks out local branch with name supplied - await git.checkoutLocalBranch(branchName) - .then( - (success: any) => { - Logger.debug(`git checkoutLocalBranch succeeded: ${JSON.stringify(success)}`); - }, (failure: any) => { - Logger.debug(`git checkoutLocalBranch failed: ${JSON.stringify(failure)}`); - error = `git checkoutLocalBranch failed: ${JSON.stringify(failure)}`; - }); - if (error.length > 0) { - return error; + const branchSummary = await git.branch(); + const isBranchPresent = branchSummary?.branches[branchName]; + if (!isBranchPresent) { + // checkoutLocalBranch checks out local branch with name supplied + await git.checkoutLocalBranch(branchName) + .then( + (success: any) => { + Logger.debug(`git checkoutLocalBranch succeeded: ${JSON.stringify(success)}`); + }, (failure: any) => { + Logger.debug(`git checkoutLocalBranch failed: ${JSON.stringify(failure)}`); + error = `git checkoutLocalBranch failed: ${JSON.stringify(failure)}`; + }); + if (error.length > 0) { + return error; + } } - // Finally, push to online repository await git.push('origin', branchName, {'--force': null}) .then((success: any) => { diff --git a/core/README.md b/core/README.md index 65cc6ec21..b289d6ded 100644 --- a/core/README.md +++ b/core/README.md @@ -4,7 +4,7 @@ - It's a Golang based gRPC server to app component. #### How to run this component? -- Navigate to core directory [cd app] from root directory of compage. +- Navigate to core directory [cd core] from root directory of compage. - Fire below set of commands in sequence to initialize the git submodules. - `git submodule init` - `git submodule update --remote` diff --git a/core/internal/handlers/projects.go b/core/internal/handlers/projects.go index c978932e5..72a29602b 100644 --- a/core/internal/handlers/projects.go +++ b/core/internal/handlers/projects.go @@ -7,6 +7,7 @@ import ( "github.com/intelops/compage/core/internal/integrations/deepsource" "github.com/intelops/compage/core/internal/integrations/readme" "github.com/intelops/compage/core/internal/languages" + "github.com/intelops/compage/core/internal/languages/dotnet" "github.com/intelops/compage/core/internal/languages/golang" "github.com/intelops/compage/core/internal/languages/java" "github.com/intelops/compage/core/internal/languages/javascript" @@ -135,6 +136,13 @@ func runLanguageProcess(languageNode *languages.LanguageNode, languageCtx contex log.Debugf("err : %s", err1) return err1 } + } else if languageNode.Language == languages.DotNet { + // add values(LanguageNode and configs from coreProject) to context. + dotnetCtx := dotnet.AddValuesToContext(languageCtx) + if err1 := dotnet.Process(dotnetCtx); err1 != nil { + log.Debugf("err : %s", err1) + return err1 + } } return nil } diff --git a/core/internal/languages/dotnet/context.go b/core/internal/languages/dotnet/context.go new file mode 100644 index 000000000..a3b07e026 --- /dev/null +++ b/core/internal/languages/dotnet/context.go @@ -0,0 +1,33 @@ +package dotnet + +import ( + "context" + "github.com/intelops/compage/core/internal/languages" +) + +type contextKey string + +func (c contextKey) String() string { + return string(c) +} + +var ( + contextKeyDotNetContextVars = contextKey("DotNetContextVars") +) + +type DotNetValues struct { + Values *languages.Values + LDotNetLangNode *LDotNetLangNode +} + +func AddValuesToContext(ctx context.Context) context.Context { + values := ctx.Value(languages.ContextKeyLanguageContextVars).(languages.Values) + v := DotNetValues{ + Values: &values, + LDotNetLangNode: &LDotNetLangNode{ + LanguageNode: values.LanguageNode, + }, + } + + return context.WithValue(ctx, contextKeyDotNetContextVars, v) +} diff --git a/core/internal/languages/dotnet/frameworks/dotnet-mvc-framework/copier.go b/core/internal/languages/dotnet/frameworks/dotnet-mvc-framework/copier.go new file mode 100644 index 000000000..79218bdd6 --- /dev/null +++ b/core/internal/languages/dotnet/frameworks/dotnet-mvc-framework/copier.go @@ -0,0 +1,88 @@ +package dotnet_mvc_framework + +import ( + "github.com/gertd/go-pluralize" + "github.com/intelops/compage/core/internal/languages/executor" + log "github.com/sirupsen/logrus" + + "strings" + + "github.com/intelops/compage/core/internal/utils" +) + +const RestServerPath = "/pkg/rest/server" + +// Copier Language specific *Copier +type Copier struct { + NodeDirectoryName string + TemplatesRootPath string + Data map[string]interface{} + IsRestServer bool + RestServerPort string + PluralizeClient *pluralize.Client +} + +func NewCopier(gitPlatformURL, gitPlatformUserName, gitRepositoryName, nodeName, nodeDirectoryName, templatesRootPath string) *Copier { + + pluralizeClient := pluralize.NewClient() + + // populate map to replace templates + data := map[string]interface{}{ + "GitRepositoryName": gitRepositoryName, + "NodeName": strings.ToLower(nodeName), + "GitPlatformUserName": gitPlatformUserName, + "GitPlatformURL": strings.Replace(gitPlatformURL, "https://", "", -1), + } + + return &Copier{ + TemplatesRootPath: templatesRootPath, + NodeDirectoryName: nodeDirectoryName, + Data: data, + PluralizeClient: pluralizeClient, + } +} + +// createRestServerDirectories creates rest server directories. +func (c *Copier) createRestServerDirectories() error { + rootDirectory := c.NodeDirectoryName + if err := utils.CreateDirectories(rootDirectory); err != nil { + log.Debugf("error creating root directory: %v", err) + return err + } + return nil +} + +// CreateRestConfigs creates/copies relevant files to generated project +func (c *Copier) CreateRestConfigs() error { + if err := c.CreateRestServer(); err != nil { + log.Debugf("error creating rest server: %v", err) + return err + } + return nil +} + +// CreateRestServer creates/copies relevant files to generated project +func (c *Copier) CreateRestServer() error { + // if the node is server, add server code + if c.IsRestServer { + // create directories for controller, service, dao, models + if err := c.createRestServerDirectories(); err != nil { + log.Debugf("error creating rest server directories: %v", err) + return err + } + } + return nil +} + +// CreateRootLevelFiles copies all root level files at language template. +func (c *Copier) CreateRootLevelFiles() error { + err := utils.CopyFiles(c.NodeDirectoryName, c.TemplatesRootPath) + if err != nil { + return err + } + _, files, err0 := utils.GetDirectoriesAndFilePaths(c.NodeDirectoryName) + if err0 != nil { + return err0 + } + return executor.Execute(files, c.Data) +} diff --git a/core/internal/languages/dotnet/generator.go b/core/internal/languages/dotnet/generator.go new file mode 100644 index 000000000..7a72e6045 --- /dev/null +++ b/core/internal/languages/dotnet/generator.go @@ -0,0 +1,63 @@ +package dotnet + +import ( + "context" + "fmt" + "github.com/intelops/compage/core/internal/languages" + dotnetmvcframework "github.com/intelops/compage/core/internal/languages/dotnet/frameworks/dotnet-mvc-framework" + "github.com/intelops/compage/core/internal/languages/templates" + log "github.com/sirupsen/logrus" +) + +// Generate generates dotnet specific code according to config passed +func Generate(ctx context.Context) error { + // extract goNode + goValues := ctx.Value(contextKeyDotNetContextVars).(DotNetValues) + // rest config + err := generateRESTConfig(ctx, &goValues) + if err != nil { + log.Debugf("err : %s", err) + return err + } + + return nil +} + +func generateRESTConfig(ctx context.Context, dotNetValues *DotNetValues) error { + n := dotNetValues.LDotNetLangNode + if n.RestConfig != nil { + // check for the templates + if n.RestConfig.Template == templates.Compage { + if n.RestConfig.Framework == NetMVCFramework { + dotNetMVCFrameworkCopier := getDotNetMVCFrameworkCopier(dotNetValues) + if n.RestConfig.Server != nil { + if err := dotNetMVCFrameworkCopier.CreateRestServer(); err != nil { + log.Debugf("err : %s", err) + return err + } + } + // copy all files at root level, fire this at last + if err := dotNetMVCFrameworkCopier.CreateRootLevelFiles(); err != nil { + log.Debugf("err : %s", err) + return err + } + } else { + return fmt.Errorf("unsupported framework %s for template %s for language %s", n.RestConfig.Framework, n.RestConfig.Template, n.Language) + } + } + } + + return nil +} + +func getDotNetMVCFrameworkCopier(dotNetValues *DotNetValues) *dotnetmvcframework.Copier { + gitPlatformURL := dotNetValues.Values.Get(languages.GitPlatformURL) + gitPlatformUserName := dotNetValues.Values.Get(languages.GitPlatformUserName) + gitRepositoryName := dotNetValues.Values.Get(languages.GitRepositoryName) + nodeName := dotNetValues.Values.Get(languages.NodeName) + nodeDirectoryName := dotNetValues.Values.NodeDirectoryName + path := GetDotNetTemplatesRootPath() + "/frameworks/" + NetMVCFramework + + copier := dotnetmvcframework.NewCopier(gitPlatformURL, gitPlatformUserName, gitRepositoryName, nodeName, nodeDirectoryName, path) + return copier +} diff --git a/core/internal/languages/dotnet/models.go b/core/internal/languages/dotnet/models.go new file mode 100644 index 000000000..0a2d19100 --- /dev/null +++ b/core/internal/languages/dotnet/models.go @@ -0,0 +1,26 @@ +package dotnet + +import ( + "github.com/intelops/compage/core/internal/languages" + "github.com/intelops/compage/core/internal/utils" +) + +// TemplatesPath directory of template files +const TemplatesPath = "templates/compage-template-dotnet" +const NetMVCFramework = "dotnet-mvc-framework" + +var templatesRootPath = utils.GetProjectRootPath(TemplatesPath) + +// LDotNetLangNode language specific struct. +type LDotNetLangNode struct { + *languages.LanguageNode +} + +// FillDefaults constructor function +func (n *LDotNetLangNode) FillDefaults() error { + return nil +} + +func GetDotNetTemplatesRootPath() string { + return templatesRootPath +} diff --git a/core/internal/languages/dotnet/processor.go b/core/internal/languages/dotnet/processor.go new file mode 100644 index 000000000..23ff522e6 --- /dev/null +++ b/core/internal/languages/dotnet/processor.go @@ -0,0 +1,24 @@ +package dotnet + +import ( + "context" + log "github.com/sirupsen/logrus" +) + +func Process(ctx context.Context) error { + dotNetValues := ctx.Value(contextKeyDotNetContextVars).(DotNetValues) + + // fills default config for DotNet + if err := dotNetValues.LDotNetLangNode.FillDefaults(); err != nil { + log.Debugf("err : %s", err) + return err + } + + // generate DotNet project + if err := Generate(ctx); err != nil { + log.Debugf("err : %s", err) + return err + } + + return nil +} diff --git a/core/internal/languages/languages.go b/core/internal/languages/languages.go index d1a4594c9..493964fb9 100644 --- a/core/internal/languages/languages.go +++ b/core/internal/languages/languages.go @@ -16,6 +16,7 @@ const Rust = "rust" const JavaScript = "javascript" const TypeScript = "typescript" const Ruby = "ruby" +const DotNet = "dotnet" type LanguageNode struct { ID string `json:"ID"` diff --git a/core/main.go b/core/main.go index 0f65671d1..91b30c19f 100644 --- a/core/main.go +++ b/core/main.go @@ -26,10 +26,10 @@ var ( func main() { // grpc server configuration - // Initialize the exporter + // Initializes the exporter var grpcTraceProvider *sdktrace.TracerProvider if len(serviceName) > 0 && len(collectorURL) > 0 { - // add opentel + // add open telemetry tracing grpcTraceProvider = config.InitGrpcTracer(serviceName, collectorURL, insecure) } defer func() { diff --git a/core/templates/compage-template-dotnet b/core/templates/compage-template-dotnet new file mode 160000 index 000000000..d55d1b0d9 --- /dev/null +++ b/core/templates/compage-template-dotnet @@ -0,0 +1 @@ +Subproject commit d55d1b0d90e952b971da0199e50d74885c0e9170 diff --git a/core/test/generator_test.go b/core/test/generator_test.go index b915d4409..c3b9d772f 100644 --- a/core/test/generator_test.go +++ b/core/test/generator_test.go @@ -1450,3 +1450,64 @@ func TestWsServerGenerator(t *testing.T) { } } } + +func TestDotNetMVCFrameworkGenerator(t *testing.T) { + restServerConfigJSON := `{ + "edges": {}, + "nodes": { + "node-b0": { + "id": "node-b0", + "typeId": "node-type-circle", + "consumerData": { + "nodeType": "circle", + "name": "student-service", + "language": "dotnet", + "restConfig": { + "server": { + "sqlDB": "SQLite", + "port": "5005", + "resources": [ + { + "fields": { + "Name": { + "datatype": "string" + }, + "RollNumber": { + "datatype": "int32" + }, + "College": { + "datatype": "string" + } + }, + "name": "Student" + } + ] + }, + "framework": "dotnet-mvc-framework", + "template": "compage" + } + } + } + } +}` + input := project.GenerateCodeRequest{ + GitPlatformURL: "https://github.com", + GitPlatformUserName: "mahendraintelops", + GitRepositoryName: "first-project-github", + ProjectName: "first-rest-server-project-dotnet", + ProjectJSON: restServerConfigJSON, + } + defer func() { + //_ = os.RemoveAll("/tmp/first-rest-server-project-dotnet") + }() + + // retrieve project struct + getProject, err := grpc.GetProject(&input) + if err != nil { + t.Errorf("grpc.GetProject conversion failed = %v", getProject) + } + // trigger project generation + if err0 := handlers.Handle(getProject); err0 != nil { + t.Errorf("handlers.Handle failed %s", err0.Error()) + } +}