From c421c1e85429d3cb39272df0f71f8c375df7e68e Mon Sep 17 00:00:00 2001 From: huangmengxuan Date: Wed, 1 Apr 2026 15:38:47 +0800 Subject: [PATCH 1/2] feat: add TestGenerateShortcutsJSON for registry shortcut export Add a test that exports all shortcuts as JSON when SHORTCUTS_OUTPUT env var is set, enabling the registry repo to extract shortcut metadata without depending on a dump-shortcuts CLI command. Change-Id: I9e450fdcb579d6a21ac8ec36e4197728bb7408bb Co-Authored-By: Claude Opus 4.6 --- shortcuts/register_test.go | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/shortcuts/register_test.go b/shortcuts/register_test.go index 48b72c39e..2d169617f 100644 --- a/shortcuts/register_test.go +++ b/shortcuts/register_test.go @@ -4,6 +4,10 @@ package shortcuts import ( + "encoding/json" + "os" + "path/filepath" + "strings" "testing" "github.com/larksuite/cli/internal/cmdutil" @@ -88,3 +92,39 @@ func TestRegisterShortcutsReusesExistingServiceCommand(t *testing.T) { t.Fatal("base workspace shortcut not mounted on existing service command") } } + +func TestGenerateShortcutsJSON(t *testing.T) { + output := os.Getenv("SHORTCUTS_OUTPUT") + if output == "" { + t.Skip("set SHORTCUTS_OUTPUT env to generate shortcuts.json") + } + + shortcuts := AllShortcuts() + + type entry struct { + Verb string `json:"verb"` + Description string `json:"description"` + Scopes []string `json:"scopes"` + } + grouped := make(map[string][]entry) + for _, s := range shortcuts { + verb := strings.TrimPrefix(s.Command, "+") + grouped[s.Service] = append(grouped[s.Service], entry{ + Verb: verb, + Description: s.Description, + Scopes: s.ScopesForIdentity("user"), + }) + } + + data, err := json.MarshalIndent(grouped, "", " ") + if err != nil { + t.Fatalf("marshal shortcuts: %v", err) + } + if err := os.MkdirAll(filepath.Dir(output), 0o755); err != nil { + t.Fatalf("mkdir: %v", err) + } + if err := os.WriteFile(output, data, 0o644); err != nil { + t.Fatalf("write file: %v", err) + } + t.Logf("wrote %d bytes to %s", len(data), output) +} From 0d0c64dbf8cbe03d1dd2cad187427f5ab1c2fd42 Mon Sep 17 00:00:00 2001 From: huangmengxuan Date: Wed, 1 Apr 2026 15:44:01 +0800 Subject: [PATCH 2/2] fix: skip fetch_meta.py when meta_data.json already exists Avoid overwriting a locally generated meta_data.json with the remote version during build. Change-Id: Ic30d70b9fa9d9c8e060879e4000c53c58f3aa525 Co-Authored-By: Claude Opus 4.6 --- scripts/fetch_meta.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/fetch_meta.py b/scripts/fetch_meta.py index 4c0145b45..b7ab0908f 100644 --- a/scripts/fetch_meta.py +++ b/scripts/fetch_meta.py @@ -67,8 +67,24 @@ def main(): parser = argparse.ArgumentParser(description="Fetch meta_data.json for build-time embedding") parser.add_argument("--brand", default="feishu", choices=["feishu", "lark"], help="API brand (default: feishu)") + parser.add_argument("--force", action="store_true", + help="force refresh from remote even if local file exists") args = parser.parse_args() + if os.path.exists(OUT_PATH) and not args.force: + if os.path.isfile(OUT_PATH): + try: + with open(OUT_PATH, "r", encoding="utf-8") as fp: + local = json.load(fp) + if local.get("services"): + print(f"fetch-meta: {OUT_PATH} already exists, skipping (use --force to re-fetch)", file=sys.stderr) + return + print(f"fetch-meta: {OUT_PATH} has no services, re-fetching", file=sys.stderr) + except (OSError, json.JSONDecodeError): + print(f"fetch-meta: {OUT_PATH} is invalid JSON, re-fetching", file=sys.stderr) + else: + print(f"fetch-meta: {OUT_PATH} is not a file, re-fetching", file=sys.stderr) + data = fetch_remote(args.brand) count = len(data.get("services", [])) print(f"fetch-meta: OK, {count} services from remote API", file=sys.stderr)