cli

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Overview

Package cli implements the devproof command line.

Every command is a thin adapter: it parses input, calls one public SDK operation, renders the result, and maps a typed error to an exit code (DP-001). No command contains logic that an embedding application could not reach through the SDK.

The stream discipline here is load-bearing. stdout carries the requested result and nothing else, so `devproof build ... | xargs crane` works and keeps working; every diagnostic, warning, progress indicator, and error goes to stderr. A tool that prints "Building..." to stdout is a tool nobody can safely pipe.

Index

Constants

View Source
const EnvelopeAPIVersion = "devproof.thingz.io/cli/v1alpha1"

EnvelopeAPIVersion identifies the CLI's JSON contract. It is versioned separately from the bundle format: the two change for different reasons.

Variables

This section is empty.

Functions

func Field

func Field(w io.Writer, name, value string)

Field writes an aligned name/value line for text output.

func Run

func Run(ctx context.Context, args []string, streams Streams) int

Run executes the command line and returns a process exit code.

It never calls os.Exit itself. Returning the code lets main decide, and lets a test run the whole command tree in-process and assert on it.

Types

type App

type App struct {
	Streams Streams
	// contains filtered or unexported fields
}

App is the command tree plus the state a run needs.

type Config

type Config struct {
	// Format is the default output rendering.
	Format string `yaml:"format,omitempty"`
	// Verbose and Debug set default diagnostic levels.
	Verbose bool `yaml:"verbose,omitempty"`
	Debug   bool `yaml:"debug,omitempty"`
	// NoColor disables color regardless of terminal detection.
	NoColor bool `yaml:"noColor,omitempty"`
	// Timeout is the default overall operation deadline, as a duration
	// string.
	Timeout string `yaml:"timeout,omitempty"`
	// Policy is a verification policy applied when --policy is not given.
	//
	// A default policy can only make verification stricter: without one,
	// trust reports not-evaluated. There is no setting that can relax
	// verification, because a file that could turn integrity checking off
	// would be the most valuable file on the machine to an attacker.
	Policy string `yaml:"policy,omitempty"`
	// TrustRoot is a default Sigstore trusted root.
	TrustRoot string `yaml:"trustRoot,omitempty"`
	// FulcioURL and RekorURL select non-default Sigstore instances, which is
	// what a private deployment needs.
	FulcioURL string `yaml:"fulcioUrl,omitempty"`
	RekorURL  string `yaml:"rekorUrl,omitempty"`
}

Config is the persisted configuration.

Decoding is strict. A misspelled key in a configuration file is a setting that silently does not apply, and the failure shows up later as behavior nobody can explain.

type Envelope

type Envelope struct {
	APIVersion string   `json:"apiVersion"`
	Kind       string   `json:"kind"`
	Result     any      `json:"result,omitempty"`
	Warnings   []string `json:"warnings,omitempty"`
}

Envelope wraps every JSON result.

The shape is the same for every command so that a caller can find the apiVersion and kind without knowing which command produced the output.

type ErrorEnvelope

type ErrorEnvelope struct {
	APIVersion string       `json:"apiVersion"`
	Kind       string       `json:"kind"`
	Error      ErrorPayload `json:"error"`
}

ErrorEnvelope is the JSON failure shape.

type ErrorPayload

type ErrorPayload struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	Source  string `json:"source,omitempty"`
	Path    string `json:"path,omitempty"`
}

ErrorPayload is the machine-readable half of a failure.

Code and the field names are a stable API. Message is not: it is written for the human deciding what to do next, and nothing should parse it.

type Format

type Format string

Format selects how a result is rendered.

const (
	// FormatText is human-readable output.
	FormatText Format = "text"
	// FormatJSON is one JSON document followed by a newline.
	FormatJSON Format = "json"
)

type Printer

type Printer struct {
	Streams Streams
	Format  Format
	Quiet   bool
	Verbose bool
	Debug   bool
	NoColor bool
	// contains filtered or unexported fields
}

Printer renders results according to the selected output mode.

func (*Printer) Failure

func (p *Printer) Failure(err error, interrupted bool) int

Failure renders an error and returns the process exit code.

In JSON mode the failure envelope goes to stdout, because a caller parsing JSON needs to read the error the same way it reads a result. In text mode stdout stays empty: a pipeline that got no result should receive no bytes.

func (*Printer) Info

func (p *Printer) Info(format string, args ...any)

Info writes an informational line to stderr, when verbose.

func (*Printer) Progress

func (p *Printer) Progress() *Progress

Progress returns the printer's progress reporter.

Owned by the printer so that every path that writes real output can erase a pending progress line first, without each call site having to remember to.

func (*Printer) Result

func (p *Printer) Result(kind string, result any, quiet string, text func(w io.Writer)) error

Result renders a successful outcome.

kind names the result type in JSON. quiet is the single value a pipeline wants — a digest, a path — and is the only thing printed under --quiet, because a script that has to parse prose is a script that breaks.

func (*Printer) Success

func (p *Printer) Success(format string, args ...any)

Success writes a short confirmation line to stderr in text mode.

func (*Printer) Warn

func (p *Printer) Warn(format string, args ...any)

Warn records a warning.

Warnings go to stderr in text mode and into the JSON envelope otherwise, so they never corrupt a piped result either way.

type Progress

type Progress struct {
	// contains filtered or unexported fields
}

Progress reports what a command is currently doing.

It writes to stderr and only when stderr is an interactive terminal. A progress indicator exists for a human watching a slow operation; written to a pipe or a log file it is noise, and written to stdout it is corruption.

Under --verbose the same steps are written as ordinary permanent lines instead, because a CI log is exactly the case where knowing which step was running when something failed is worth the extra output.

func (*Progress) Done

func (p *Progress) Done()

Done erases the transient line.

Called before any other output so that a result, a warning, or an error is never printed on top of a half-erased progress line.

func (*Progress) Step

func (p *Progress) Step(format string, args ...any)

Step reports the operation now in progress.

type Streams

type Streams struct {
	Out io.Writer
	Err io.Writer
	// IsTerminal reports whether Err is an interactive terminal. Progress and
	// color are enabled only when it is.
	IsTerminal bool
}

Streams are a command's output destinations.

Passed rather than taken from the process so that a test can capture them and assert the discipline holds, which is the only way to know it does.

func DefaultStreams

func DefaultStreams() Streams

DefaultStreams returns the process streams.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL