Skip to content

Commit b35405a

Browse files
authored
Merge pull request #1382 from devstream-io/refactor-struct-error-msg
refactor: error message and add app validate
2 parents 90f96b3 + 909c311 commit b35405a

File tree

35 files changed

+238
-300
lines changed

35 files changed

+238
-300
lines changed

internal/pkg/configmanager/app.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/devstream-io/devstream/pkg/util/log"
77
"github.com/devstream-io/devstream/pkg/util/scm/git"
8+
"github.com/devstream-io/devstream/pkg/util/validator"
89
)
910

1011
const (
@@ -17,28 +18,32 @@ type repoTemplate struct {
1718
}
1819

1920
type app struct {
20-
Name string `yaml:"name" mapstructure:"name"`
21-
Spec *appSpec `yaml:"spec" mapstructure:"spec"`
22-
Repo *git.RepoInfo `yaml:"repo" mapstructure:"repo"`
21+
Name string `yaml:"name" mapstructure:"name" validate:"required"`
22+
Spec *appSpec `yaml:"spec" mapstructure:"spec" validate:"required"`
23+
Repo *git.RepoInfo `yaml:"repo" mapstructure:"repo" validate:"required"`
2324
RepoTemplate *repoTemplate `yaml:"repoTemplate" mapstructure:"repoTemplate"`
2425
CIRawConfigs []pipelineRaw `yaml:"ci" mapstructure:"ci"`
2526
CDRawConfigs []pipelineRaw `yaml:"cd" mapstructure:"cd"`
2627
}
2728

2829
func (a *app) getTools(vars map[string]any, templateMap map[string]string) (Tools, error) {
29-
// 1. set app default field repoInfo and repoTemplateInfo
30+
// 1. check app config data is valid
31+
if err := validator.CheckStructError(a).Combine(); err != nil {
32+
return nil, err
33+
}
34+
// 2. set app default field repoInfo and repoTemplateInfo
3035
if err := a.setDefault(); err != nil {
3136
return nil, err
3237
}
3338

34-
// 2. get ci/cd pipelineTemplates
39+
// 3. get ci/cd pipelineTemplates
3540
appVars := a.Spec.merge(vars)
3641
tools, err := a.generateCICDTools(templateMap, appVars)
3742
if err != nil {
3843
return nil, fmt.Errorf("app[%s] get pipeline tools failed: %w", a.Name, err)
3944
}
4045

41-
// 3. generate app repo and template repo from scmInfo
46+
// 4. generate app repo and template repo from scmInfo
4247
repoScaffoldingTool := a.generateRepoTemplateTool()
4348
if repoScaffoldingTool != nil {
4449
tools = append(tools, repoScaffoldingTool)
@@ -58,6 +63,9 @@ func (a *app) generateCICDTools(templateMap map[string]string, appVars map[strin
5863
if err != nil {
5964
return nil, err
6065
}
66+
if err := validator.CheckStructError(t).Combine(); err != nil {
67+
return nil, err
68+
}
6169
t.updatePipelineVars(pipelineGlobalVars)
6270
pipelineTool, err := t.generatePipelineTool(pipelineGlobalVars)
6371
if err != nil {
@@ -90,9 +98,6 @@ func (a *app) generateRepoTemplateTool() *Tool {
9098

9199
// setDefault will set repoName to appName if repo.name field is empty
92100
func (a *app) setDefault() error {
93-
if a.Repo == nil {
94-
return fmt.Errorf("configmanager[app] is invalid, repo field must be configured")
95-
}
96101
if a.Repo.Repo == "" {
97102
a.Repo.Repo = a.Name
98103
}

internal/pkg/configmanager/app_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ var _ = Describe("app struct", func() {
2727
It("should return error", func() {
2828
_, err := a.getTools(vars, templateMap)
2929
Expect(err).Should(HaveOccurred())
30-
Expect(err.Error()).Should(ContainSubstring("configmanager[app] is invalid, repo field must be configured"))
30+
Expect(err.Error()).Should(ContainSubstring("field app.repo is required"))
3131
})
3232
})
3333
When("ci/cd template is not valid", func() {
@@ -47,7 +47,8 @@ var _ = Describe("app struct", func() {
4747
It("should return error", func() {
4848
_, err := a.getTools(vars, templateMap)
4949
Expect(err).Should(HaveOccurred())
50-
Expect(err.Error()).Should(ContainSubstring("not found in pipelineTemplates"))
50+
Expect(err.Error()).Should(ContainSubstring("field app.name is required"))
51+
Expect(err.Error()).Should(ContainSubstring("field app.spec is required"))
5152
})
5253
})
5354
When("app repo template is empty", func() {
@@ -57,6 +58,7 @@ var _ = Describe("app struct", func() {
5758
Repo: &git.RepoInfo{
5859
CloneURL: "http://test.com/test/test_app",
5960
},
61+
Spec: &appSpec{Language: "go", FrameWork: "gin"},
6062
}
6163
})
6264
It("should return empty tools", func() {
@@ -89,7 +91,7 @@ name: not_valid,
8991
type: not_valid`}
9092
_, err := a.generateCICDTools(templateMap, vars)
9193
Expect(err).Should(HaveOccurred())
92-
Expect(err.Error()).Should(ContainSubstring("pipeline type [not_valid] not supported for now"))
94+
Expect(err.Error()).Should(ContainSubstring("field pipelineTemplate.type must be one of"))
9395
})
9496
})
9597
})

internal/pkg/configmanager/appspec.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import (
1010
// appSpec is app special options
1111
type appSpec struct {
1212
// language config
13-
Language string `yaml:"language" mapstructure:"language"`
14-
FrameWork string `yaml:"framework" mapstructure:"framework"`
13+
Language string `yaml:"language" mapstructure:"language" validate:"required"`
14+
FrameWork string `yaml:"framework" mapstructure:"framework" validate:"required"`
1515
}
1616

1717
// merge will merge vars and appSpec

internal/pkg/configmanager/configmanager_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ apps:
4545
url: github.com/devstream-io/dtm-repo-scaffolding-golang-gin # optional,if url is specified,we can infer scm/owner/org/name from url
4646
ci:
4747
- type: template
48-
templateName: ci-pipeline-for-gh-actions
48+
templateName: ci-pipeline-for-github-actions
4949
options: # overwrite options in pipelineTemplates
5050
docker:
5151
registry:
@@ -76,7 +76,7 @@ tools:
7676
foo2: [[ foo2 ]]
7777
7878
pipelineTemplates:
79-
- name: ci-pipeline-for-gh-actions
79+
- name: ci-pipeline-for-github-actions
8080
type: github-actions # corresponding to a plugin
8181
options:
8282
branch: main # optional, default is main

internal/pkg/configmanager/pipelinetemplate.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import (
1313
type (
1414
// pipelineRaw is the raw format of app.ci/app.cd config
1515
pipelineRaw struct {
16-
Type string `yaml:"type" mapstructure:"type"`
17-
TemplateName string `yaml:"templateName" mapstructure:"templateName"`
16+
Type string `yaml:"type" mapstructure:"type" validate:"required,oneof=template jenkins-pipeline github-actions gitlab-ci argocdapp"`
17+
TemplateName string `yaml:"templateName" mapstructure:"templateName" validate:"required"`
1818
Options RawOptions `yaml:"options" mapstructure:"options"`
1919
Vars RawOptions `yaml:"vars" mapstructure:"vars"`
2020
}
2121
// pipelineTemplate is valid pipeline format
2222
pipelineTemplate struct {
23-
Name string `yaml:"name"`
24-
Type string `yaml:"type"`
23+
Name string `yaml:"name" validate:"required"`
24+
Type string `yaml:"type" validate:"required,oneof=jenkins-pipeline github-actions gitlab-ci argocdapp"`
2525
Options RawOptions `yaml:"options"`
2626
}
2727
// pipelineGlobalOption is used to pass variable between ci/cd pipeline

internal/pkg/configmanager/tool.go

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"runtime"
66
"strings"
77

8-
"go.uber.org/multierr"
98
"gopkg.in/yaml.v3"
109

1110
"github.com/devstream-io/devstream/internal/pkg/version"
@@ -56,22 +55,13 @@ func (t *Tool) String() string {
5655
type Tools []*Tool
5756

5857
func (tools Tools) validateAll() error {
59-
var errs []error
60-
errs = append(errs, tools.validate()...)
61-
errs = append(errs, tools.validateDependsOnConfig()...)
62-
return multierr.Combine(errs...)
63-
}
64-
65-
func (tools Tools) validate() (errs []error) {
58+
var errs validator.StructFieldErrors
6659
for _, tool := range tools {
67-
errs = append(errs, tool.validate()...)
60+
errs = append(errs, validator.CheckStructError(tool)...)
6861
}
62+
errs = append(errs, tools.validateDependsOnConfig()...)
6963
errs = append(errs, tools.duplicatedCheck()...)
70-
return
71-
}
72-
73-
func (t *Tool) validate() []error {
74-
return validator.Struct(t)
64+
return errs.Combine()
7565
}
7666

7767
func (t *Tool) DeepCopy() *Tool {

internal/pkg/configmanager/tool_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,20 @@ var _ = Describe("validateDependsOnConfig", func() {
6767
})
6868
})
6969

70-
var _ = Describe("Tool Validation", func() {
70+
var _ = Describe("Tool Validation all", func() {
7171
It("should return empty error array if tools all valid", func() {
7272
tools := Tools{
7373
{Name: "test_tool", InstanceID: "0", DependsOn: []string{}},
7474
}
75-
errors := tools.validate()
76-
Expect(errors).Should(BeEmpty())
75+
err := tools.validateAll()
76+
Expect(err).ShouldNot(HaveOccurred())
7777
})
7878
It("should return error if tool not valid", func() {
7979
tools := Tools{
8080
{Name: "", InstanceID: "", DependsOn: []string{}},
8181
}
82-
errors := tools.validate()
83-
Expect(errors).ShouldNot(BeEmpty())
82+
err := tools.validateAll()
83+
Expect(err).Should(HaveOccurred())
8484
})
8585

8686
})

internal/pkg/develop/plugin/template/validate.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,8 @@ func validate(options configmanager.RawOptions) (configmanager.RawOptions, error
1818
if err != nil {
1919
return nil, err
2020
}
21-
errs := validator.Struct(opts)
22-
if len(errs) > 0 {
23-
for _, e := range errs {
24-
log.Errorf("Options error: %s.", e)
25-
}
26-
return nil, fmt.Errorf("opts are illegal")
21+
if errs := validator.CheckStructError(opts).Combine(); len(errs) != 0 {
22+
return nil, errs.Combine()
2723
}
2824
return options, nil
2925
}

internal/pkg/plugin/argocdapp/validate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func validate(options configmanager.RawOptions) (configmanager.RawOptions, error
1515
if err != nil {
1616
return nil, err
1717
}
18-
if err = validator.StructAllError(opts); err != nil {
18+
if err := validator.CheckStructError(opts).Combine(); err != nil {
1919
return nil, err
2020
}
2121
return options, nil
Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package devlakeconfig
22

33
import (
4-
"fmt"
5-
64
"github.com/devstream-io/devstream/internal/pkg/configmanager"
7-
"github.com/devstream-io/devstream/pkg/util/log"
85
"github.com/devstream-io/devstream/pkg/util/validator"
96
)
107

@@ -14,12 +11,8 @@ func validate(options configmanager.RawOptions) (configmanager.RawOptions, error
1411
if err != nil {
1512
return nil, err
1613
}
17-
errs := validator.Struct(opts)
18-
if len(errs) > 0 {
19-
for _, e := range errs {
20-
log.Errorf("Options error: %s.", e)
21-
}
22-
return nil, fmt.Errorf("opts are illegal")
14+
if err := validator.CheckStructError(opts).Combine(); err != nil {
15+
return nil, err
2316
}
2417
return options, nil
2518
}

0 commit comments

Comments
 (0)