Skip to content

feat: add --json output mode to all func subcommands#3822

Open
Ankitsinghsisodya wants to merge 3 commits into
knative:mainfrom
Ankitsinghsisodya:feat/json-output-mode
Open

feat: add --json output mode to all func subcommands#3822
Ankitsinghsisodya wants to merge 3 commits into
knative:mainfrom
Ankitsinghsisodya:feat/json-output-mode

Conversation

@Ankitsinghsisodya
Copy link
Copy Markdown
Contributor

@Ankitsinghsisodya Ankitsinghsisodya commented May 21, 2026

Note: Re-submission of #3774, accidentally closed when the head repository was deleted.

Summary

Implements structured JSON output for every func subcommand, as described in #3769.

All JSON is written to stdout using a versioned envelope:

{"apiVersion":"v1","status":"ok","data":{...}}
{"apiVersion":"v1","status":"error","error":{"category":"...","code":"...","retryable":false,"message":"...","hint":"..."}}

The flag is opt-in — all existing human-readable output is unchanged.

Changes

New files

  • cmd/json.go — shared JSONResponse/JSONError structs, WriteJSONSuccess, WriteJSONError, errorToJSONError (maps 14+ typed errors to category/code/retryable), and isJSONEnabled helper
  • cmd/json_test.go — 20 unit tests covering every error-type mapping, envelope shape, apiVersion presence, and round-trip validity

Global plumbing

  • cmd/root.go--json registered as a persistent flag on the root command (inheritable by all subcommands), bound to Viper
  • pkg/app/app.go — top-level error sink writes WriteJSONError to stdout when --json is set, instead of plain text to stderr

Per-command success payloads

Command data fields
build name, image
deploy name, namespace, url, image
create name, path, runtime, template
delete name, namespace
describe existing fn.Instance object
list array of listItems
run address, host, port
invoke response (HTTP body)
version existing Version struct
languages array of runtime strings
templates map of runtime → template array
environment existing Environment struct
subscribe name, source, filters
repository list array of {name, url}
repository add/rename/remove operation result fields
logs explicitly unsupported — returns error if --json is set

Test plan

  • go test knative.dev/func/cmd -run "TestWriteJSON|TestAPIVersion|TestErrorToJSONError|TestRound|TestLanguages_JSON|TestTemplates_JSON|TestTemplates_ByLanguage|TestRepository_List" — all 26 pass
  • func create -l go myfunc --json → envelope with status: ok
  • func logs --json → returns error: --json is not supported for streaming commands

- Added JSON output functionality to multiple commands including build, create, delete, deploy, describe, environment, invoke, languages, list, logs, repository, run, subscribe, templates, and version.
- Introduced a standardized JSON response structure for success and error messages, enhancing the user experience and consistency across the CLI.
- Updated existing commands to check for the --json flag and return structured JSON responses when enabled.
- Added tests to ensure the correctness of JSON output and error handling in various scenarios.

This enhancement improves the usability of the CLI by allowing users to easily parse command outputs programmatically.
- Added JSON output support for various commands, ensuring structured responses when the --json flag is enabled.
- Updated error handling in commands like 'completion', 'mcp start', and 'tkn-tasks' to return appropriate error messages when JSON output is requested.
- Redirected non-error messages to stderr in commands such as 'deploy' and 'invoke' to prevent contamination of JSON output on stdout.
- Improved test cases to validate the new output behavior and error handling across commands.

These changes enhance the user experience by providing clearer error messages and maintaining output consistency across the CLI.
- Updated the `invoke` command to return the response body directly as JSON when the `--json` flag is enabled, improving output consistency.
- Removed the internal alias for `writeJSONError` in the `json.go` file to streamline the codebase.
- Added documentation to multiple command reference files to include the `--json` option, ensuring users are aware of the new output format.

These changes enhance the user experience by providing structured JSON responses across various commands, facilitating easier parsing and integration.
Copilot AI review requested due to automatic review settings May 21, 2026 11:19
@knative-prow
Copy link
Copy Markdown

knative-prow Bot commented May 21, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Ankitsinghsisodya
Once this PR has been reviewed and has the lgtm label, please assign gauron99 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@knative-prow knative-prow Bot requested review from dsimansk and jrangelramos May 21, 2026 11:19
@knative-prow knative-prow Bot added size/XXL 🤖 PR changes 1000+ lines, ignoring generated files. needs-ok-to-test 🤖 Needs an org member to approve testing labels May 21, 2026
@knative-prow
Copy link
Copy Markdown

knative-prow Bot commented May 21, 2026

Hi @Ankitsinghsisodya. Thanks for your PR.

I'm waiting for a knative member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a global --json mode with a standard response envelope for machine-readable CLI output, including structured error reporting, and updates command docs/tests accordingly.

Changes:

  • Introduces JSON envelope helpers (WriteJSONSuccess, WriteJSONError) and applies them across multiple commands.
  • Adds a global --json persistent flag and updates the top-level error sink to emit JSON errors.
  • Updates generated reference docs and adjusts tests to validate the new JSON envelope shape.

Reviewed changes

