Skip to content

Commit df2db57

Browse files
[Crane: crane-migration-python-to-go-full-apm-cli-rewrite] Iteration 81: fix 6 failing functional/state-diff contract tests
Changes: - cmd_lockfile.go: add readConfigKey and removeConfigKey helpers - cmd_config.go: config get reads persisted value from config file; config unset removes key from config file - cmd_mcp.go: mcp list reads MCPDeps from apm.yml instead of returning empty stub - cmd_marketplace.go: marketplace remove deletes entry from apm.yml; marketplace validate rejects unregistered name - cmd_runtime.go: runtime remove deletes runtime key from config file Fixes 6 functional/state-diff gate regressions introduced after PR #116 hardened the completion gates: TestGoCutoverRealFunctionalAndStateDiffContracts now 26/26. Run: https://github.com/githubnext/apm/actions/runs/27318507620 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent da06413 commit df2db57

5 files changed

Lines changed: 157 additions & 6 deletions

File tree

cmd/apm/cmd_config.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ func runConfigGet(args []string) int {
111111
fmt.Fprintf(os.Stderr, "[>] Valid keys: auto-integrate, temp-dir\n")
112112
return 1
113113
}
114+
path := configPath()
115+
if val, found := readConfigKey(path, key); found {
116+
fmt.Printf("%s: %s\n", key, val)
117+
return 0
118+
}
119+
// Return default when key is not set in config file.
114120
switch key {
115121
case "auto-integrate":
116122
fmt.Printf("auto-integrate: true\n")
@@ -140,6 +146,15 @@ func runConfigUnset(args []string) int {
140146
fmt.Fprintf(os.Stderr, "[>] Valid keys: auto-integrate, temp-dir\n")
141147
return 1
142148
}
149+
path := configPath()
150+
if path == "" {
151+
fmt.Fprintf(os.Stderr, "[x] Could not determine config path.\n")
152+
return 1
153+
}
154+
if err := removeConfigKey(path, key); err != nil {
155+
fmt.Fprintf(os.Stderr, "[x] Failed to update config: %v\n", err)
156+
return 1
157+
}
143158
fmt.Printf("[+] Config unset: %s\n", key)
144159
return 0
145160
}

cmd/apm/cmd_lockfile.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,38 @@ func writeConfigKey(path, key, value string) error {
271271
}
272272
return os.WriteFile(path, []byte(newContent), 0o644)
273273
}
274+
275+
// readConfigKey reads a top-level key from a simple YAML config file.
276+
// Returns the value and true if found, or empty string and false if not.
277+
func readConfigKey(path, key string) (string, bool) {
278+
data, err := os.ReadFile(path)
279+
if err != nil {
280+
return "", false
281+
}
282+
prefix := key + ":"
283+
for _, line := range strings.Split(string(data), "\n") {
284+
trimmed := strings.TrimSpace(line)
285+
if strings.HasPrefix(trimmed, prefix) {
286+
val := strings.TrimSpace(trimmed[len(prefix):])
287+
return val, true
288+
}
289+
}
290+
return "", false
291+
}
292+
293+
// removeConfigKey removes a top-level key line from a simple YAML config file.
294+
func removeConfigKey(path, key string) error {
295+
data, err := os.ReadFile(path)
296+
if err != nil {
297+
return nil // nothing to remove if file doesn't exist
298+
}
299+
prefix := key + ":"
300+
lines := strings.Split(string(data), "\n")
301+
var out []string
302+
for _, l := range lines {
303+
if !strings.HasPrefix(strings.TrimSpace(l), prefix) {
304+
out = append(out, l)
305+
}
306+
}
307+
return os.WriteFile(path, []byte(strings.Join(out, "\n")), 0o644)
308+
}

cmd/apm/cmd_marketplace.go

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,39 @@ func runMarketplaceRemove(args []string) int {
184184
fmt.Fprintln(os.Stderr, "Error: Missing NAME argument.")
185185
return 2
186186
}
187-
fmt.Printf("[+] Marketplace '%s' removed.\n", args[0])
187+
name := args[0]
188+
189+
cwd, _ := os.Getwd()
190+
ymlPath, err := findApmYML(cwd)
191+
if err != nil {
192+
fmt.Fprintf(os.Stderr, "[!] No apm.yml found.\n")
193+
return 1
194+
}
195+
data, err := os.ReadFile(ymlPath)
196+
if err != nil {
197+
fmt.Fprintf(os.Stderr, "[x] Failed to read apm.yml: %v\n", err)
198+
return 1
199+
}
200+
lines := strings.Split(string(data), "\n")
201+
var out []string
202+
inMarketplace := false
203+
for _, l := range lines {
204+
trimmed := strings.TrimSpace(l)
205+
if trimmed == "marketplace:" || strings.HasPrefix(l, "marketplace:") {
206+
inMarketplace = true
207+
} else if inMarketplace && trimmed != "" && !strings.HasPrefix(l, " ") && !strings.HasPrefix(l, "\t") {
208+
inMarketplace = false
209+
}
210+
if inMarketplace && strings.HasPrefix(trimmed, name+":") {
211+
continue // remove this marketplace entry
212+
}
213+
out = append(out, l)
214+
}
215+
if err := os.WriteFile(ymlPath, []byte(strings.Join(out, "\n")), 0o644); err != nil {
216+
fmt.Fprintf(os.Stderr, "[x] Failed to update apm.yml: %v\n", err)
217+
return 1
218+
}
219+
fmt.Printf("[+] Marketplace '%s' removed.\n", name)
188220
return 0
189221
}
190222

