diff --git a/README.md b/README.md index 7a2aa1299..5b2d307ab 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The best way then to use this is to add an alias, then you can use the CLI as if ## Usage 1) To create a project run `commit0 create [PROJECT_NAME]` -2) A folder will be created and within that update the `commit0.yml` and then run `commit0 generate -l=[LANGUAGE OF CHOICE] eg. go` +2) A folder will be created and within that update the `commit0.yml` and then run `commit0 generate` 3) You will see that there is now an idl folder created. 4) Within the idl folder modify the the protobuf services generated with your desired methods 5) Go up to the parent directory and re run `commit0 generate -l=[LANGUAGE OF CHOICE]` diff --git a/cmd/commit0_ui.go b/cmd/commit0_ui.go new file mode 100644 index 000000000..e01efe69f --- /dev/null +++ b/cmd/commit0_ui.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/commitdev/commit0/internal/api" + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(commit0api) +} + +var commit0api = &cobra.Command{ + Use: "ui", + Short: "Run Commit0 Api", + Run: func(cmd *cobra.Command, args []string) { + api.Commit0Api() + }, +} diff --git a/cmd/create.go b/cmd/create.go index 7ca6eb848..feeb892da 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -30,13 +30,34 @@ func Create(projectName string, outDir string, t *templator.Templator) string { } var wg sync.WaitGroup - util.TemplateFileIfDoesNotExist(rootDir, "commit0.yml", t.Commit0, &wg, projectName) + defaultProjConfig := defaultProjConfig(projectName) + + util.TemplateFileIfDoesNotExist(rootDir, util.CommitYml, t.Commit0, &wg, defaultProjConfig) util.TemplateFileIfDoesNotExist(rootDir, ".gitignore", t.GitIgnore, &wg, projectName) wg.Wait() return rootDir } +func defaultProjConfig(projectName string) util.ProjectConfiguration { + return util.ProjectConfiguration{ + ProjectName: projectName, + FrontendFramework: "react", + Organization: "mycompany", + Description: "", + Maintainers: []util.Maintainer{{ + Name: "bob", + Email: "bob@test.com", + }}, + Services: []util.Service{{ + Name: "User", + Description: "User Service", + Language: "go", + GitRepo: "github.com/test/repo", + }}, + } +} + var createCmd = &cobra.Command{ Use: "create", Short: "Create new project with provided name.", diff --git a/cmd/create_test.go b/cmd/create_test.go index fd4ac2e58..5c68811c9 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -8,6 +8,7 @@ import ( "github.com/commitdev/commit0/cmd" "github.com/commitdev/commit0/internal/templator" + "github.com/commitdev/commit0/internal/util" "github.com/gobuffalo/packr/v2" ) @@ -25,7 +26,7 @@ func TestCreateWorks(t *testing.T) { root := cmd.Create(projectName, tmpdir, templator) defer os.RemoveAll(tmpdir) - st, err := os.Stat(path.Join(root, "commit0.yml")) + st, err := os.Stat(path.Join(root, util.CommitYml)) if err != nil { t.Fatal(err) } diff --git a/cmd/generate.go b/cmd/generate.go index c103c2665..26c8baeb2 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -1,35 +1,19 @@ package cmd import ( - "log" - "sync" - "github.com/commitdev/commit0/internal/config" - "github.com/commitdev/commit0/internal/generate/golang" - "github.com/commitdev/commit0/internal/generate/kubernetes" - "github.com/commitdev/commit0/internal/generate/proto" - "github.com/commitdev/commit0/internal/generate/react" + "github.com/commitdev/commit0/internal/generate" "github.com/commitdev/commit0/internal/templator" "github.com/commitdev/commit0/internal/util" "github.com/gobuffalo/packr/v2" - "github.com/kyokomi/emoji" - "github.com/logrusorgru/aurora" "github.com/spf13/cobra" ) var configPath string -const ( - Go = "go" - React = "react" - Kubernetes = "kubernetes" -) - -var supportedLanguages = [...]string{Go, React, Kubernetes} - func init() { - generateCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "commit0.yml", "config path") + generateCmd.PersistentFlags().StringVarP(&configPath, "config", "c", util.CommitYml, "config path") rootCmd.AddCommand(generateCmd) } @@ -45,58 +29,7 @@ var generateCmd = &cobra.Command{ cfg := config.LoadConfig(configPath) cfg.Print() - var wg sync.WaitGroup - if !ValidLanguage(cfg.Frontend.Framework) { - log.Fatalln(aurora.Red(emoji.Sprintf(":exclamation: '%s' is not a supported framework.", cfg.Frontend.Framework))) - } - - for _, s := range cfg.Services { - if !ValidLanguage(cfg.Frontend.Framework) { - log.Fatalln(aurora.Red(emoji.Sprintf(":exclamation: '%s' in service '%s' is not a supported language.", s.Name, s.Language))) - } - } - - for _, s := range cfg.Services { - switch s.Language { - case Go: - log.Println(aurora.Cyan(emoji.Sprintf("Creating Go service"))) - proto.Generate(t, cfg, s, &wg) - golang.Generate(t, cfg, s, &wg) - } - } - - if cfg.Infrastructure.AWS.EKS.ClusterName != "" { - log.Println(aurora.Cyan(emoji.Sprintf("Generating Terraform"))) - kubernetes.Generate(t, cfg, &wg) - } - - // @TODO : This strucuture probably needs to be adjusted. Probably too generic. - switch cfg.Frontend.Framework { - case React: - log.Println(aurora.Cyan(emoji.Sprintf("Creating React frontend"))) - react.Generate(t, cfg, &wg) - } - - util.TemplateFileIfDoesNotExist("", "README.md", t.Readme, &wg, templator.GenericTemplateData{*cfg}) - - // Wait for all the templates to be generated - wg.Wait() - - log.Println("Executing commands") - // @TODO : Move this stuff to another command? Or genericize it a bit. - if cfg.Infrastructure.AWS.EKS.Deploy { - kubernetes.Execute(cfg) - } + generate.GenerateArtifactsHelper(t, cfg, "") }, } - -func ValidLanguage(language string) bool { - for _, l := range supportedLanguages { - if l == language { - return true - } - } - - return false -} diff --git a/example/hello-world/go.mod b/example/hello-world/go.mod index 9b83fa8ac..fcdaf198d 100644 --- a/example/hello-world/go.mod +++ b/example/hello-world/go.mod @@ -7,7 +7,6 @@ replace github.com/yourrepo/hello-world-idl => ./hello-world-idl require ( github.com/grpc-ecosystem/grpc-gateway v1.11.3 // indirect github.com/yourrepo/hello-world-idl v0.0.0 - google.golang.org/appengine v1.4.0 // indirect google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 // indirect google.golang.org/grpc v1.24.0 // indirect ) diff --git a/go.mod b/go.mod index e83a5c97b..316bc3597 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.12 require ( github.com/gobuffalo/logger v1.0.1 // indirect github.com/gobuffalo/packr/v2 v2.5.2 + github.com/gorilla/mux v1.7.3 github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect github.com/k0kubun/pp v3.0.1+incompatible github.com/kyokomi/emoji v2.1.0+incompatible diff --git a/go.sum b/go.sum index ea6ccd3ee..1d68c2377 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,8 @@ github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4 github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= github.com/gobuffalo/packr/v2 v2.5.2 h1:4EvjeIpQLZuRIljwnidYgbRXbr1yIzVRrESiLjqKj6s= github.com/gobuffalo/packr/v2 v2.5.2/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= diff --git a/internal/api/README.md b/internal/api/README.md new file mode 100644 index 000000000..fdbdc8443 --- /dev/null +++ b/internal/api/README.md @@ -0,0 +1,39 @@ +# Commit0 Api + +## Usage + - To run: + `commit0 api` + - Endpoint: + - POST `localhost:8080/{version}/generate` + - Post request body json example: + ``` { + "projectName":"funApp", + "frontendFramework":"react", + "organization":"commit org", + "description":"this app will do amazing things", + "maintainers":[ + { + "name":"Lill", + "email":"ll@gmail.com" + }, + { + "name":"Pi", + "email":"pi@live.ca" + } + ], + "services":[ + { + "name":"user", + "description":"user service", + "language":"go", + "gitRepo":"github.com/user" + }, + { + "name":"account", + "description":"bank account service", + "language":"go", + "gitRepo":"github.com/account" + } + ] + } + ``` diff --git a/internal/api/create_project.go b/internal/api/create_project.go new file mode 100644 index 000000000..2071a0c15 --- /dev/null +++ b/internal/api/create_project.go @@ -0,0 +1,53 @@ +package api + +import ( + "log" + "os" + "path" + "sync" + + "github.com/commitdev/commit0/internal/config" + "github.com/commitdev/commit0/internal/generate" + "github.com/commitdev/commit0/internal/templator" + "github.com/commitdev/commit0/internal/util" + "github.com/gobuffalo/packr/v2" +) + +func createProject(projectConfig util.ProjectConfiguration) string { + templates := packr.New("templates", "../../templates") + t := templator.NewTemplator(templates) + outDir := "./" + rootDir := path.Join(outDir, projectConfig.ProjectName) + log.Printf("Creating project %s.", projectConfig.ProjectName) + err := os.MkdirAll(rootDir, os.ModePerm) + + if os.IsExist(err) { + log.Fatalf("Directory %v already exists! Error: %v", projectConfig.ProjectName, err) + } else if err != nil { + log.Fatalf("Error creating root: %v ", err) + } + var wg sync.WaitGroup + + util.TemplateFileIfDoesNotExist(rootDir, util.CommitYml, t.Commit0, &wg, projectConfig) + + util.TemplateFileIfDoesNotExist(rootDir, ".gitignore", t.GitIgnore, &wg, projectConfig.ProjectName) + + wg.Wait() + + GenerateArtifacts(projectConfig) + + return rootDir +} + +func GenerateArtifacts(projectConfig util.ProjectConfiguration) { + + templates := packr.New("templates", "../templates") + t := templator.NewTemplator(templates) + + generatedYml := path.Join(projectConfig.ProjectName, util.CommitYml) + + cfg := config.LoadConfig(generatedYml) + cfg.Print() + + generate.GenerateArtifactsHelper(t, cfg, projectConfig.ProjectName) +} diff --git a/internal/api/generate_api.go b/internal/api/generate_api.go new file mode 100644 index 000000000..af6569a59 --- /dev/null +++ b/internal/api/generate_api.go @@ -0,0 +1,40 @@ +package api + +import ( + "encoding/json" + "github.com/gorilla/mux" + "log" + "net/http" + + "github.com/commitdev/commit0/internal/util" +) + +func generateProject(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch req.Method { + case "POST": + decoder := json.NewDecoder(req.Body) + var projectConfig util.ProjectConfiguration + err := decoder.Decode(&projectConfig) + if err != nil { + panic(err) + } + log.Println(projectConfig.ProjectName) + createProject(projectConfig) + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"message": "Post successful"}`)) + + default: + w.WriteHeader(http.StatusNotFound) + w.Write([]byte(`{"message": "Not found"}`)) + } + +} + +func Commit0Api() { + var router = mux.NewRouter() + var api = router.PathPrefix("/v1/generate").Subrouter() + api.NotFoundHandler = http.HandlerFunc(generateProject) + + log.Fatal(http.ListenAndServe(":8080", router)) +} diff --git a/internal/config/config.go b/internal/config/config.go index 6ae68273a..1eeee6578 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -8,7 +8,7 @@ import ( "gopkg.in/yaml.v2" ) -type maintainers struct { +type maintainer struct { Name string Email string } @@ -63,7 +63,7 @@ type Commit0Config struct { Organization string Name string Description string - Maintainers []maintainers + Maintainers []maintainer Services []Service Frontend frontend Infrastructure infrastructure diff --git a/internal/generate/generate_helper.go b/internal/generate/generate_helper.go new file mode 100644 index 000000000..f4406e6a0 --- /dev/null +++ b/internal/generate/generate_helper.go @@ -0,0 +1,60 @@ +package generate + +import ( + "github.com/commitdev/commit0/internal/config" + "github.com/commitdev/commit0/internal/generate/golang" + "github.com/commitdev/commit0/internal/generate/kubernetes" + "github.com/commitdev/commit0/internal/generate/proto" + "github.com/commitdev/commit0/internal/generate/react" + "github.com/commitdev/commit0/internal/templator" + "github.com/commitdev/commit0/internal/util" + "github.com/kyokomi/emoji" + "github.com/logrusorgru/aurora" + "log" + "sync" +) + +func GenerateArtifactsHelper(t *templator.Templator, cfg *config.Commit0Config, pathPrefix string) { + var wg sync.WaitGroup + if !util.ValidateLanguage(cfg.Frontend.Framework) { + log.Fatalln(aurora.Red(emoji.Sprintf(":exclamation: '%s' is not a supported framework.", cfg.Frontend.Framework))) + } + + for _, s := range cfg.Services { + if !util.ValidateLanguage(cfg.Frontend.Framework) { + log.Fatalln(aurora.Red(emoji.Sprintf(":exclamation: '%s' in service '%s' is not a supported language.", s.Name, s.Language))) + } + } + + for _, s := range cfg.Services { + switch s.Language { + case util.Go: + log.Println(aurora.Cyan(emoji.Sprintf("Creating Go service"))) + proto.Generate(t, cfg, s, &wg, pathPrefix) + golang.Generate(t, cfg, s, &wg, pathPrefix) + } + } + + if cfg.Infrastructure.AWS.EKS.ClusterName != "" { + log.Println(aurora.Cyan(emoji.Sprintf("Generating Terraform"))) + kubernetes.Generate(t, cfg, &wg, pathPrefix) + } + + // @TODO : This strucuture probably needs to be adjusted. Probably too generic. + switch cfg.Frontend.Framework { + case util.React: + log.Println(aurora.Cyan(emoji.Sprintf("Creating React frontend"))) + react.Generate(t, cfg, &wg, pathPrefix) + } + + util.TemplateFileIfDoesNotExist(pathPrefix, "README.md", t.Readme, &wg, templator.GenericTemplateData{*cfg}) + + // Wait for all the templates to be generated + wg.Wait() + + log.Println("Executing commands") + // @TODO : Move this stuff to another command? Or genericize it a bit. + if cfg.Infrastructure.AWS.EKS.Deploy { + kubernetes.Execute(cfg, pathPrefix) + } +} diff --git a/internal/generate/golang/generate.go b/internal/generate/golang/generate.go index 705744e17..84287a343 100644 --- a/internal/generate/golang/generate.go +++ b/internal/generate/golang/generate.go @@ -13,8 +13,8 @@ import ( "github.com/commitdev/commit0/internal/util" ) -func Generate(t *templator.Templator, cfg *config.Commit0Config, service config.Service, wg *sync.WaitGroup) { - basePath := filepath.Join("service", service.Name) +func Generate(t *templator.Templator, cfg *config.Commit0Config, service config.Service, wg *sync.WaitGroup, pathPrefix string) { + basePath := filepath.Join(pathPrefix, "service", service.Name) healthPath := filepath.Join(basePath, "health") data := templator.GolangTemplateData{ diff --git a/internal/generate/kubernetes/generate.go b/internal/generate/kubernetes/generate.go index 7ecc50f4c..a394d2315 100644 --- a/internal/generate/kubernetes/generate.go +++ b/internal/generate/kubernetes/generate.go @@ -1,37 +1,37 @@ package kubernetes import ( - "fmt" "io" "log" "os" "os/exec" + "path" "sync" "github.com/commitdev/commit0/internal/config" "github.com/commitdev/commit0/internal/templator" ) -func Generate(t *templator.Templator, cfg *config.Commit0Config, wg *sync.WaitGroup) { +func Generate(t *templator.Templator, cfg *config.Commit0Config, wg *sync.WaitGroup, pathPrefix string) { data := templator.GenericTemplateData{*cfg} - t.Kubernetes.TemplateFiles(data, false, wg) + t.Kubernetes.TemplateFiles(data, false, wg, pathPrefix) } -func Execute(config *config.Commit0Config) { +func Execute(config *config.Commit0Config, pathPrefix string) { if config.Infrastructure.AWS.EKS.Deploy { log.Println("Planning infrastructure...") - execute(exec.Command("terraform", "init")) - execute(exec.Command("terraform", "plan")) + execute(exec.Command("terraform", "init"), pathPrefix) + execute(exec.Command("terraform", "plan"), pathPrefix) } } -func execute(cmd *exec.Cmd) { +func execute(cmd *exec.Cmd, pathPrefix string) { dir, err := os.Getwd() if err != nil { log.Fatalf("Getting working directory failed: %v\n", err) } - - cmd.Dir = fmt.Sprintf("%s/kubernetes/terraform/environments/staging", dir) + kubDir := path.Join(pathPrefix, "kubernetes/terraform/environments/staging") + cmd.Dir = path.Join(dir, kubDir) stdoutPipe, _ := cmd.StdoutPipe() stderrPipe, _ := cmd.StderrPipe() diff --git a/internal/generate/proto/generate.go b/internal/generate/proto/generate.go index 76b0f49c9..6c1bb4b56 100644 --- a/internal/generate/proto/generate.go +++ b/internal/generate/proto/generate.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "os/exec" + "path" "path/filepath" "sync" @@ -16,8 +17,9 @@ import ( "github.com/logrusorgru/aurora" ) -func Generate(t *templator.Templator, cfg *config.Commit0Config, service config.Service, wg *sync.WaitGroup) { - idlPath := fmt.Sprintf("%s-idl", cfg.Name) +func Generate(t *templator.Templator, cfg *config.Commit0Config, service config.Service, wg *sync.WaitGroup, pathPrefix string) { + idlName := fmt.Sprintf("%s-idl", cfg.Name) + idlPath := path.Join(pathPrefix, idlName) idlHealthPath := filepath.Join(idlPath, "proto", "health") data := templator.GolangTemplateData{ @@ -33,13 +35,12 @@ func Generate(t *templator.Templator, cfg *config.Commit0Config, service config. file := fmt.Sprintf("%s.proto", service.Name) util.TemplateFileIfDoesNotExist(serviceProtoDir, file, t.ProtoServiceTemplate, wg, data) - GenerateProtoServiceLibs(cfg) + GenerateProtoServiceLibs(idlPath) } -func GenerateProtoServiceLibs(cfg *config.Commit0Config) { - idlRoot := fmt.Sprintf("%s-idl", cfg.Name) +func GenerateProtoServiceLibs(idlPath string) { cmd := exec.Command("make", "generate") - cmd.Dir = idlRoot + cmd.Dir = idlPath var out bytes.Buffer var stderr bytes.Buffer cmd.Stdout = &out diff --git a/internal/generate/react/generate.go b/internal/generate/react/generate.go index 9ba7dce30..01301c28b 100644 --- a/internal/generate/react/generate.go +++ b/internal/generate/react/generate.go @@ -1,6 +1,7 @@ package react import ( + "path" "sync" "github.com/commitdev/commit0/internal/config" @@ -8,11 +9,12 @@ import ( "github.com/commitdev/commit0/internal/templator" ) -func Generate(t *templator.Templator, cfg *config.Commit0Config, wg *sync.WaitGroup) { +func Generate(t *templator.Templator, cfg *config.Commit0Config, wg *sync.WaitGroup, pathPrefix string) { data := templator.GenericTemplateData{*cfg} - t.React.TemplateFiles(data, false, wg) + t.React.TemplateFiles(data, false, wg, pathPrefix) + basePath := path.Join(pathPrefix, "react/") if cfg.Frontend.CI.System != "" { - ci.Generate(t.CI, cfg, cfg.Frontend.CI, "react/", wg) + ci.Generate(t.CI, cfg, cfg.Frontend.CI, basePath, wg) } } diff --git a/internal/templator/templator.go b/internal/templator/templator.go index 1d53cf52f..dc2b347fb 100644 --- a/internal/templator/templator.go +++ b/internal/templator/templator.go @@ -1,6 +1,7 @@ package templator import ( + "path" "path/filepath" "strings" "sync" @@ -125,9 +126,10 @@ type DirectoryTemplator struct { Templates []*template.Template } -func (d *DirectoryTemplator) TemplateFiles(data interface{}, overwrite bool, wg *sync.WaitGroup) { +func (d *DirectoryTemplator) TemplateFiles(data interface{}, overwrite bool, wg *sync.WaitGroup, pathPrefix string) { for _, template := range d.Templates { - d, f := filepath.Split(template.Name()) + templatePath := path.Join(pathPrefix, template.Name()) + d, f := filepath.Split(templatePath) if strings.HasSuffix(f, ".tmpl") { f = strings.Replace(f, ".tmpl", "", -1) } diff --git a/internal/util/projectAttributes.go b/internal/util/projectAttributes.go new file mode 100644 index 000000000..99c70f7e0 --- /dev/null +++ b/internal/util/projectAttributes.go @@ -0,0 +1,42 @@ +package util + +const ( + Go = "go" + React = "react" + Kubernetes = "kubernetes" +) + +const CommitYml = "commit0.yml" + +var supportedLanguages = [...]string{Go, React, Kubernetes} + +func ValidateLanguage(language string) bool { + for _, l := range supportedLanguages { + if l == language { + return true + } + } + + return false +} + +type Maintainer struct { + Name string `json:"name"` + Email string `json:"email"` +} + +type Service struct { + Name string `json:"name"` + Description string `json:"description"` + Language string `json:"language"` + GitRepo string `json:"gitRepo"` +} + +type ProjectConfiguration struct { + ProjectName string `json:"projectName"` + FrontendFramework string `json:"frontendFramework"` + Organization string `json:"organization"` + Description string `json:"description"` + Maintainers []Maintainer `json:"maintainers"` + Services []Service `json:"services"` +} diff --git a/templates/commit0/commit0.tmpl b/templates/commit0/commit0.tmpl index e37db9432..dd8f7c553 100644 --- a/templates/commit0/commit0.tmpl +++ b/templates/commit0/commit0.tmpl @@ -1,9 +1,11 @@ -organization: mycompany -name: {{.}} -description: +organization: {{.Organization}} +name: {{.ProjectName}} +description: {{.Description}} maintainers: -# - name: bob -# email: bob@test.com + {{range .Maintainers}} + # - name: {{.Name}} + # email: {{.Email}} + {{end}} infrastructure: aws: @@ -14,7 +16,7 @@ infrastructure: deploy: true frontend: - framework: react + framework: {{.FrontendFramework}} ci: system: circleci buildImage: react/react @@ -22,7 +24,7 @@ frontend: buildCommand: make build testCommand: make test app: - name: {{.}} + name: {{.ProjectName}} header: enabled: true account: @@ -45,10 +47,11 @@ frontend: services: - - name: User - description: User service - language: go - gitRepo: github.com/test/repo + {{range .Services}} + - name: {{.Name}} + description: {{.Description}} + language: {{.Language}} + gitRepo: {{.GitRepo}} dockerRepo: ci: system: circleci @@ -66,3 +69,4 @@ services: web: enabled: true port: 8090 + {{end}}