From aa81f37551a9f5c5b72e486fba3f78bd8b5f6f20 Mon Sep 17 00:00:00 2001 From: lillian Date: Tue, 14 Jul 2026 13:13:11 +0000 Subject: [PATCH 1/2] Show app network in fly status and fly apps list Display which private network an app belongs to. The field is only shown when the app is on a non-default network: fly status adds a Network row (and JSON key), and fly apps list adds a Network column when at least one listed app has one. fly-go's GetApps/GetAppsForOrganization queries don't request the network field, so apps list now runs the same paginated query locally with network included. Co-Authored-By: Claude Fable 5 --- internal/command/apps/list.go | 95 ++++++++++++++++++++++++++--- internal/command/status/machines.go | 12 +++- 2 files changed, 96 insertions(+), 11 deletions(-) diff --git a/internal/command/apps/list.go b/internal/command/apps/list.go index 4d23777685..f6a70952ff 100644 --- a/internal/command/apps/list.go +++ b/internal/command/apps/list.go @@ -24,6 +24,7 @@ func newList() *cobra.Command { available to this user. The list includes applications from all the organizations the user is a member of. The list shows the name, owner (org), status, and date/time of latest deploy for each app. +Apps on a non-default network also show the network name. ` short = "List applications." ) @@ -46,7 +47,6 @@ the name, owner (org), status, and date/time of latest deploy for each app. } func runList(ctx context.Context) (err error) { - client := flyutil.ClientFromContext(ctx) silence := flag.GetBool(ctx, "quiet") cfg := config.FromContext(ctx) org, err := getOrg(ctx) @@ -54,13 +54,12 @@ func runList(ctx context.Context) (err error) { return fmt.Errorf("error getting organization: %w", err) } - var apps []fly.App + var orgID *string if org != nil { - apps, err = client.GetAppsForOrganization(ctx, org.ID) - } else { - apps, err = client.GetApps(ctx, nil) + orgID = &org.ID } + apps, err := getApps(ctx, orgID) if err != nil { return } @@ -83,6 +82,14 @@ func runList(ctx context.Context) (err error) { return } + showNetwork := false + for _, app := range apps { + if app.Network != "" { + showNetwork = true + break + } + } + for _, app := range apps { latestDeploy := "" if app.Deployed && app.CurrentRelease != nil { @@ -93,19 +100,89 @@ func runList(ctx context.Context) (err error) { app.Name = "(interactive shells app)" } - rows = append(rows, []string{ + row := []string{ app.Name, app.Organization.Slug, app.Status, - latestDeploy, - }) + } + if showNetwork { + row = append(row, app.Network) + } + rows = append(rows, append(row, latestDeploy)) + } + + headers := []string{"Name", "Owner", "Status"} + if showNetwork { + headers = append(headers, "Network") } + headers = append(headers, "Latest Deploy") - _ = render.Table(out, "", rows, "Name", "Owner", "Status", "Latest Deploy") + _ = render.Table(out, "", rows, headers...) return } +// getApps mirrors fly-go's GetApps/GetAppsForOrganization but also requests +// the network field, which those queries omit. +func getApps(ctx context.Context, orgID *string) ([]fly.App, error) { + client := flyutil.ClientFromContext(ctx) + + query := ` + query($org: ID, $after: String) { + apps(type: "container", first: 200, after: $after, organizationId: $org) { + pageInfo { + hasNextPage + endCursor + } + nodes { + id + name + deployed + hostname + platformVersion + network + organization { + slug + name + } + currentRelease { + createdAt + status + } + status + } + } + } + ` + + var apps []fly.App + var after *string + + for { + req := client.NewRequest(query) + if orgID != nil { + req.Var("org", *orgID) + } + if after != nil { + req.Var("after", *after) + } + + data, err := client.RunWithContext(ctx, req) + if err != nil { + return nil, err + } + + apps = append(apps, data.Apps.Nodes...) + + if !data.Apps.PageInfo.HasNextPage { + break + } + after = &data.Apps.PageInfo.EndCursor + } + + return apps, nil +} + func getOrg(ctx context.Context) (*fly.Organization, error) { client := flyutil.ClientFromContext(ctx) diff --git a/internal/command/status/machines.go b/internal/command/status/machines.go index 0ab4f74c3a..6e6880b517 100644 --- a/internal/command/status/machines.go +++ b/internal/command/status/machines.go @@ -163,8 +163,13 @@ func RenderMachineStatus(ctx context.Context, app *fly.AppCompact, out io.Writer return err } - obj := [][]string{{app.Name, app.Organization.Slug, app.Hostname, image}} - if err := render.VerticalTable(out, "App", obj, "Name", "Owner", "Hostname", "Image"); err != nil { + fields := []string{app.Name, app.Organization.Slug, app.Hostname, image} + headers := []string{"Name", "Owner", "Hostname", "Image"} + if app.Network != "" { + fields = append(fields, app.Network) + headers = append(headers, "Network") + } + if err := render.VerticalTable(out, "App", [][]string{fields}, headers...); err != nil { return err } @@ -274,6 +279,9 @@ func renderMachineJSONStatus(ctx context.Context, app *fly.AppCompact, machines "PlatformVersion": app.PlatformVersion, "Machines": machinesToShow, } + if app.Network != "" { + status["Network"] = app.Network + } return render.JSON(out, status) } From 1ca46345b465db36e658f08d6c69e4e94b30e655 Mon Sep 17 00:00:00 2001 From: lillian Date: Tue, 14 Jul 2026 13:19:22 +0000 Subject: [PATCH 2/2] Fix nlreturn lint: blank line before break Co-Authored-By: Claude Fable 5 --- internal/command/apps/list.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/command/apps/list.go b/internal/command/apps/list.go index f6a70952ff..b9a4c31e2f 100644 --- a/internal/command/apps/list.go +++ b/internal/command/apps/list.go @@ -86,6 +86,7 @@ func runList(ctx context.Context) (err error) { for _, app := range apps { if app.Network != "" { showNetwork = true + break } }