Skip to content

feat : add consistent exit codes - #3130

Open
vikashkumar2020 wants to merge 2 commits into
tektoncd:mainfrom
vikashkumar2020:feature/consistent-exit-codes
Open

vikashkumar2020 wants to merge 2 commits into
tektoncd:mainfrom
vikashkumar2020:feature/consistent-exit-codes

Conversation

@vikashkumar2020

@vikashkumar2020 vikashkumar2020 commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

Changes

Fixes : #2855
Implemented consistent exit codes across tkn. Added a new pkg/exitcode package defining codes 0–5 (success, general error, not found, invalid input, timeout, unauthorized) with a typed error that propagates through the call stack. All Kubernetes API calls in pkg/actions now classify errors at the boundary via exitcode.FromAPIError(). The root command wires up exitcode.CodeFrom() to drive os.Exit, and adds structured {"error":"…","code":N} JSON output to stderr when --output json is set. A reference doc at docs/exit-codes.md covers the full scheme with examples.

Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

  • Includes tests (if functionality changed/added)
  • Run the code checkers with make check
  • Regenerate the manpages, docs and go formatting with make generated
  • Commit messages follow commit message best practices

See the contribution guide
for more details.

Release Notes

Add consistent exit codes to tkn: 0 success, 1 general error, 2 not found, 3 invalid input, 4 timeout, 5 unauthorized/forbidden. Kubernetes API errors are now classified at the boundary with typed errors, and `--output json` emits a structured {"error":"...","code":N} object on stderr. `tkn pipelinerun logs --exit-with-error` now exits 1 (general error) instead of 2 when the PipelineRun has no conditions yet.

@tekton-robot tekton-robot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Aug 11, 2026
@tekton-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
To complete the pull request process, please assign divyansh42 after the PR has been reviewed.
You can assign the PR to them by writing /assign @divyansh42 in a comment when ready.

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

@tekton-robot tekton-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Aug 11, 2026
@divyansh42

Copy link
Copy Markdown
Member

@vikashkumar2020 thanks for the PR!
Could you please add release notes and link it to the corresponding GitHub issue?

@vikashkumar2020

Copy link
Copy Markdown
Contributor Author

@vikashkumar2020 thanks for the PR! Could you please add release notes and link it to the corresponding GitHub issue?

added into description

@divyansh42 divyansh42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The PR wraps errors in pkg/actions (get, list, delete, patch) but many commands produce errors through other paths: direct client calls in trigger/bundle commands, flag validation errors in RunE, etc. The issue asks for consistent exit codes "across all commands."

This is acceptable as a first pass, but please file a follow-up issue tracking the remaining commands so this doesn't fall through the cracks.

Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/cmd/root.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/cmd/pipelinerun/logs.go Resolved
Comment thread docs/exit-codes.md Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Implements a shared exit-code scheme for tkn by introducing a typed error that carries an intended exit code, classifying certain Kubernetes API failures at the pkg/actions boundary, and wiring the top-level CLI entrypoint to exit using the resolved code (with documentation for consumers).

Changes:

  • Added pkg/exitcode with standard codes (0–5), a typed exitcode.Error, and Kubernetes API error classification helpers.
  • Updated the top-level command execution path to silence Cobra’s default error printing and to drive os.Exit(...) from exitcode.CodeFrom(err), plus structured JSON error output support.
  • Updated selected actions helpers to wrap API errors via exitcode.FromAPIError(...) and aligned pipelinerun logs --exit-with-error behavior with the new scheme.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pkg/exitcode/exitcode.go Defines exit codes, typed error, and K8s API error classification.
pkg/exitcode/exitcode_test.go Unit tests for CodeFrom and FromAPIError.
pkg/cmd/root.go Silences Cobra errors and adds PrintError to emit JSON error payloads for --output json.
cmd/tkn/main.go Switches to centralized error printing + exit code resolution.
pkg/actions/get.go Wraps dynamic client Get errors via exitcode.FromAPIError.
pkg/actions/list.go Wraps dynamic client List errors via exitcode.FromAPIError.
pkg/actions/delete.go Wraps dynamic client Delete errors via exitcode.FromAPIError.
pkg/actions/patch.go Wraps dynamic client Patch errors via exitcode.FromAPIError.
pkg/cmd/pipelinerun/logs.go Adjusts “no conditions” exit code to avoid conflicting with NotFound.
pkg/cmd/pipelinerun/logs_test.go Updates the corresponding unit test expectation.
docs/exit-codes.md Documents the exit code table, examples, and structured JSON stderr errors.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cmd/tkn/main.go Resolved
Comment thread pkg/actions/patch.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/actions/list.go Resolved
Comment thread pkg/cmd/root.go Resolved
@divyansh42

