Skip to content

Commit 3cd99e5

Browse files
committed
added support for categorisation
1 parent 5a9f4bc commit 3cd99e5

File tree

12 files changed

+424
-329
lines changed

12 files changed

+424
-329
lines changed

api/helm-app/gRPC/applicationClient.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ func NewHelmAppClientImpl(logger *zap.SugaredLogger,
7272
}
7373
}
7474

75+
// CATEGORY=INFRA_SETUP
7576
type HelmClientConfig struct {
7677
Url string `env:"HELM_CLIENT_URL" envDefault:"127.0.0.1:50051"`
7778
}

api/helm-app/service/HelmAppService.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ func NewHelmAppServiceImpl(Logger *zap.SugaredLogger, clusterService cluster.Clu
146146
}
147147
}
148148

149+
// CATEGORY=CD
149150
type HelmReleaseConfig struct {
150151
RevisionHistoryLimitDevtronApp int `env:"REVISION_HISTORY_LIMIT_DEVTRON_APP" envDefault:"1"`
151152
RevisionHistoryLimitHelmApp int `env:"REVISION_HISTORY_LIMIT_HELM_APP" envDefault:"1"`

client/dashboard/Config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/caarlos0/env"
2121
)
2222

23+
// CATEGORY=INFRA_SETUP
2324
type Config struct {
2425
Host string `env:"DASHBOARD_HOST" envDefault:"localhost"`
2526
Port string `env:"DASHBOARD_PORT" envDefault:"3000"`

client/gitSensor/GitSensorClient.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func NewGitSensorClient(logger *zap.SugaredLogger, config *ClientConfig) (*Clien
7979
return client, nil
8080
}
8181

82+
// CATEGORY=INFRA_SETUP
8283
type ClientConfig struct {
8384
Url string `env:"GIT_SENSOR_URL" envDefault:"127.0.0.1:7070"`
8485
Protocol string `env:"GIT_SENSOR_PROTOCOL" envDefault:"REST"`

env_gen.md

Lines changed: 299 additions & 267 deletions
Large diffs are not rendered by default.

fetchAllEnv/fetchAllEnv.go

Lines changed: 115 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package main
1818

1919
import (
20+
"errors"
2021
"go/ast"
2122
"go/parser"
2223
"go/token"
@@ -31,13 +32,23 @@ import (
3132

3233
type EnvField struct {
3334
Env string
35+
EnvType string
3436
EnvValue string
3537
EnvDescription string
3638
EnvPossibleValues string
3739
EnvDeprecated string
3840
}
3941

42+
type CategoryField struct {
43+
Category string
44+
Fields []EnvField
45+
}
46+
4047
const (
48+
categoryCommentStructPrefix = "CATEGORY="
49+
defaultCategory = "DEVTRON"
50+
deprecatedDefaultValue = "false"
51+
4152
envFieldTypeTag = "env"
4253
envDefaultFieldTypeTag = "envDefault"
4354
envDescriptionFieldTypeTag = "envDescription"
@@ -47,44 +58,28 @@ const (
4758
)
4859

4960
const MarkdownTemplate = `
50-
## Devtron Environment Variables
61+
{{range . }}
62+
## {{ .Category }} Related Environment Variables
5163
| Key | Value | Description | Possible values | Deprecated |
5264
|-------|--------------|-------------------|-----------------------|------------------|
53-
{{range .}} | {{ .Env }} | {{ .EnvValue }} | {{ .EnvDescription }} | {{ .EnvPossibleValues }} | {{ .EnvDeprecated }} |
65+
{{range .Fields }} | {{ .Env }} | {{ .EnvValue }} | {{ .EnvDescription }} | {{ .EnvPossibleValues }} | {{ .EnvDeprecated }} |
66+
{{end}}
5467
{{end}}`
5568

56-
func writeToFile(allFields []EnvField) {
57-
sort.Slice(allFields, func(i, j int) bool {
58-
return allFields[i].Env < allFields[j].Env
59-
})
60-
61-
file, err := os.Create(MARKDOWN_FILENAME)
62-
if err != nil {
63-
panic(err)
64-
}
65-
defer file.Close()
66-
67-
tmpl, err := template.New("markdown").Parse(MarkdownTemplate)
68-
if err != nil {
69-
panic(err)
70-
}
71-
72-
err = tmpl.Execute(file, allFields)
73-
if err != nil {
74-
panic(err)
75-
}
69+
func main() {
70+
WalkThroughProject()
71+
return
7672
}
7773

7874
func WalkThroughProject() {
79-
var allFields []EnvField
75+
categoryFieldsMap := make(map[string][]EnvField)
8076
uniqueKeys := make(map[string]bool)
81-
8277
err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
8378
if err != nil {
8479
return err
8580
}
8681
if !info.IsDir() && strings.HasSuffix(path, ".go") {
87-
err = processGoFile(path, &allFields, &uniqueKeys)
82+
err = processGoFile(path, categoryFieldsMap, uniqueKeys)
8883
if err != nil {
8984
log.Println("error in processing go file", err)
9085
return err
@@ -95,14 +90,53 @@ func WalkThroughProject() {
9590
if err != nil {
9691
return
9792
}
98-
writeToFile(allFields)
93+
writeToFile(categoryFieldsMap)
9994
}
10095

101-
func convertTagToStructTag(tag string) reflect.StructTag {
102-
return reflect.StructTag(strings.Split(tag, "`")[1])
96+
func processGoFile(filePath string, categoryFieldsMap map[string][]EnvField, uniqueKeys map[string]bool) error {
97+
fset := token.NewFileSet()
98+
node, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
99+
if err != nil {
100+
log.Println("error parsing file:", err)
101+
return err
102+
}
103+
ast.Inspect(node, func(n ast.Node) bool {
104+
if genDecl, ok := n.(*ast.GenDecl); ok {
105+
// checking if type declaration, one of [func, map, struct, array, channel, interface]
106+
if genDecl.Tok == token.TYPE {
107+
for _, spec := range genDecl.Specs {
108+
if typeSpec, ok := spec.(*ast.TypeSpec); ok {
109+
// only checking struct type declarations
110+
if structType, ok2 := typeSpec.Type.(*ast.StructType); ok2 {
111+
allFields := make([]EnvField, 0, len(structType.Fields.List))
112+
for _, field := range structType.Fields.List {
113+
if field.Tag != nil {
114+
envField := getEnvKeyAndValue(field)
115+
envKey := envField.Env
116+
if len(envKey) == 0 || uniqueKeys[envKey] {
117+
continue
118+
}
119+
allFields = append(allFields, envField)
120+
uniqueKeys[envKey] = true
121+
}
122+
}
123+
if len(allFields) > 0 {
124+
category := getCategoryForAStruct(genDecl)
125+
categoryFieldsMap[category] = append(categoryFieldsMap[category], allFields...)
126+
}
127+
}
128+
}
129+
}
130+
}
131+
}
132+
return true
133+
})
134+
return nil
103135
}
104136

105-
func getEnvKeyAndValue(tag reflect.StructTag) EnvField {
137+
func getEnvKeyAndValue(field *ast.Field) EnvField {
138+
tag := reflect.StructTag(strings.Trim(field.Tag.Value, "`")) // remove surrounding backticks
139+
106140
envKey := addReadmeTableDelimiterEscapeChar(tag.Get(envFieldTypeTag))
107141
envValue := addReadmeTableDelimiterEscapeChar(tag.Get(envDefaultFieldTypeTag))
108142
envDescription := addReadmeTableDelimiterEscapeChar(tag.Get(envDescriptionFieldTypeTag))
@@ -112,51 +146,70 @@ func getEnvKeyAndValue(tag reflect.StructTag) EnvField {
112146
if value, ok := os.LookupEnv(envKey); ok {
113147
envValue = value
114148
}
115-
return EnvField{
149+
env := EnvField{
116150
Env: envKey,
117151
EnvValue: envValue,
118152
EnvDescription: envDescription,
119153
EnvPossibleValues: envPossibleValues,
120154
EnvDeprecated: envDeprecated,
121155
}
156+
if indent, ok := field.Type.(*ast.Ident); ok && indent != nil {
157+
env.EnvType = indent.Name
158+
}
159+
if len(envDeprecated) == 0 {
160+
env.EnvDeprecated = deprecatedDefaultValue
161+
}
162+
return env
163+
}
164+
165+
func getCategoryForAStruct(genDecl *ast.GenDecl) string {
166+
category := defaultCategory
167+
if genDecl.Doc != nil {
168+
commentTexts := strings.Split(genDecl.Doc.Text(), "\n")
169+
for _, comment := range commentTexts {
170+
commentText := strings.TrimPrefix(strings.ReplaceAll(comment, " ", ""), "//") // this can happen if comment group is in /* */
171+
if strings.HasPrefix(commentText, categoryCommentStructPrefix) {
172+
categories := strings.Split(strings.TrimPrefix(commentText, categoryCommentStructPrefix), ",")
173+
if len(categories) > 0 && len(categories[0]) > 0 { //only supporting one category as of now
174+
category = categories[0] //overriding category
175+
break
176+
}
177+
}
178+
}
179+
}
180+
return category
122181
}
123182

124183
func addReadmeTableDelimiterEscapeChar(s string) string {
125184
return strings.ReplaceAll(s, "|", `\|`)
126185
}
127186

128-
func processGoFile(filePath string, allFields *[]EnvField, uniqueKeys *map[string]bool) error {
129-
fset := token.NewFileSet()
130-
node, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
131-
if err != nil {
132-
log.Println("error parsing file:", err)
133-
return err
187+
func writeToFile(categoryFieldsMap map[string][]EnvField) {
188+
cfs := make([]CategoryField, 0, len(categoryFieldsMap))
189+
for category, allFields := range categoryFieldsMap {
190+
sort.Slice(allFields, func(i, j int) bool {
191+
return allFields[i].Env < allFields[j].Env
192+
})
193+
194+
cfs = append(cfs, CategoryField{
195+
Category: category,
196+
Fields: allFields,
197+
})
134198
}
135-
136-
ast.Inspect(node, func(n ast.Node) bool {
137-
switch x := n.(type) {
138-
case *ast.TypeSpec:
139-
if structType, ok := x.Type.(*ast.StructType); ok {
140-
for _, field := range structType.Fields.List {
141-
if field.Tag != nil {
142-
strippedTags := convertTagToStructTag(field.Tag.Value)
143-
envField := getEnvKeyAndValue(strippedTags)
144-
envKey := envField.Env
145-
if len(envKey) == 0 || (*uniqueKeys)[envKey] {
146-
continue
147-
}
148-
*allFields = append(*allFields, envField)
149-
(*uniqueKeys)[envKey] = true
150-
}
151-
}
152-
}
153-
}
154-
return true
199+
sort.Slice(cfs, func(i, j int) bool {
200+
return cfs[i].Category < cfs[j].Category
155201
})
156-
return nil
157-
}
158-
159-
func main() {
160-
WalkThroughProject()
161-
return
202+
file, err := os.Create(MARKDOWN_FILENAME)
203+
if err != nil && !errors.Is(err, os.ErrExist) {
204+
panic(err)
205+
}
206+
defer file.Close()
207+
tmpl, err := template.New("markdown").Parse(MarkdownTemplate)
208+
if err != nil {
209+
panic(err)
210+
}
211+
err = tmpl.Execute(file, cfs)
212+
if err != nil {
213+
panic(err)
214+
}
162215
}

pkg/app/AppService.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import (
7575
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7676
)
7777

78+
// CATEGORY=CD
7879
type AppServiceConfig struct {
7980
CdPipelineStatusCronTime string `env:"CD_PIPELINE_STATUS_CRON_TIME" envDefault:"*/2 * * * *"`
8081
CdHelmPipelineStatusCronTime string `env:"CD_HELM_PIPELINE_STATUS_CRON_TIME" envDefault:"*/2 * * * *"`

pkg/auth/authorisation/casbin/rbac.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type CacheData struct {
7272
enforceReqCounter int64
7373
}
7474

75+
// CATEGORY=RBAC
7576
type EnforcerConfig struct {
7677
CacheEnabled bool `env:"ENFORCER_CACHE" envDefault:"false"`
7778
CacheExpirationInSecs int `env:"ENFORCER_CACHE_EXPIRATION_IN_SEC" envDefault:"86400"`

pkg/dex/Config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package dex
1818

1919
import "github.com/caarlos0/env"
2020

21+
// CATEGORY=INFRA_SETUP
2122
type Config struct {
2223
Host string `env:"DEX_HOST" envDefault:"http://localhost"`
2324
Port string `env:"DEX_PORT" envDefault:"5556"`

pkg/pipeline/types/CiCdConfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type CancelWfRequestDto struct {
5252

5353
// build infra configurations like ciTimeout,ciCpuLimit,ciMemLimit,ciCpuReq,ciMemReq are being managed by infraConfig service
5454

55+
// CATEGORY=CI_RUNNER
5556
type CiCdConfig struct {
5657
// from ciConfig
5758
DefaultCacheBucket string `env:"DEFAULT_CACHE_BUCKET" envDefault:"ci-caching"`

0 commit comments

Comments
 (0)