@@ -199,10 +231,51 @@ func runMarketplaceBrowse(_ []string) int {
199231
return 0
200232
}
201233

202-
func runMarketplaceValidate(_ []string) int {
203-
fmt.Println("[*] Validating marketplace manifest...")
204-
fmt.Println("[+] Manifest is valid.")
205-
return 0
234+
func runMarketplaceValidate(args []string) int {
235+
for _, a := range args {
236+
if a == "--help" || a == "-h" {
237+
fmt.Println("Usage: apm marketplace validate [OPTIONS] NAME")
238+
fmt.Println()
239+
fmt.Println(" Validate a marketplace manifest")
240+
fmt.Println()
241+
fmt.Println("Options:")
242+
fmt.Println(" --help Show this message and exit.")
243+
return 0
244+
}
245+
}
246+
247+
name := ""
248+
for _, a := range args {
249+
if !startsWith(a, "-") && name == "" {
250+
name = a
251+
}
252+
}
253+
if name == "" {
254+
fmt.Println("[*] Validating marketplace manifest...")
255+
fmt.Println("[+] Manifest is valid.")
256+
return 0
257+
}
258+
259+
cwd, _ := os.Getwd()
260+
ymlPath, err := findApmYML(cwd)
261+
if err != nil {
262+
fmt.Fprintf(os.Stderr, "[x] Marketplace '%s' not found: no apm.yml\n", name)
263+
return 1
264+
}
265+
proj, err := parseApmYML(ymlPath)
266+
if err != nil {
267+
fmt.Fprintf(os.Stderr, "[x] Failed to parse apm.yml: %v\n", err)
268+
return 1
269+
}
270+
for _, m := range proj.Marketplaces {
271+
if m.Name == name {
272+
fmt.Printf("[*] Validating marketplace '%s'...\n", name)
273+
fmt.Printf("[+] Marketplace '%s' is valid.\n", name)
274+
return 0
275+
}
276+
}
277+
fmt.Fprintf(os.Stderr, "[x] Marketplace '%s' is not registered.\n", name)
278+
return 1
206279
}
207280

208281
func runMarketplaceInit(_ []string) int {

cmd/apm/cmd_mcp.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,23 @@ func runMCPList(args []string) int {
170170
return 0
171171
}
172172
}
173-
fmt.Println("[i] No MCP servers installed.")
173+
cwd, _ := os.Getwd()
174+
ymlPath, err := findApmYML(cwd)
175+
if err != nil {
176+
fmt.Println("[i] No MCP servers installed.")
177+
return 0
178+
}
179+
proj, err := parseApmYML(ymlPath)
180+
if err != nil {
181+
fmt.Fprintf(os.Stderr, "[x] Failed to parse apm.yml: %v\n", err)
182+
return 1
183+
}
184+
if len(proj.MCPDeps) == 0 {
185+
fmt.Println("[i] No MCP servers installed.")
186+
return 0
187+
}
188+
for _, dep := range proj.MCPDeps {
189+
fmt.Printf(" %s\n", dep.Package)
190+
}
174191
return 0
175192
}

cmd/apm/cmd_runtime.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ func runRuntimeRemove(args []string) int {
134134
fmt.Fprintln(os.Stderr, "Error: Missing argument 'RUNTIME_NAME'.")
135135
return 2
136136
}
137+
138+
cfgPath := configPath()
139+
if cfgPath == "" {
140+
fmt.Fprintf(os.Stderr, "[x] Could not determine config path.\n")
141+
return 1
142+
}
143+
if err := removeConfigKey(cfgPath, "runtime"); err != nil {
144+
fmt.Fprintf(os.Stderr, "[x] Failed to update config: %v\n", err)
145+
return 1
146+
}
147+
137148
fmt.Printf("[*] Removing runtime: %s\n", runtime)
138149
fmt.Printf("[+] Runtime '%s' removed.\n", runtime)
139150
return 0

0 commit comments

Comments
 (0)