From 8b40903a449a5a8bd6fd6a5458d235864e261634 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 9 Jun 2026 21:40:15 +0000
Subject: [PATCH 1/2] [Crane:
crane-migration-python-to-go-full-apm-cli-rewrite] Iteration 79: fix cache
subcommand --help routing; add --force/--yes flags and output parity
Changes:
- cmd/apm/cmd_cache.go: fix runCache to route subcommand --help to the
subcommand handler instead of intercepting all --help flags at the
top level (cache clean --help and cache prune --help now show their
own usage, not the top-level cache menu)
- cmd/apm/cmd_cache.go: add -f/--force and -y/--yes flags to cache clean
help text; align output messages to Python ('Cleaning cache...' +
'Cache cleaned.' instead of 'Cache cleared:
')
- cmd/apm/parity_harness_test.go: add 3 new parity contract tests
(GoCacheCleanHelp, GoCachePruneHelp, GoCacheCleanOutputMessages)
Score: 1.0 (858/858 parity, 903 Go tests, 247 Python tests, all 13 gates pass)
Run: https://github.com/githubnext/apm/actions/runs/27236411257
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
cmd/apm/cmd_cache.go | 24 +++++++++++-------
cmd/apm/parity_harness_test.go | 46 ++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/cmd/apm/cmd_cache.go b/cmd/apm/cmd_cache.go
index ec8b9112..a6149cc4 100644
--- a/cmd/apm/cmd_cache.go
+++ b/cmd/apm/cmd_cache.go
@@ -44,11 +44,12 @@ func runCache(args []string) int {
return 0
}
- for _, a := range args {
- if a == "--help" || a == "-h" {
- printCacheHelp()
- return 0
- }
+ // Only intercept --help/-h when it is the very first argument (top-level
+ // cache help). When a subcommand precedes --help (e.g. "cache clean --help"),
+ // delegate to the subcommand handler so it can show its own usage.
+ if args[0] == "--help" || args[0] == "-h" {
+ printCacheHelp()
+ return 0
}
sub := args[0]
@@ -109,7 +110,9 @@ func runCacheClean(args []string) int {
fmt.Println(" Remove all cached content")
fmt.Println()
fmt.Println("Options:")
- fmt.Println(" --help Show this message and exit.")
+ fmt.Println(" -f, --force Skip confirmation prompt")
+ fmt.Println(" -y, --yes Skip confirmation prompt")
+ fmt.Println(" --help Show this message and exit.")
return 0
}
}
@@ -121,7 +124,8 @@ func runCacheClean(args []string) int {
fmt.Fprintf(os.Stderr, "[x] Failed to create cache dir: %v\n", mkErr)
return 1
}
- fmt.Printf("[+] Cache cleared: %s\n", dir)
+ fmt.Println("[*] Cleaning cache...")
+ fmt.Println("[+] Cache cleaned.")
return 0
}
fmt.Fprintf(os.Stderr, "[x] Failed to read cache dir: %v\n", err)
@@ -133,7 +137,8 @@ func runCacheClean(args []string) int {
return 1
}
}
- fmt.Printf("[+] Cache cleared: %s\n", dir)
+ fmt.Println("[*] Cleaning cache...")
+ fmt.Println("[+] Cache cleaned.")
return 0
}
@@ -145,7 +150,8 @@ func runCachePrune(args []string) int {
fmt.Println(" Remove cache entries older than N days")
fmt.Println()
fmt.Println("Options:")
- fmt.Println(" --days INTEGER Remove entries older than N days. [default: 30]")
+ fmt.Println(" --days INTEGER Remove entries not accessed within this many days")
+ fmt.Println(" [default: 30]")
fmt.Println(" --help Show this message and exit.")
return 0
}
diff --git a/cmd/apm/parity_harness_test.go b/cmd/apm/parity_harness_test.go
index ea33382f..96bc94c4 100644
--- a/cmd/apm/parity_harness_test.go
+++ b/cmd/apm/parity_harness_test.go
@@ -375,6 +375,52 @@ func TestParityHarnessGoCacheInfo(t *testing.T) {
}
}
+// TestParityHarnessGoCacheCleanHelp verifies `apm cache clean --help` routes
+// to the subcommand help (not the top-level cache help).
+func TestParityHarnessGoCacheCleanHelp(t *testing.T) {
+ r := runBothInTempRepo(t, minimalApmYML, "cache", "clean", "--help")
+ assertGoExitCode(t, r, 0)
+ assertPythonVsGoExitCode(t, r)
+ if !strings.Contains(r.GoStdout, "Usage: apm cache clean") {
+ t.Errorf("Go `apm cache clean --help` does not show subcommand help: %q", r.GoStdout)
+ }
+ if !strings.Contains(r.GoStdout, "--force") || !strings.Contains(r.GoStdout, "--yes") {
+ t.Errorf("Go `apm cache clean --help` missing --force/--yes flags: %q", r.GoStdout)
+ }
+}
+
+// TestParityHarnessGoCachePruneHelp verifies `apm cache prune --help` routes
+// to the subcommand help (not the top-level cache help).
+func TestParityHarnessGoCachePruneHelp(t *testing.T) {
+ r := runBothInTempRepo(t, minimalApmYML, "cache", "prune", "--help")
+ assertGoExitCode(t, r, 0)
+ assertPythonVsGoExitCode(t, r)
+ if !strings.Contains(r.GoStdout, "Usage: apm cache prune") {
+ t.Errorf("Go `apm cache prune --help` does not show subcommand help: %q", r.GoStdout)
+ }
+ if !strings.Contains(r.GoStdout, "--days") {
+ t.Errorf("Go `apm cache prune --help` missing --days flag: %q", r.GoStdout)
+ }
+}
+
+// TestParityHarnessGoCacheCleanOutputMessages verifies `apm cache clean --yes`
+// outputs the same messages as Python.
+func TestParityHarnessGoCacheCleanOutputMessages(t *testing.T) {
+ // Use an isolated temp cache dir so the test does not clear the user's real
+ // cache and both CLIs operate on the same fresh directory.
+ cacheDir := t.TempDir()
+ t.Setenv("APM_CACHE_DIR", cacheDir)
+ r := runBothInTempRepo(t, minimalApmYML, "cache", "clean", "--yes")
+ assertGoExitCode(t, r, 0)
+ assertPythonVsGoExitCode(t, r)
+ if !strings.Contains(r.GoStdout, "Cleaning cache") {
+ t.Errorf("Go `apm cache clean --yes` missing 'Cleaning cache' in stdout: %q", r.GoStdout)
+ }
+ if !strings.Contains(r.GoStdout, "Cache cleaned") {
+ t.Errorf("Go `apm cache clean --yes` missing 'Cache cleaned' in stdout: %q", r.GoStdout)
+ }
+}
+
// TestParityHarnessGoConfigHelp verifies `apm config --help`.
func TestParityHarnessGoConfigHelp(t *testing.T) {
out, _, code := runGo(t, "config", "--help")
From f02847267a544d9700e885f6edebe15f4c4aa406 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Tue, 9 Jun 2026 21:40:20 +0000
Subject: [PATCH 2/2] ci: trigger checks