feat: add ndjson output format with field selection to list commands - #3068
feat: add ndjson output format with field selection to list commands#3068vikashkumar2020 wants to merge 3 commits into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
This PR adds a new NDJSON (--output ndjson) streaming output mode plus optional field projection (--fields) to Tekton CLI tkn * list commands, enabling incremental consumption of Kubernetes list results and reducing payload size for automation workflows.
Changes:
- Introduces
pkg/formatted.PrintNDJSONto stream Kubernetes listitemsas one JSON object per line, with optional dot-path field projection. - Adds a
--fieldsflag and anndjsonoutput branch to the supportedlistcommands. - Adds unit tests for NDJSON output and field projection behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/formatted/ndjson.go | Adds NDJSON list streaming + dot-path field projection helpers. |
| pkg/formatted/ndjson_test.go | Adds tests covering NDJSON output and field selection semantics. |
| pkg/cmd/pipeline/list.go | Adds --fields and --output ndjson handling for tkn pipeline list. |
| pkg/cmd/pipelinerun/list.go | Adds --fields and --output ndjson handling for tkn pipelinerun list. |
| pkg/cmd/task/list.go | Adds --fields and --output ndjson handling for tkn task list. |
| pkg/cmd/taskrun/list.go | Adds --fields and --output ndjson handling for tkn taskrun list. |
| pkg/cmd/customrun/list.go | Adds --fields and --output ndjson handling for tkn customrun list. |
| pkg/cmd/eventlistener/list.go | Adds --fields and --output ndjson handling for tkn eventlistener list. |
| pkg/cmd/triggertemplate/list.go | Adds --fields and --output ndjson handling for tkn triggertemplate list. |
| pkg/cmd/triggerbinding/list.go | Adds --fields and --output ndjson handling for tkn triggerbinding list. |
| pkg/cmd/clustertriggerbinding/list.go | Adds --fields and --output ndjson handling for tkn clustertriggerbinding list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
d536549 to
f2cfdd2
Compare
|
@divyansh42 @pradeepitm12 Can you please take a look at PR, i have fixed the review comments |
divyansh42
left a comment
There was a problem hiding this comment.
Thanks @vikashkumar2020. I have added few suggestion, please let me know your thoughts on the same.
Also, the test file only covers the PrintNDJSON helper function. There are no unit tests verifying:
- The
--output ndjsonbranch is correctly reached in each command'sRunE --fieldsis properly parsed and passed through the options struct- Error handling in commands that make their own
ListV1call (pipeline, task)
The existing test infrastructure for other commands (e.g., pipelinerun/list_test.go) uses fake clients — adding similar tests for the ndjson path would guard against regression in the wiring logic.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Suppressed comments (2)
pkg/cmd/pipeline/list.go:122
- The generated command documentation has not been updated for these public flags:
docs/cmd/tkn_pipeline_list.md:20-26contains no--fields, and its--outputhelp still lists formats withoutndjson; the other affected list docs are likewise unchanged. Also extend the runtime output-format usage sondjsonis advertised, then runmake generatedand commit the generated Markdown/manpage changes.
f.AddFlags(c)
c.Flags().BoolVarP(&opts.AllNamespaces, "all-namespaces", "A", opts.AllNamespaces, "list Pipelines from all namespaces")
c.Flags().BoolVarP(&opts.NoHeaders, "no-headers", "", opts.NoHeaders, "do not print column headers with output (default print column headers with output)")
c.Flags().StringSliceVar(&opts.Fields, "fields", opts.Fields, "Comma-separated list of fields to include in output (e.g. metadata.name,status.startTime); only used with --output ndjson")
pkg/cmd/pipeline/list.go:122
- Issue #2853 demonstrates field selection with
--output json, but this flag is read only by thendjsonbranch, so--fields ... --output jsonsucceeds while silently emitting every field. Apply projection to JSON output too, or reject that combination and explicitly resolve the narrower scope before closing the linked issue.
c.Flags().StringSliceVar(&opts.Fields, "fields", opts.Fields, "Comma-separated list of fields to include in output (e.g. metadata.name,status.startTime); only used with --output ndjson")
|
@divyansh42 addressed the comments |
There was a problem hiding this comment.
🟡 Changes recommended
Field projection misses the linked JSON requirement, and typed-list buffering undermines NDJSON’s intended memory benefit.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
pkg/cmd/pipeline/list.go:101
- This typed
PipelineListround-trip drops fields unknown to the vendored Tekton API before NDJSON projection, unlike the existing JSON/YAML path that prints the server’s unstructured list. This makes newer CRD fields silently unavailable to--fields; retain and pass the dynamic client’s unstructured result instead.
var pl *v1.PipelineList
if err := actions.ListV1(pipelineGroupResource, cs, metav1.ListOptions{}, ns, &pl); err != nil {
pkg/cmd/task/list.go:90
- As in the Pipeline command, converting the dynamic response into the vendored
TaskListsilently removes server fields that this client version does not know about. NDJSON/--fieldsshould operate on the dynamic client’s unstructured result so it preserves the same resource data as JSON/YAML output.
var tl *v1.TaskList
if err := actions.ListV1(taskGroupResource, cs, metav1.ListOptions{}, ns, &tl); err != nil {
- Files reviewed: 14/14 changed files
- Comments generated: 5
- Review effort level: Balanced
| if len(opts.Fields) > 0 && output != "ndjson" { | ||
| return fmt.Errorf("--fields is only supported with --output ndjson") |
| var pl *v1.PipelineList | ||
| if err := actions.ListV1(pipelineGroupResource, cs, metav1.ListOptions{}, ns, &pl); err != nil { |
| var tl *v1.TaskList | ||
| if err := actions.ListV1(taskGroupResource, cs, metav1.ListOptions{}, ns, &tl); err != nil { |
| } | ||
|
|
||
| if output != "" { | ||
| if output == "ndjson" { |
|
|
||
| var buf bytes.Buffer | ||
| // Request metadata.name — present and non-nil. | ||
| if err := formatted.PrintNDJSON(&buf, list, []string{"metadata.name"}); err != nil { |
Changes
Fixes: #2853
Add
--output ndjsonand--fieldsto everytkn * listcommand so thatautomation scripts and AI agents can consume resource lists incrementally and
request only the fields they need.
--output ndjson— newline-delimited JSON streamingInstead of a single JSON array, each resource is emitted as one JSON object
per line (NDJSON / JSON Lines). Consumers can begin processing the first record
before the last one arrives, and never need to buffer an entire response in
memory.
--fields— dot-path field projectionRestricts each NDJSON object to the requested fields, specified as a
comma-separated list of dot-separated paths. Shared path prefixes are merged
into a single nested object; unknown paths are silently ignored.
Implementation
New helper in
pkg/formatted/ndjson.go:PrintNDJSON(w, obj, fields)runtime.Objectlist to NDJSON viaruntime.DefaultUnstructuredConverter, then streams one line per itempickFields(src, fields)getNestedField/setNestedFieldEach of the nine
listcommands gains:Fields []stringin itsListOptions/listOptionsstruct--fieldsflag wired to that slicecase output == "ndjson":branch (inswitch {}form to satisfygocritic) that callsformatted.PrintNDJSONThe
--outputflag is the existingcliopts.NewPrintFlagsflag — no new top-level flag required.Commands covered
tkn pipeline listpkg/cmd/pipelinetkn pipelinerun listpkg/cmd/pipelineruntkn task listpkg/cmd/tasktkn taskrun listpkg/cmd/taskruntkn customrun listpkg/cmd/customruntkn eventlistener listpkg/cmd/eventlistenertkn triggertemplate listpkg/cmd/triggertemplatetkn triggerbinding listpkg/cmd/triggerbindingtkn clustertriggerbinding listpkg/cmd/clustertriggerbinding(
tkn bundle listreads from an OCI registry, not a Kubernetes API, and isintentionally excluded.)
Tests
pkg/formatted/ndjson_test.gocovers:Submitter Checklist
These are the criteria that every PR should meet, please check them off as you
review them:
make checkmake generatedSee the contribution guide
for more details.
Release Notes