Conversation
Enable machine-readable JSON output for agents and scripts. Follows the established pattern from app list: embed FormatOptions, check IsJSON(), output via PrintJSON(). Sensitive env vars remain masked in JSON output and timestamps use RFC3339 format.
📝 WalkthroughWalkthroughThis pull request adds JSON output support to App, AppHistory, and AppStatus CLI commands by embedding FormatOptions into their opts structs and routing to new JSON printers when opts.IsJSON() is true. New helpers—printAppJSON, printAppHistoryJSON, and printAppStatusJSON—serialize richer structured payloads including configuration, deployment metadata, masked environment variables, request statistics (trimmed to recent non-zero samples), top paths, error breakdowns, and git/deployer details. Existing textual UI paths are preserved; JSON paths return early after emitting the serialized output. Public function signatures were updated to accept FormatOptions. 📝 Coding Plan
Comment Tip Migrating from UI to YAML configuration.Use the |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cli/commands/app_history.go`:
- Around line 176-179: The JSON branch is skipped when results are empty because
earlier text-mode returns exit before checking opts.IsJSON; ensure JSON output
honors --format json even for empty deployments by checking opts.IsJSON (or
calling printAppHistoryJSON) before any early text-mode returns, or by replacing
those early returns with a path that calls printAppHistoryJSON(deployments,
opts.App, ctx.ClusterName) when opts.IsJSON is true; update the logic around the
early-return points that print text (the branches handling no
deployments/filtered results) to route to printAppHistoryJSON when opts.IsJSON()
is true.
In `@cli/commands/app_status.go`:
- Around line 397-404: The masking currently only uses isSensitiveKey(key) and
can leak values when metadata marks an env var as sensitive; update the loop
over appConfig.EnvVars() to also consult the env-var metadata (e.g., call a
sensitivity accessor on the kv object such as kv.IsSensitive() or
kv.GetSensitive()) and treat the var as sensitive if either isSensitiveKey(key)
returns true OR kv indicates sensitivity, then apply the same masking logic
(preserve first char then stars when len(value) > 0) so metadata-marked
sensitive values are masked even when the key name is non-obvious.
In `@cli/commands/app.go`:
- Around line 725-727: The current masking exposes the first character for
sensitive env vars (via the block checking v.Sensitive() ||
isSensitiveKey(v.Key()) and slicing value[:1]), so change the logic to fully
mask any non-empty sensitive value rather than reveal the first char: inside the
same conditional that checks v.Sensitive() or isSensitiveKey(v.Key()), replace
the value assignment with value = strings.Repeat("*", len(value)) (and leave
empty values unchanged) so 1-character secrets become "*" and no characters are
leaked.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7605d298-9985-4d84-91aa-13730d86d9b5
📒 Files selected for processing (3)
cli/commands/app.gocli/commands/app_history.gocli/commands/app_status.go
- app history: return empty JSON deployments array instead of printing text when no deployments match filters - Fully mask env vars marked sensitive via metadata (****) rather than leaking the first character; keep partial masking for key-pattern matches only
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cli/commands/app_history.go`:
- Around line 35-107: The nil slice deps can serialize to JSON null; change its
initialization so it's always a non-nil empty slice when there are no entries.
Replace the declaration/usage of deps (currently "var deps []deploymentJSON" and
the later append logic) with an explicitly initialized empty slice (e.g., deps
:= make([]deploymentJSON, 0)) or ensure right before building the output struct
you set deps = []deploymentJSON{} if deps == nil so the output.Deployments field
is serialized as [] instead of null.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 57606970-2d3a-45ef-8f32-2f8b5590b158
📒 Files selected for processing (3)
cli/commands/app.gocli/commands/app_history.gocli/commands/app_status.go
🚧 Files skipped from review as they are similar to previous changes (1)
- cli/commands/app.go
Summary
--format jsonflag tomiren app,miren app status, andmiren app historycommandsapp list: embedFormatOptions, checkIsJSON(), output viaPrintJSON()miren app --format jsonOutputs app name, active version, last deploy, CPU stats, pools, env vars, request stats (last 5 non-zero samples), top paths, and error breakdown.
miren app status --format jsonOutputs app/cluster, current version, configuration, active deployment, and all 5 recent deployments with full git info.
miren app history --format jsonOutputs all deployments (after filtering/sorting) with all fields regardless of
--detailedflag, including git info and error messages.Test plan
make lintpassesmake testpassesmiren app -a <app> --format jsonreturns valid JSON with traffic datamiren app status -a <app> --format jsonreturns valid JSONmiren app history -a <app> --format jsonreturns valid JSON