Copilot reviewed 59 out of 59 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/app/app.go Emits structured JSON errors from the top-level error sink when JSON mode is enabled
cmd/json.go Adds JSON envelope types/helpers and error classification mapping
cmd/json_test.go Adds tests for JSON envelope shape and error classification mapping
cmd/root.go Adds global persistent --json flag and binds it to viper
cmd/version.go Emits version output as a JSON envelope when JSON mode is enabled
cmd/tkn_tasks.go Rejects --json for raw YAML output command
cmd/templates.go Switches templates output to JSON envelope when JSON mode is enabled
cmd/templates_test.go Updates templates tests to expect JSON envelope
cmd/subscribe.go Emits subscribe success payload in JSON envelope
cmd/run.go Emits run success payload in JSON envelope
cmd/repository.go Emits repository subcommand success payloads in JSON envelope
cmd/mcp.go Rejects --json for long-running stdio-protocol server
cmd/logs.go Rejects --json for streaming logs
cmd/list.go Wraps list JSON output inside the standard envelope
cmd/languages.go Switches languages output to JSON envelope when JSON mode is enabled
cmd/languages_test.go Updates languages tests to expect JSON envelope
cmd/invoke.go Emits invoke response in JSON envelope and moves verbose text to stderr
cmd/environment.go Emits environment output in JSON envelope when JSON mode is enabled
cmd/describe.go Wraps describe JSON output inside the standard envelope
cmd/deploy.go Moves deploy status text to stderr and emits deploy result JSON envelope
cmd/deploy_test.go Adjusts deploy tests for messages now written to stderr
cmd/delete.go Emits delete success payload in JSON envelope
cmd/create.go Emits create success payload in JSON envelope
cmd/config_git.go Adds JSON envelope behavior for unimplemented config git command
cmd/completion.go Rejects --json for raw shell completion script output
cmd/build.go Emits build success payload in JSON envelope
docs/reference/func.md Documents global --json flag
docs/reference/func_version.md Documents inherited --json flag
docs/reference/func_subscribe.md Documents inherited --json flag
docs/reference/func_repository_rename.md Documents inherited --json flag
docs/reference/func_repository_remove.md Documents inherited --json flag
docs/reference/func_repository_list.md Documents inherited --json flag
docs/reference/func_repository_add.md Documents inherited --json flag
docs/reference/func_repository.md Documents inherited --json flag
docs/reference/func_mcp_start.md Documents inherited --json flag
docs/reference/func_mcp.md Documents inherited --json flag
docs/reference/func_logs.md Documents inherited --json flag
docs/reference/func_list.md Documents inherited --json flag
docs/reference/func_invoke.md Documents inherited --json flag
docs/reference/func_environment.md Documents inherited --json flag
docs/reference/func_describe.md Documents inherited --json flag
docs/reference/func_deploy.md Documents inherited --json flag
docs/reference/func_delete.md Documents inherited --json flag
docs/reference/func_create.md Documents inherited --json flag
docs/reference/func_config_volumes_remove.md Documents inherited --json flag
docs/reference/func_config_volumes_add.md Documents inherited --json flag
docs/reference/func_config_volumes.md Documents inherited --json flag
docs/reference/func_config_labels_remove.md Documents inherited --json flag
docs/reference/func_config_labels_add.md Documents inherited --json flag
docs/reference/func_config_labels.md Documents inherited --json flag
docs/reference/func_config_git_set.md Documents inherited --json flag
docs/reference/func_config_git_remove.md Documents inherited --json flag
docs/reference/func_config_git.md Documents inherited --json flag
docs/reference/func_config_envs_remove.md Documents inherited --json flag
docs/reference/func_config_envs_add.md Documents inherited --json flag
docs/reference/func_config_envs.md Documents inherited --json flag
docs/reference/func_config.md Documents inherited --json flag
docs/reference/func_completion.md Documents inherited --json flag
docs/reference/func_build.md Documents inherited --json flag
Comments suppressed due to low confidence (1)

pkg/app/app.go:1

  • The error from cmd.WriteJSONError is ignored. Since this is the top-level error sink, failing to write JSON should fall back to a plain-text error on stderr (or at least print an additional message) so failures don't become silent/no-output in JSON mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cmd/json.go
Comment on lines +16 to +22
// isJSONEnabled reports whether --json was explicitly set for this execution.
// Using cmd.Flag("json").Changed (rather than viper.GetBool("json")) avoids
// stale viper state polluting test runs.
func isJSONEnabled(cmd *cobra.Command) bool {
f := cmd.Flag("json")
return f != nil && f.Changed
}
Comment thread cmd/templates_test.go
Comment on lines +58 to +71
var resp JSONResponse
if err := json.Unmarshal([]byte(buf()), &resp); err != nil {
t.Fatalf("output is not valid JSON: %v", err)
}
if resp.APIVersion != "v1" {
t.Errorf("expected apiVersion 'v1', got %q", resp.APIVersion)
}
if resp.Status != "ok" {
t.Errorf("expected status 'ok', got %q", resp.Status)
}
if resp.Data == nil {
t.Error("expected non-nil data in templates JSON response")
}
_ = cmp.Diff // keep import used
Comment thread cmd/languages_test.go
Comment on lines +48 to 60
var resp JSONResponse
if err := json.Unmarshal([]byte(buf()), &resp); err != nil {
t.Fatalf("output is not valid JSON: %v", err)
}
if resp.APIVersion != "v1" {
t.Errorf("expected apiVersion 'v1', got %q", resp.APIVersion)
}
if resp.Status != "ok" {
t.Errorf("expected status 'ok', got %q", resp.Status)
}
if resp.Data == nil {
t.Error("expected non-nil data")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ok-to-test 🤖 Needs an org member to approve testing size/XXL 🤖 PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants