Documentation
¶
Overview ¶
Package exitcode is the public contract for what the process exit code means. External consumers (an orchestrator, a CI step, a watchdog)
Index ¶
Examples ¶
Constants ¶
const ( // Success = the verb ran and the underlying tool / SDK call returned // without error. Success = 0 // Generic = catch-all for errors that haven't been classified yet. // New code should not return this; reach for one of the typed codes Generic = 1 // PolicyDenied = coily's pre-flight rejected the invocation // (shell-metacharacter validation, missing required arg, etc). PolicyDenied = 2 // UpstreamFailed = the underlying tool / SDK call ran and returned a // non-zero exit. Stdout/stderr from the tool flow through; the UpstreamFailed = 3 // Internal = coily-internal failure: config load, manifest miss, // audit-write fail, etc. Distinct from PolicyDenied because there's Internal = 4 // UserError = the user supplied something obviously wrong: missing // flag, wrong arg count, bad arg shape that wasn't a metacharacter UserError = 5 )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Coded ¶
type Coded interface {
error
Code() int
// Kind returns a stable lowercase token (e.g. "policy_denied") used
// in the yaml error envelope. Lets the envelope stay decoupled from
Kind() string
}
Coded is the optional interface errors implement to declare their intended exit code. main.go checks this via errors.As; if no error in
func From ¶
From returns the deepest Coded error in the chain, or nil if none.
Example ¶
From recovers a Coded annotation from a wrapped error chain. Use in main() to map a returned error to os.Exit.
package main
import (
"errors"
"fmt"
"github.com/coilysiren/cli-guard/exitcode"
)
func main() {
err := exitcode.New(exitcode.UpstreamFailed, "upstream", errors.New("aws cli exited 7"), "")
wrapped := fmt.Errorf("ssm get-parameter: %w", err)
if coded := exitcode.From(wrapped); coded != nil {
fmt.Println("would os.Exit:", coded.Code())
}
}
Output: would os.Exit: 3
type CodedError ¶
CodedError wraps an error with a code+kind. Unwrap-friendly so callers can still errors.Is / errors.As the underlying cause.
func New ¶
func New(code int, kind string, err error, hint string) *CodedError
New tags an error with a code and kind. Hint is the optional recovery line; attach a reason after construction via WithReason if desired.
Example ¶
Annotate any error with a public exit-code so orchestrators can pattern-match on $? without parsing stderr.
package main
import (
"errors"
"fmt"
"github.com/coilysiren/cli-guard/exitcode"
)
func main() {
err := exitcode.New(exitcode.PolicyDenied, "policy", errors.New("argv rejected"), "fix the input and retry")
fmt.Printf("code=%d kind=%s err=%v\n", err.Code(), err.Kind(), err)
}
Output: code=2 kind=policy err=argv rejected
func (*CodedError) Code ¶
func (e *CodedError) Code() int
Code returns the numeric exit code coily should exit with.
func (*CodedError) Error ¶
func (e *CodedError) Error() string
Error returns the wrapped error's message.
func (*CodedError) HintText ¶
func (e *CodedError) HintText() string
HintText returns the optional one-line recovery hint shown to the user alongside the error envelope. Empty when no hint was attached.
func (*CodedError) Kind ¶
func (e *CodedError) Kind() string
Kind returns the lowercase stable token written into the yaml error envelope.
func (*CodedError) Reason ¶
func (e *CodedError) Reason() string
Reason returns the optional one-line statement of the threat or invariant this rule preserves. Empty when no reason was attached.
func (*CodedError) Unwrap ¶
func (e *CodedError) Unwrap() error
Unwrap returns the underlying cause for errors.Is / errors.As.
func (*CodedError) WithReason ¶
func (e *CodedError) WithReason(reason string) *CodedError
WithReason attaches a why-line to the error and returns the receiver so callers can chain: `return exitcode.New(...).WithReason("...")`.