Skip to content

Commit 50660ff

Browse files
authored
fix: raw write olares manifest (#63)
1 parent bc0bd5d commit 50660ff

File tree

2 files changed

+148
-96
lines changed

2 files changed

+148
-96
lines changed

pkg/appcfg/updater.go

Lines changed: 133 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,47 +10,139 @@ import (
1010

1111
// UpdateMetadataField updates one field under metadata: by in-place line replacement to preserve templating and comments.
1212
func UpdateMetadataField(appDir string, field string, value string) error {
13-
appCfgPath := filepath.Join(appDir, constants.AppCfgFileName)
14-
data, err := os.ReadFile(appCfgPath)
15-
if err != nil {
16-
return err
17-
}
18-
content := string(data)
19-
lines := strings.Split(content, "\n")
20-
inMetadata := false
21-
for i := 0; i < len(lines); i++ {
22-
line := lines[i]
23-
if !inMetadata {
24-
if strings.TrimSpace(line) == "metadata:" {
25-
inMetadata = true
26-
}
27-
continue
28-
}
29-
if len(line) > 0 && (line[0] != ' ' && line[0] != '\t') {
30-
break
31-
}
32-
trimmed := strings.TrimSpace(line)
33-
if strings.HasPrefix(trimmed, field+":") {
34-
colonIdx := strings.Index(line, ":")
35-
if colonIdx == -1 {
36-
continue
37-
}
38-
prefix := line[:colonIdx+1]
39-
after := line[colonIdx+1:]
40-
commentIdx := strings.Index(after, "#")
41-
var comment string
42-
if commentIdx >= 0 {
43-
comment = after[commentIdx:]
44-
}
45-
lines[i] = strings.TrimRight(prefix, " ") + " " + value
46-
if commentIdx >= 0 {
47-
lines[i] += " " + strings.TrimRight(comment, "\r\n")
48-
}
49-
break
50-
}
51-
}
52-
newContent := strings.Join(lines, "\n")
53-
return os.WriteFile(appCfgPath, []byte(newContent), 0644)
13+
appCfgPath := filepath.Join(appDir, constants.AppCfgFileName)
14+
data, err := os.ReadFile(appCfgPath)
15+
if err != nil {
16+
return err
17+
}
18+
content := string(data)
19+
lines := strings.Split(content, "\n")
20+
inMetadata := false
21+
for i := 0; i < len(lines); i++ {
22+
line := lines[i]
23+
if !inMetadata {
24+
if strings.TrimSpace(line) == "metadata:" {
25+
inMetadata = true
26+
}
27+
continue
28+
}
29+
if len(line) > 0 && (line[0] != ' ' && line[0] != '\t') {
30+
break
31+
}
32+
trimmed := strings.TrimSpace(line)
33+
if strings.HasPrefix(trimmed, field+":") {
34+
colonIdx := strings.Index(line, ":")
35+
if colonIdx == -1 {
36+
continue
37+
}
38+
prefix := line[:colonIdx+1]
39+
after := line[colonIdx+1:]
40+
commentIdx := strings.Index(after, "#")
41+
var comment string
42+
if commentIdx >= 0 {
43+
comment = after[commentIdx:]
44+
}
45+
lines[i] = strings.TrimRight(prefix, " ") + " " + value
46+
if commentIdx >= 0 {
47+
lines[i] += " " + strings.TrimRight(comment, "\r\n")
48+
}
49+
break
50+
}
51+
}
52+
newContent := strings.Join(lines, "\n")
53+
return os.WriteFile(appCfgPath, []byte(newContent), 0644)
5454
}
5555

56+
// UpdateEntrancesTitleAddDev appends "-dev" to every title under entrances list
57+
// It performs in-place line updates to preserve existing comments and templating.
58+
func UpdateEntrancesTitleAddDev(appDir string) error {
59+
appCfgPath := filepath.Join(appDir, constants.AppCfgFileName)
60+
data, err := os.ReadFile(appCfgPath)
61+
if err != nil {
62+
return err
63+
}
5664

65+
lines := strings.Split(string(data), "\n")
66+
inEntrances := false
67+
entrancesIndent := ""
68+
69+
// get leading whitespace (spaces/tabs) of a line
70+
leadingWS := func(s string) string {
71+
for i := 0; i < len(s); i++ {
72+
if s[i] != ' ' && s[i] != '\t' {
73+
return s[:i]
74+
}
75+
}
76+
return s
77+
}
78+
79+
for i := 0; i < len(lines); i++ {
80+
line := lines[i]
81+
trimmed := strings.TrimSpace(line)
82+
83+
if !inEntrances {
84+
if trimmed == "entrances:" {
85+
inEntrances = true
86+
entrancesIndent = leadingWS(line)
87+
}
88+
continue
89+
}
90+
91+
// leave entrances block when indentation returns, but ignore helm template lines like {{- end }}
92+
if len(line) > 0 {
93+
ws := leadingWS(line)
94+
if len(ws) <= len(entrancesIndent) && strings.TrimSpace(line) != "" && !strings.HasPrefix(trimmed, "#") && !strings.HasPrefix(trimmed, "{{") && !strings.HasPrefix(trimmed, "-") {
95+
inEntrances = false
96+
i-- // re-process this line outside entrances
97+
continue
98+
}
99+
}
100+
101+
if strings.HasPrefix(trimmed, "title:") {
102+
colonIdx := strings.Index(line, ":")
103+
if colonIdx == -1 {
104+
continue
105+
}
106+
prefix := line[:colonIdx+1]
107+
after := line[colonIdx+1:]
108+
commentIdx := strings.Index(after, "#")
109+
var valuePart string
110+
var comment string
111+
if commentIdx >= 0 {
112+
valuePart = after[:commentIdx]
113+
comment = after[commentIdx:]
114+
} else {
115+
valuePart = after
116+
}
117+
118+
v := strings.TrimSpace(valuePart)
119+
newV := v
120+
if len(v) >= 2 && ((v[0] == '"' && v[len(v)-1] == '"') || (v[0] == '\'' && v[len(v)-1] == '\'')) {
121+
quote := v[0]
122+
content := v[1 : len(v)-1]
123+
if strings.HasSuffix(content, "-dev") {
124+
newV = v
125+
} else {
126+
newV = string(quote) + content + "-dev" + string(quote)
127+
}
128+
} else if v != "" {
129+
if strings.HasSuffix(v, "-dev") {
130+
newV = v
131+
} else {
132+
newV = v + "-dev"
133+
}
134+
} else {
135+
newV = "-dev"
136+
}
137+
138+
newLine := strings.TrimRight(prefix, " ") + " " + newV
139+
if commentIdx >= 0 {
140+
newLine += " " + strings.TrimRight(comment, "\r\n")
141+
}
142+
lines[i] = newLine
143+
}
144+
}
145+
146+
newContent := strings.Join(lines, "\n")
147+
return os.WriteFile(appCfgPath, []byte(newContent), 0644)
148+
}

pkg/development/helm/chart.go

Lines changed: 15 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import (
1414

1515
"github.com/Masterminds/semver/v3"
1616
"github.com/beclab/devbox/pkg/appcfg"
17-
"github.com/beclab/devbox/pkg/constants"
18-
"github.com/beclab/devbox/pkg/utils"
1917
"gopkg.in/yaml.v2"
2018
"helm.sh/helm/v3/pkg/action"
2119
"helm.sh/helm/v3/pkg/chart"
@@ -118,75 +116,37 @@ func UpdateChartName(chart *chart.Chart, name, path string) error {
118116
}
119117

120118
func UpdateAppCfgVersion(owner, path string, version *semver.Version) error {
121-
appCfgYaml := filepath.Join(path, constants.AppCfgFileName)
122-
data, err := os.ReadFile(appCfgYaml)
119+
err := appcfg.UpdateMetadataField(path, "version", version.String())
123120
if err != nil {
124-
klog.Error("read app cfg error, ", err, ", ", appCfgYaml)
121+
klog.Infof("failed to update metadata version %v", err)
125122
return err
126123
}
127-
//var appCfg application.AppConfiguration
128-
//err = yaml.Unmarshal(data, &appCfg)
129-
130-
appCfg, err := utils.GetAppConfig(owner, data)
131-
if err != nil {
132-
klog.Error("parse appcfg error, ", err)
133-
return err
134-
}
135-
if version != nil {
136-
appCfg.Metadata.Version = version.String()
137-
}
138-
data, err = yaml.Marshal(&appCfg)
139-
if err != nil {
140-
klog.Error("encode appcfg error, ", err)
141-
return err
142-
}
143-
err = os.WriteFile(appCfgYaml, data, 0644)
144-
if err != nil {
145-
klog.Error("write file OlaresManifest.yaml error, ", err)
146-
return err
147-
}
148-
149124
return nil
150125
}
151126

152127
func UpdateAppCfgName(owner, name, path string) error {
153128
appDevName := name + "-dev"
154-
appCfgYaml := filepath.Join(path, constants.AppCfgFileName)
155-
data, err := os.ReadFile(appCfgYaml)
156-
if err != nil {
157-
klog.Error("read app cfg error, ", err, ", ", appCfgYaml)
158-
return err
159-
}
160129

161-
//var appCfg application.AppConfiguration
162-
//err = yaml.Unmarshal(data, &appCfg)
163-
appCfg, err := utils.GetAppConfig(owner, data)
164-
if err != nil {
165-
klog.Error("parse OlaresManifest.yaml error, ", err)
130+
// update metadata fields directly using in-place updater
131+
if err := appcfg.UpdateMetadataField(path, "name", appDevName); err != nil {
132+
klog.Infof("failed to update metadata name %v", err)
133+
166134
return err
167135
}
136+
if err := appcfg.UpdateMetadataField(path, "appid", appDevName); err != nil {
137+
klog.Infof("failed to update metadata appid %v", err)
168138

169-
appCfg.Metadata.Name = appDevName
170-
appCfg.Metadata.AppID = appDevName
171-
appCfg.Metadata.Title = appDevName
172-
173-
//if version != nil {
174-
// appCfg.Metadata.Version = version.String()
175-
//}
176-
177-
for i, e := range appCfg.Entrances {
178-
appCfg.Entrances[i].Title = e.Title + "-dev"
139+
return err
179140
}
141+
if err := appcfg.UpdateMetadataField(path, "title", appDevName); err != nil {
142+
klog.Infof("failed to update metadata title %v", err)
180143

181-
data, err = yaml.Marshal(&appCfg)
182-
if err != nil {
183-
klog.Error("encode appcfg error, ", err)
184144
return err
185145
}
186146

187-
err = os.WriteFile(appCfgYaml, data, 0644)
188-
if err != nil {
189-
klog.Error("write file OlaresManifest.yaml error, ", err)
147+
if err := appcfg.UpdateEntrancesTitleAddDev(path); err != nil {
148+
klog.Infof("failed to update entrances title %v", err)
149+
190150
return err
191151
}
192152

@@ -197,7 +157,7 @@ func UpgradeChartVersion(chart *chart.Chart, name, path string, version *semver.
197157
return UpdateChartVersion(chart, name, path, version)
198158
}
199159

200-
// try to render the helm chart, and return the rendered manifest or error
160+
// DryRun try to render the helm chart, and return the rendered manifest or error
201161
func DryRun(ctx context.Context, kubeConfig *rest.Config, namespace, app, path string, vals map[string]interface{}) (string, error) {
202162
settings := cli.New()
203163
settings.KubeAPIServer = kubeConfig.Host

0 commit comments

Comments
 (0)