Skip to content

Commit

Permalink
modulegen: use cobra instead of native golang flag (#1550)
Browse files Browse the repository at this point in the history
* modulegen: Use cobra instead of native golang flag

Signed-off-by: Matthieu MOREL <[email protected]>

* chore: define flag names as constant

---------

Signed-off-by: Matthieu MOREL <[email protected]>
Co-authored-by: Manuel de la Peña <[email protected]>
  • Loading branch information
mmorel-35 and mdelapenya authored Aug 31, 2023
1 parent e25b7e0 commit f4433dd
Show file tree
Hide file tree
Showing 28 changed files with 388 additions and 307 deletions.
16 changes: 8 additions & 8 deletions docs/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ We have provided a command line tool to generate the scaffolding for the code of

### Command line flags

| Flag | Type | Required | Description |
|------------|--------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| -name | string | Yes | Name of the module, use camel-case when needed. Only alphanumerical characters are allowed (leading character must be a letter). |
| -image | string | Yes | Fully-qualified name of the Docker image to be used by the module (i.e. 'docker.io/org/project:tag') |
| -title | string | No | A variant of the name supporting mixed casing (i.e. 'MongoDB'). Only alphanumerical characters are allowed (leading character must be a letter). |
| -as-module | bool | No | If set, the module will be generated as a Go module, under the modules directory. Otherwise, it will be generated as a subdirectory of the examples directory. |
| Flag | Short | Type | Required | Description |
|---------|-------|--------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| --name | -n | string | Yes | Name of the module, use camel-case when needed. Only alphanumerical characters are allowed (leading character must be a letter). |
| --image | -i | string | Yes | Fully-qualified name of the Docker image to be used by the module (i.e. 'docker.io/org/project:tag') |
| --title | -t | string | No | A variant of the name supporting mixed casing (i.e. 'MongoDB'). Only alphanumerical characters are allowed (leading character must be a letter). |


### What is this tool not doing?

Expand All @@ -45,13 +45,13 @@ We have provided a command line tool to generate the scaffolding for the code of
From the [`modulegen` directory]({{repo_url}}/tree/main/modulegen), please run:

```shell
go run . --name ${NAME_OF_YOUR_MODULE} --image "${REGISTRY}/${MODULE}:${TAG}" --title ${TITLE_OF_YOUR_MODULE}
go run . new example --name ${NAME_OF_YOUR_MODULE} --image "${REGISTRY}/${MODULE}:${TAG}" --title ${TITLE_OF_YOUR_MODULE}
```

or for creating a Go module:

```shell
go run . --name ${NAME_OF_YOUR_MODULE} --image "${REGISTRY}/${MODULE}:${TAG}" --title ${TITLE_OF_YOUR_MODULE} --as-module
go run . new module --name ${NAME_OF_YOUR_MODULE} --image "${REGISTRY}/${MODULE}:${TAG}" --title ${TITLE_OF_YOUR_MODULE}
```

### Adding types and methods to the module
Expand Down
25 changes: 25 additions & 0 deletions modulegen/cmd/modules/example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package modules

import (
"github.com/spf13/cobra"

"github.com/testcontainers/testcontainers-go/modulegen/internal"
)

var newExampleCmd = &cobra.Command{
Use: "example",
Short: "Create a new Example",
Long: "Create a new Example",
RunE: func(cmd *cobra.Command, args []string) error {
return internal.Generate(*exampleVar, false)
},
}

func init() {
newExampleCmd.Flags().StringVarP(&exampleVar.Name, nameFlag, "n", "", "Name of the example. Only alphabetical characters are allowed.")
newExampleCmd.Flags().StringVarP(&exampleVar.NameTitle, titleFlag, "t", "", "(Optional) Title of the example name, used to override the name in the case of mixed casing (Mongodb -> MongoDB). Use camel-case when needed. Only alphabetical characters are allowed.")
newExampleCmd.Flags().StringVarP(&exampleVar.Image, imageFlag, "i", "", "Fully-qualified name of the Docker image to be used by the example")

_ = newExampleCmd.MarkFlagRequired(imageFlag)
_ = newExampleCmd.MarkFlagRequired(nameFlag)
}
7 changes: 7 additions & 0 deletions modulegen/cmd/modules/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package modules

const (
imageFlag = "image"
nameFlag = "name"
titleFlag = "title"
)
20 changes: 20 additions & 0 deletions modulegen/cmd/modules/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package modules

import (
"github.com/spf13/cobra"

"github.com/testcontainers/testcontainers-go/modulegen/internal/context"
)

var exampleVar = &context.ExampleVar{}

var NewCmd = &cobra.Command{
Use: "new",
Short: "Create a new Example or Module",
Long: "Create a new Example or Module",
}

func init() {
NewCmd.AddCommand(newExampleCmd)
NewCmd.AddCommand(newModuleCmd)
}
25 changes: 25 additions & 0 deletions modulegen/cmd/modules/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package modules

import (
"github.com/spf13/cobra"

"github.com/testcontainers/testcontainers-go/modulegen/internal"
)

var newModuleCmd = &cobra.Command{
Use: "module",
Short: "Create a new Module",
Long: "Create a new Module",
RunE: func(cmd *cobra.Command, args []string) error {
return internal.Generate(*exampleVar, true)
},
}

func init() {
newModuleCmd.Flags().StringVarP(&exampleVar.Name, nameFlag, "n", "", "Name of the module. Only alphabetical characters are allowed.")
newModuleCmd.Flags().StringVarP(&exampleVar.NameTitle, titleFlag, "t", "", "(Optional) Title of the module name, used to override the name in the case of mixed casing (Mongodb -> MongoDB). Use camel-case when needed. Only alphabetical characters are allowed.")
newModuleCmd.Flags().StringVarP(&exampleVar.Image, imageFlag, "i", "", "Fully-qualified name of the Docker image to be used by the module")

_ = newModuleCmd.MarkFlagRequired(imageFlag)
_ = newModuleCmd.MarkFlagRequired(nameFlag)
}
17 changes: 17 additions & 0 deletions modulegen/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cmd

import (
"github.com/spf13/cobra"

"github.com/testcontainers/testcontainers-go/modulegen/cmd/modules"
)

var NewRootCmd = &cobra.Command{
Use: "modulegen",
Short: "Management tool for testcontainers-go",
Long: "Management tool for testcontainers-go",
}

func init() {
NewRootCmd.AddCommand(modules.NewCmd)
}
7 changes: 4 additions & 3 deletions modulegen/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/testcontainers/testcontainers-go/modulegen/internal/context"
"github.com/testcontainers/testcontainers-go/modulegen/internal/dependabot"
)