Copy link
Copy Markdown
Member

One more minor comment:
The new files have Copyright © 2024 but this PR is authored in 2026. Please update to 2026.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

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

Suppressed comments (2)

cmd/tkn/main.go:53

  • PrintError is given the root command, but --output is a local flag on the executed leaf command (PrintFlags.AddFlags uses cmd.Flags()). The lookup therefore fails and is ignored, so even tkn pipelinerun describe missing --output json emits the plain-text error instead of JSON. Use ExecuteC and pass its returned command; an integration test with a leaf --output json flag would catch this.
	if err := tkn.Execute(); err != nil {
		tknCmd.PrintError(tkn, err, os.Stderr)

pkg/actions/list.go:61

  • The API-boundary audit is incomplete. pkg/actions/create.go:34 and pkg/actions/watch.go:35 still return raw Kubernetes API errors, so commands using actions.Create or actions.Watch return code 1 for forbidden or timeout responses instead of codes 5 or 4. Apply the same classification to every API operation in this package.
	allRes, err := dynamic.Resource(*gvr).Namespace(ns).List(context.Background(), op)
	if err != nil {
		return nil, exitcode.FromAPIError(err)

Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
@divyansh42

Copy link
Copy Markdown
Member

@vikashkumar2020 is there any update on this?

1 similar comment
@divyansh42

Copy link
Copy Markdown
Member

@vikashkumar2020 is there any update on this?

@divyansh42
divyansh42 requested a balanced review from Copilot October 20, 2026 13:47
@vikashkumar2020

Copy link
Copy Markdown
Contributor Author

@vikashkumar2020 is there any update on this?

Hi, due to some complications around the contribution to open source in my org at IBM. I have to hold on making any further contribution

@divyansh42

Copy link
Copy Markdown
Member

@vikashkumar2020 is there any update on this?

Hi, due to some complications around the contribution to open source in my org at IBM. I have to hold on making any further contribution

Thanks, @vikashkumar2020 for informing us.
We will take your commits and create another PR with these changes so that we can unblock this feature.
I hope that is fine.

I hope you come back to contribute to this project. Thank you for your contributions. 🙂

@divyansh42
divyansh42 force-pushed the feature/consistent-exit-codes branch from 034007f to b94d1b2 Compare November 2, 2026 08:51
@divyansh42

Copy link
Copy Markdown
Member

/retest

1 similar comment
@divyansh42

Copy link
Copy Markdown
Member

/retest

@divyansh42
divyansh42 force-pushed the feature/consistent-exit-codes branch from b94d1b2 to c095e71 Compare November 2, 2026 12:54
@divyansh42

Copy link
Copy Markdown
Member

/retest

@divyansh42 divyansh42 closed this Nov 3, 2026
@divyansh42 divyansh42 reopened this Nov 3, 2026
@divyansh42

Copy link
Copy Markdown
Member

@copilot review

@divyansh42
divyansh42 requested a max review from Copilot and removed request for Copilot November 3, 2026 09:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved error classification and propagation gaps produce incorrect exit codes, while direct stderr diagnostics and inconsistent output-mode handling break the JSON error contract.

14 open issues
1 resolved since last review

Review effort: Max

Comment thread cmd/tkn/main.go Resolved
Comment thread pkg/cmd/root.go Resolved
Comment thread pkg/cmd/root.go Resolved
Comment thread pkg/cmd/root.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved
@divyansh42
divyansh42 force-pushed the feature/consistent-exit-codes branch from c095e71 to 5b41f4b Compare November 4, 2026 20:30
@tekton-robot tekton-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Nov 4, 2026
@divyansh42
divyansh42 requested a balanced review from Copilot November 5, 2026 04:24
@divyansh42

Copy link
Copy Markdown
Member

/retest

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Existing command paths lose classified error causes, validation failures return incorrect exit codes, and JSON error output depends on flag order.

11 open issues
6 resolved since last review

Review effort: Balanced

Comment thread pkg/exitcode/exitcode.go Resolved
Comment thread docs/exit-codes.md Resolved
Comment thread pkg/cmd/pipelinerun/logs.go Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Comment thread pkg/cmd/root.go Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Comment thread cmd/tkn/main.go Resolved
Comment thread pkg/exitcode/exitcode.go Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Comment thread pkg/actions/get.go Resolved
@divyansh42
divyansh42 force-pushed the feature/consistent-exit-codes branch from d4afff0 to cb85acc Compare November 11, 2026 14:48
@tekton-robot tekton-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 11, 2026
vikashkumar2020 and others added 2 commits November 11, 2026 20:24
Introduce a pkg/exitcode package that defines the standard tkn exit
codes (0 success, 1 general error, 2 not found, 3 invalid input,
4 timeout, 5 unauthorized) and a typed error so that errors can carry
their intended exit code through the call stack.

Classify Kubernetes API errors at the boundary in the shared actions
layer (get, list, delete, patch) via exitcode.FromAPIError, and emit
the resolved code from main using exitcode.CodeFrom. When --output
json is set, errors are written to stderr as a structured
{"error":"...","code":N} payload. Document the full scheme in
docs/exit-codes.md.

Closes tektoncd#2855

Signed-off-by: Vikash Kumar <kvvik2020@gmail.com>
Build on the exit-code support with correctness and coverage fixes:

- FromAPIError now keeps the original Kubernetes error as the wrapped
  error and exposes it via Unwrap, so k8serrors helpers such as
  IsNotFound/IsForbidden still match after classification. Replacing
  the typed error broke callers like customrun delete that branch on
  IsNotFound.

- main passes the command returned by ExecuteC (the one that actually
  ran) to PrintError, and PrintError takes an io.Writer. --output is a
  subcommand-local flag, so reading it from the root command meant the
  structured {"error":...,"code":N} JSON output never triggered.
  PrintError now normalizes the flag so "JSON"/"Json" also match.

- Classify invalid/bad-request errors as InvalidInput (3) and
  timeout/server-timeout/context.DeadlineExceeded as Timeout (4) via a
  shared classify helper, and let CodeFrom fall back to it for raw
  Kubernetes/context errors preserved by intermediate callers.

- Wrap Create and Watch API errors through FromAPIError, and drop the
  stray stderr message in Patch so failures surface only as the typed
  error.

- Align the --exit-with-pipelinerun-error help text (pipelinerun logs
  and pipeline start) and regenerated docs/man pages with the new
  "no conditions" behavior, which now exits 1 instead of 2.

- Document that code 2 (not found) intentionally diverges from the Bash
  "misuse of builtins" convention, and reference the real
  --exit-with-pipelinerun-error flag name in docs/exit-codes.md.

Address review follow-ups so the documented codes actually reach the
caller and cover client-side input errors:

- Preserve the error cause with %w across the describe, list, cancel and
  delete paths that previously formatted it with %v/%s or discarded it
  (for example pkg/taskrun/description.go, pkg/cmd/pipeline/list.go and
  pkg/deleter/deleter.go). NotFound and Forbidden now propagate through
  CodeFrom regardless of output format. Where a caller must keep an exact
  message without the cause, it returns exitcode.New(CodeFrom(err), ...)
  so the code is retained.

- Classify client-side input errors as InvalidInput (3): a root
  SetFlagErrorFunc tags flag-parsing failures, a visitCommands pass wraps
  positional-argument validators, and option validators (negative
  --limit and invalid --output/kind) are wrapped at their source.

- Resolve the requested --output mode independently of successful flag
  parsing. Cobra stops at the first invalid flag, so PrintError now falls
  back to scanning the raw arguments (honoring the -- terminator) and the
  JSON error format no longer depends on flag order.

Signed-off-by: divyansh42 <diagrawa@redhat.com>
Assisted-by: Claude Opus 4.8 (via GitHub Copilot CLI)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@divyansh42
divyansh42 force-pushed the feature/consistent-exit-codes branch from cb85acc to a2f3bfb Compare November 11, 2026 14:59
@tekton-robot tekton-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 11, 2026
@divyansh42
divyansh42 requested a balanced review from Copilot November 11, 2026 15:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Comment thread pkg/cmd/root.go
Comment on lines +151 to +153
if outputFlag == "" {
outputFlag = outputFromArgs(os.Args[1:])
}
Comment thread pkg/cmd/root.go
Comment on lines +188 to +189
case strings.HasPrefix(a, "-o") && len(a) > 2:
return a[2:]
Comment thread pkg/cmd/root.go
Comment on lines +249 to +250
if err := orig(c, args); err != nil {
return exitcode.New(exitcode.InvalidInput, "%s", err)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Define consistent exit codes for all tkn commands

4 participants