From 63f4d08a2935e3d052d7bca1954b5beaf84b3ddf Mon Sep 17 00:00:00 2001 From: ryank90 Date: Tue, 22 Sep 2026 16:19:48 +0100 Subject: [PATCH 1/2] fix(serverless): drop activity and errorRate from apps list --sort Those orderings stay in the API enum, but the server returns 422 until traffic metrics exist. The CLI only offers createdAt and name. --- docs/runware_serverless_apps_list.md | 2 +- internal/cmd/serverless/apps.go | 21 +++++++++++++++++++-- internal/cmd/serverless/display_test.go | 23 +++++++++++------------ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/runware_serverless_apps_list.md b/docs/runware_serverless_apps_list.md index 80d6a0a..6fa7ac1 100644 --- a/docs/runware_serverless_apps_list.md +++ b/docs/runware_serverless_apps_list.md @@ -33,7 +33,7 @@ runware serverless apps list [flags] -h, --help help for list --limit int Maximum number of applications to return (1-100) --query string Filter by substring on name or ID - --sort string Sort order (createdAt (default), name, activity, or errorRate) + --sort string Sort order (createdAt (default) or name) --status string Filter by status (active, initializing, stopped, …) ``` diff --git a/internal/cmd/serverless/apps.go b/internal/cmd/serverless/apps.go index 919d7fb..52fe46f 100644 --- a/internal/cmd/serverless/apps.go +++ b/internal/cmd/serverless/apps.go @@ -112,7 +112,7 @@ func newAppsListCmd(logger *log.Logger) *cobra.Command { cmd.Flags().StringVar(&status, "status", "", "Filter by status (active, initializing, stopped, …)") cmd.Flags().StringVar(&query, "query", "", "Filter by substring on name or ID") cmd.Flags().StringVar(&gpuType, "gpu-type", "", "Filter by GPU type (see 'serverless gpus')") - cmd.Flags().StringVar(&sort, "sort", "", "Sort order (createdAt (default), name, activity, or errorRate)") + cmd.Flags().StringVar(&sort, "sort", "", "Sort order (createdAt (default) or name)") return cmd } @@ -438,8 +438,25 @@ func parseValidFlag[T validListFlag](flag, value, want string) (*T, error) { return &v, nil } +// appListSorts are the listApps orderings this CLI offers. activity and +// errorRate stay in the API enum, but they rank on traffic metrics that are +// not collected yet, so the server answers 422. They are omitted until that lands. +var appListSorts = map[string]struct{}{ + "createdAt": {}, + "name": {}, +} + +const appListSortsHelp = "createdAt (default) or name" + func parseAppSort(sort string) (*serverlessapi.AppSort, error) { - return parseValidFlag[serverlessapi.AppSort]("--sort", sort, "createdAt, name, activity, or errorRate") + if sort == "" { + return nil, nil + } + if _, ok := appListSorts[sort]; !ok { + return nil, fmt.Errorf("invalid --sort %q (want %s)", sort, appListSortsHelp) + } + v := serverlessapi.AppSort(sort) + return &v, nil } func parseAppStatus(status string) (*serverlessapi.AppStatus, error) { diff --git a/internal/cmd/serverless/display_test.go b/internal/cmd/serverless/display_test.go index 80ff968..3979f01 100644 --- a/internal/cmd/serverless/display_test.go +++ b/internal/cmd/serverless/display_test.go @@ -66,12 +66,9 @@ func TestParseAppSort(t *testing.T) { t.Fatalf("unset sort: got=%v err=%v", got, err) } - got, err = parseAppSort("activity") - if err != nil { - t.Fatalf("activity: %v", err) - } - if got == nil || *got != "activity" { - t.Fatalf("activity: got %+v", got) + got, err = parseAppSort("name") + if err != nil || got == nil || *got != "name" { + t.Fatalf("name: got=%v err=%v", got, err) } got, err = parseAppSort("createdAt") @@ -79,12 +76,14 @@ func TestParseAppSort(t *testing.T) { t.Fatalf("createdAt: got=%v err=%v", got, err) } - _, err = parseAppSort("nope") - if err == nil { - t.Fatal("expected error for sort nope") - } - if !strings.Contains(err.Error(), "invalid --sort") { - t.Fatalf("error %q should mention invalid --sort", err) + for _, sort := range []string{"activity", "errorRate", "nope"} { + _, err = parseAppSort(sort) + if err == nil { + t.Fatalf("expected error for sort %q", sort) + } + if !strings.Contains(err.Error(), "invalid --sort") || !strings.Contains(err.Error(), "createdAt (default) or name") { + t.Fatalf("error %q should name the allowed sorts", err) + } } } From a9c12c1e135628030577940dc839599da9e2e5c5 Mon Sep 17 00:00:00 2001 From: ryank90 Date: Thu, 24 Sep 2026 16:03:14 +0100 Subject: [PATCH 2/2] fix(serverless): key apps list --sort by the generated AppSort values The allowlist and help now share one constant, so a rename in the OpenAPI enum fails to compile instead of drifting in the flag text. --- internal/api/serverless/client.go | 5 +++++ internal/cmd/serverless/apps.go | 12 ++++++------ internal/cmd/serverless/display_test.go | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/internal/api/serverless/client.go b/internal/api/serverless/client.go index b85fdd8..dcf9598 100644 --- a/internal/api/serverless/client.go +++ b/internal/api/serverless/client.go @@ -160,6 +160,11 @@ const ( // AppSort is a listApps ordering. type AppSort = gen.AppSort +const ( + AppSortCreatedAt AppSort = gen.CreatedAt + AppSortName AppSort = gen.Name +) + // WorkerStatus is a worker lifecycle status. type WorkerStatus = gen.WorkerStatus diff --git a/internal/cmd/serverless/apps.go b/internal/cmd/serverless/apps.go index 52fe46f..ec83d59 100644 --- a/internal/cmd/serverless/apps.go +++ b/internal/cmd/serverless/apps.go @@ -112,7 +112,7 @@ func newAppsListCmd(logger *log.Logger) *cobra.Command { cmd.Flags().StringVar(&status, "status", "", "Filter by status (active, initializing, stopped, …)") cmd.Flags().StringVar(&query, "query", "", "Filter by substring on name or ID") cmd.Flags().StringVar(&gpuType, "gpu-type", "", "Filter by GPU type (see 'serverless gpus')") - cmd.Flags().StringVar(&sort, "sort", "", "Sort order (createdAt (default) or name)") + cmd.Flags().StringVar(&sort, "sort", "", "Sort order ("+appListSortsHelp+")") return cmd } @@ -441,9 +441,9 @@ func parseValidFlag[T validListFlag](flag, value, want string) (*T, error) { // appListSorts are the listApps orderings this CLI offers. activity and // errorRate stay in the API enum, but they rank on traffic metrics that are // not collected yet, so the server answers 422. They are omitted until that lands. -var appListSorts = map[string]struct{}{ - "createdAt": {}, - "name": {}, +var appListSorts = map[serverlessapi.AppSort]struct{}{ + serverlessapi.AppSortCreatedAt: {}, + serverlessapi.AppSortName: {}, } const appListSortsHelp = "createdAt (default) or name" @@ -452,10 +452,10 @@ func parseAppSort(sort string) (*serverlessapi.AppSort, error) { if sort == "" { return nil, nil } - if _, ok := appListSorts[sort]; !ok { + v := serverlessapi.AppSort(sort) + if _, ok := appListSorts[v]; !ok { return nil, fmt.Errorf("invalid --sort %q (want %s)", sort, appListSortsHelp) } - v := serverlessapi.AppSort(sort) return &v, nil } diff --git a/internal/cmd/serverless/display_test.go b/internal/cmd/serverless/display_test.go index 3979f01..07c4601 100644 --- a/internal/cmd/serverless/display_test.go +++ b/internal/cmd/serverless/display_test.go @@ -81,7 +81,7 @@ func TestParseAppSort(t *testing.T) { if err == nil { t.Fatalf("expected error for sort %q", sort) } - if !strings.Contains(err.Error(), "invalid --sort") || !strings.Contains(err.Error(), "createdAt (default) or name") { + if !strings.Contains(err.Error(), "invalid --sort") || !strings.Contains(err.Error(), appListSortsHelp) { t.Fatalf("error %q should name the allowed sorts", err) } }