func TestGetDependabotConfigFile(t *testing.T) {
ctx := NewContext(filepath.Join(t.TempDir(), "testcontainers-go"))
ctx := context.New(filepath.Join(t.TempDir(), "testcontainers-go"))

githubDir := ctx.GithubDir()
cfgFile := ctx.DependabotConfigFile()
Expand Down Expand Up @@ -96,8 +97,8 @@ func TestModulesHasDependabotEntry(t *testing.T) {
}
}

func getTestRootContext(t *testing.T) *Context {
func getTestRootContext(t *testing.T) *context.Context {
current, err := os.Getwd()
require.NoError(t, err)
return NewContext(filepath.Dir(current))
return context.New(filepath.Dir(current))
}
11 changes: 0 additions & 11 deletions modulegen/dependabot.go

This file was deleted.

3 changes: 3 additions & 0 deletions modulegen/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/testcontainers/testcontainers-go/modulegen
go 1.20

require (
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb
golang.org/x/mod v0.11.0
Expand All @@ -12,5 +13,7 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
8 changes: 8 additions & 0 deletions modulegen/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA=
Expand Down
7 changes: 7 additions & 0 deletions modulegen/internal/context/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package context

type ExampleVar struct {
Name string
NameTitle string
Image string
}
14 changes: 11 additions & 3 deletions modulegen/context.go → modulegen/internal/context/context.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package context

import (
"os"
Expand Down Expand Up @@ -89,9 +89,17 @@ func (ctx *Context) MkdocsConfigFile() string {
}

func (ctx *Context) VSCodeWorkspaceFile() string {
return filepath.Join(ctx.RootDir, ".testcontainers-go.code-workspace")
return filepath.Join(ctx.RootDir, ".vscode", ".testcontainers-go.code-workspace")
}

func NewContext(dir string) *Context {
func New(dir string) *Context {
return &Context{RootDir: dir}
}

func GetRootContext() (*Context, error) {
current, err := os.Getwd()
if err != nil {
return nil, err
}
return New(filepath.Dir(current)), nil
}
2 changes: 1 addition & 1 deletion modulegen/types.go → modulegen/internal/context/types.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package context

import (
"fmt"
Expand Down
10 changes: 10 additions & 0 deletions modulegen/internal/dependabot/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
package dependabot

import (
"github.com/testcontainers/testcontainers-go/modulegen/internal/context"
)

// update examples in dependabot
func GenerateDependabotUpdates(ctx *context.Context, example context.Example) error {
directory := "/" + example.ParentDir() + "/" + example.Lower()
return UpdateConfig(ctx.DependabotConfigFile(), directory, "gomod")
}

func UpdateConfig(configFile string, directory string, packageEcosystem string) error {
config, err := readConfig(configFile)
if err != nil {
Expand Down
87 changes: 87 additions & 0 deletions modulegen/internal/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package internal

import (
"fmt"
"path/filepath"

"github.com/testcontainers/testcontainers-go/modulegen/internal/context"
"github.com/testcontainers/testcontainers-go/modulegen/internal/dependabot"
"github.com/testcontainers/testcontainers-go/modulegen/internal/make"
"github.com/testcontainers/testcontainers-go/modulegen/internal/mkdocs"
"github.com/testcontainers/testcontainers-go/modulegen/internal/module"
"github.com/testcontainers/testcontainers-go/modulegen/internal/tools"
"github.com/testcontainers/testcontainers-go/modulegen/internal/vscode"
"github.com/testcontainers/testcontainers-go/modulegen/internal/workflow"
)

func Generate(exampleVar context.ExampleVar, isModule bool) error {
ctx, err := context.GetRootContext()
if err != nil {
return fmt.Errorf(">> could not get the root dir: %w", err)
}

example := context.Example{
Image: exampleVar.Image,
IsModule: isModule,
Name: exampleVar.Name,
TitleName: exampleVar.NameTitle,
}

err = GenerateFiles(ctx, example)
if err != nil {
return fmt.Errorf(">> error generating the example: %w", err)
}

cmdDir := filepath.Join(ctx.RootDir, example.ParentDir(), example.Lower())
err = tools.GoModTidy(cmdDir)
if err != nil {
return fmt.Errorf(">> error synchronizing the dependencies: %w", err)
}
err = tools.GoVet(cmdDir)
if err != nil {
return fmt.Errorf(">> error checking generated code: %w", err)
}

fmt.Println("Please go to", cmdDir, "directory to check the results, where 'go mod tidy' and 'go vet' was executed to synchronize the dependencies")
fmt.Println("Commit the modified files and submit a pull request to include them into the project")
fmt.Println("Thanks!")
return nil
}

func GenerateFiles(ctx *context.Context, example context.Example) error {
if err := example.Validate(); err != nil {
return err
}
// creates Makefile for example
err := make.GenerateMakefile(ctx, example)
if err != nil {
return err
}

err = module.GenerateGoModule(ctx, example)
if err != nil {
return err
}

// update github ci workflow
err = workflow.GenerateWorkflow(ctx)
if err != nil {
return err
}
// update examples in mkdocs
err = mkdocs.GenerateMkdocs(ctx, example)
if err != nil {
return err
}
// update examples in dependabot
err = dependabot.GenerateDependabotUpdates(ctx, example)
if err != nil {
return err
}
// generate vscode workspace
err = vscode.GenerateVSCodeWorkspace(ctx)
if err != nil {
return err
}
return nil
}
8 changes: 8 additions & 0 deletions modulegen/internal/make/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import (
"path/filepath"
"text/template"

"github.com/testcontainers/testcontainers-go/modulegen/internal/context"
internal_template "github.com/testcontainers/testcontainers-go/modulegen/internal/template"
)

// creates Makefile for example
func GenerateMakefile(ctx *context.Context, example context.Example) error {
exampleDir := filepath.Join(ctx.RootDir, example.ParentDir(), example.Lower())
exampleName := example.Lower()
return Generate(exampleDir, exampleName)
}

func Generate(exampleDir string, exampleName string) error {
name := "Makefile.tmpl"
t, err := template.New(name).ParseFiles(filepath.Join("_template", name))
Expand Down
26 changes: 26 additions & 0 deletions modulegen/internal/mkdocs/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
package mkdocs

import (
"path/filepath"
"text/template"

"github.com/testcontainers/testcontainers-go/modulegen/internal/context"
)

// update examples in mkdocs
func GenerateMkdocs(ctx *context.Context, example context.Example) error {
exampleMdFile := filepath.Join(ctx.DocsDir(), example.ParentDir(), example.Lower()+".md")
funcMap := template.FuncMap{
"Entrypoint": func() string { return example.Entrypoint() },
"ContainerName": func() string { return example.ContainerName() },
"ParentDir": func() string { return example.ParentDir() },
"ToLower": func() string { return example.Lower() },
"Title": func() string { return example.Title() },
}
err := GenerateMdFile(exampleMdFile, funcMap, example)
if err != nil {
return err
}
exampleMd := example.ParentDir() + "/" + example.Lower() + ".md"
indexMd := example.ParentDir() + "/index.md"
return UpdateConfig(ctx.MkdocsConfigFile(), example.IsModule, exampleMd, indexMd)
}

func UpdateConfig(configFile string, isModule bool, exampleMd string, indexMd string) error {
config, err := ReadConfig(configFile)
if err != nil {
Expand Down
Loading

0 comments on commit f4433dd

Please sign in to comment.