headless

package
v0.31.2 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package headless runs Resterm requests and workflows without the TUI.

The package exposes a library API for CI/CD, automation, and other non-interactive integrations. Choose the entrypoint based on how you run:

  • Call Run for a one-shot execution.
  • Call Build and then RunPlan when you want to prepare once and reuse the same validated plan across retries, repeated runs, or concurrent calls.

The primary workflow is:

  1. Construct Options.
  2. Call Build to prepare and validate a reusable Plan.
  3. Call RunPlan to execute the prepared plan, or call Run for a one-shot run.
  4. Inspect the returned Report, Result, and Step values.
  5. Serialize the report with Report.Encode using JSON, JUnit, or Text.

Reports expose structured failure metadata through Failure values on failed results, steps, and profile iterations. Report.FailureCodes returns the unique failure codes present in a report, and Report.ExitCode returns either detailed classified CI exit codes or the legacy summary pass/fail codes.

WriteJSON, WriteJUnit, and WriteText remain available as helpers over Encode. Programmatic format selection is available through the Format constants JSON, JUnit, and Text, and ParseFormat converts user-provided names into a Format value.

Invalid library inputs are reported as UsageError values. Use IsUsageError to classify them, and errors.Is to match specific sentinels such as ErrNoSourcePath or ErrTooFewTargets.

Index

Examples

Constants

View Source
const (
	ExitPass       = 0
	ExitFailure    = 1
	ExitUsage      = 2
	ExitInternal   = 3
	ExitTimeout    = 20
	ExitNetwork    = 21
	ExitTLS        = 22
	ExitAuth       = 23
	ExitScript     = 24
	ExitFilesystem = 25
	ExitProtocol   = 26
	ExitRoute      = 27
	ExitCanceled   = 130
)
View Source
const DefaultHTTPTimeout = 30 * time.Second

DefaultHTTPTimeout is the timeout applied when Options.HTTP.Timeout is zero.

Variables

View Source
var (
	// ErrNoSourcePath reports that Options.Source.Path was empty.
	ErrNoSourcePath = errors.New("headless: source path is required")

	// ErrNilContext reports that a nil context was passed to Run or RunPlan.
	ErrNilContext = errors.New("headless: nil context")

	// ErrTooFewTargets reports that compare mode was enabled without enough targets.
	ErrTooFewTargets = errors.New("headless: compare requires at least two target environments")

	// ErrInvalidPlan reports that a zero-value or otherwise invalid Plan was used.
	ErrInvalidPlan = errors.New("headless: invalid plan")

	// ErrNilReport reports an attempt to encode a nil report.
	ErrNilReport = errors.New("headless: nil report")

	// ErrNilWriter reports an attempt to write to a nil writer.
	ErrNilWriter = errors.New("headless: nil writer")
)

Functions

func IsUsageError

func IsUsageError(err error) bool

IsUsageError reports whether err contains a UsageError.

Types

type Compare

type Compare struct {
	Baseline string `json:"baseline,omitempty"`
}

Compare contains compare-run summary fields.

type CompareOptions added in v0.27.3

type CompareOptions struct {
	Targets []string `json:"targets,omitempty"`
	Base    string   `json:"base,omitempty"`
}

CompareOptions configures compare runs across multiple environments.

type EnvironmentOptions added in v0.27.3

type EnvironmentOptions struct {
	Set      EnvironmentSet `json:"set,omitempty"`
	Name     string         `json:"name,omitempty"`
	FilePath string         `json:"filePath,omitempty"`
}

EnvironmentOptions controls environment loading and selection.

type EnvironmentSet added in v0.27.3

type EnvironmentSet map[string]map[string]string

EnvironmentSet maps environment names to variable values.

type ExitCodeMode added in v0.31.2

type ExitCodeMode string

ExitCodeMode selects whether Report.ExitCode returns detailed classified codes or the legacy pass/fail summary codes.

const (
	// ExitCodeDetailed returns classified CI exit codes such as timeout,
	// network, TLS, auth, script, filesystem, protocol, route, or canceled.
	ExitCodeDetailed ExitCodeMode = "detailed"
	// ExitCodeSummary returns the legacy pass/fail/usage-style code for reports.
	ExitCodeSummary ExitCodeMode = "summary"
)

type Failure added in v0.31.2

type Failure struct {
	Code     FailureCode     `json:"code,omitempty"`
	Category FailureCategory `json:"category,omitempty"`
	ExitCode int             `json:"exitCode,omitempty"`
	Message  string          `json:"message,omitempty"`
	Source   string          `json:"source,omitempty"`
}

Failure contains structured machine-readable metadata for a failed result, workflow step, compare step, or profile iteration.

type FailureCategory added in v0.31.2

type FailureCategory string

FailureCategory groups failure codes into broader operational categories.

const (
	CategorySemantic   FailureCategory = "semantic"
	CategoryTimeout    FailureCategory = "timeout"
	CategoryNetwork    FailureCategory = "network"
	CategoryTLS        FailureCategory = "tls"
	CategoryAuth       FailureCategory = "auth"
	CategoryScript     FailureCategory = "script"
	CategoryFilesystem FailureCategory = "filesystem"
	CategoryProtocol   FailureCategory = "protocol"
	CategoryRoute      FailureCategory = "route"
	CategoryCanceled   FailureCategory = "canceled"
	CategoryInternal   FailureCategory = "internal"
)

type FailureCode added in v0.31.2

type FailureCode string

FailureCode identifies the stable machine-readable reason for a failed item.

const (
	FailureAssertion   FailureCode = "assertion"
	FailureTraceBudget FailureCode = "trace_budget"
	FailureTimeout     FailureCode = "timeout"
	FailureNetwork     FailureCode = "network"
	FailureTLS         FailureCode = "tls"
	FailureAuth        FailureCode = "auth"
	FailureScript      FailureCode = "script"
	FailureFilesystem  FailureCode = "filesystem"
	FailureProtocol    FailureCode = "protocol"
	FailureRoute       FailureCode = "route"
	FailureCanceled    FailureCode = "canceled"
	FailureInternal    FailureCode = "internal"
	FailureUnknown     FailureCode = "unknown"
)

type Format added in v0.28.2

type Format int
const (
	JSON Format = iota
	JUnit
	Text
)

func ParseFormat added in v0.28.2

func ParseFormat(s string) (Format, error)

func (Format) String added in v0.28.2

func (f Format) String() string

type GRPC

type GRPC struct {
	Code          string `json:"code,omitempty"`
	StatusCode    int    `json:"statusCode,omitempty"`
	StatusMessage string `json:"statusMessage,omitempty"`
}

GRPC contains gRPC response summary fields.

type GRPCOptions added in v0.27.3

type GRPCOptions struct {
	Plaintext *bool `json:"plaintext,omitempty"`
}

GRPCOptions configures default gRPC behavior.

type HTTP

type HTTP struct {
	Status     string `json:"status,omitempty"`
	StatusCode int    `json:"statusCode,omitempty"`
	Protocol   string `json:"protocol,omitempty"`
}

HTTP contains HTTP response summary fields.

type HTTPOptions added in v0.27.3

type HTTPOptions struct {
	Timeout            time.Duration `json:"timeout,omitempty"`
	FollowRedirects    *bool         `json:"followRedirects,omitempty"`
	InsecureSkipVerify bool          `json:"insecureSkipVerify,omitempty"`
	ProxyURL           string        `json:"proxyURL,omitempty"`
}

HTTPOptions configures default HTTP client behavior.

type HistBin

type HistBin struct {
	From  time.Duration `json:"from,omitempty"`
	To    time.Duration `json:"to,omitempty"`
	Count int           `json:"count,omitempty"`
}

HistBin contains one profile histogram bin.

type Kind

type Kind string

Kind identifies the executed result type.

const (
	KindRequest  Kind = "request"
	KindWorkflow Kind = "workflow"
	KindForEach  Kind = "for-each"
	KindCompare  Kind = "compare"
	KindProfile  Kind = "profile"
)

func (Kind) IsValid added in v0.28.2

func (k Kind) IsValid() bool

IsValid reports whether k is a known result kind.

func (Kind) String added in v0.28.2

func (k Kind) String() string

String implements fmt.Stringer.

type Latency

type Latency struct {
	Count  int           `json:"count,omitempty"`
	Min    time.Duration `json:"min,omitempty"`
	Max    time.Duration `json:"max,omitempty"`
	Mean   time.Duration `json:"mean,omitempty"`
	Median time.Duration `json:"median,omitempty"`
	StdDev time.Duration `json:"stdDev,omitempty"`
}

Latency contains aggregate profile latency statistics.

type Options added in v0.27.3

type Options struct {
	Version       string             `json:"version,omitempty"`
	Source        Source             `json:"source,omitempty"`
	WorkspaceRoot string             `json:"workspaceRoot,omitempty"`
	Recursive     bool               `json:"recursive,omitempty"`
	State         StateOptions       `json:"state,omitempty"`
	FailFast      bool               `json:"failFast,omitempty"`
	Environment   EnvironmentOptions `json:"environment,omitempty"`
	Compare       CompareOptions     `json:"compare,omitempty"`
	Profile       ProfileOptions     `json:"profile,omitempty"`
	HTTP          HTTPOptions        `json:"http,omitempty"`
	GRPC          GRPCOptions        `json:"grpc,omitempty"`
	Selection     Selection          `json:"selection,omitempty"`
}

Options configures a headless run.

type Percentile

type Percentile struct {
	Percentile int           `json:"percentile"`
	Value      time.Duration `json:"value,omitempty"`
}

Percentile contains one profile percentile.

type Plan added in v0.29.1

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

Plan stores a prepared run configuration. A Plan can be reused across multiple RunPlan calls, including concurrently. The zero value is invalid.

func Build added in v0.29.1

func Build(o Options) (Plan, error)

Build prepares o for execution and returns a reusable plan. Use Build with RunPlan when you want to validate once and reuse the same source and selection across multiple runs.

type Profile

type Profile struct {
	Count          int              `json:"count,omitempty"`
	Warmup         int              `json:"warmup,omitempty"`
	Delay          time.Duration    `json:"delay,omitempty"`
	TotalRuns      int              `json:"totalRuns,omitempty"`
	WarmupRuns     int              `json:"warmupRuns,omitempty"`
	SuccessfulRuns int              `json:"successfulRuns,omitempty"`
	FailedRuns     int              `json:"failedRuns,omitempty"`
	Latency        *Latency         `json:"latency,omitempty"`
	Percentiles    []Percentile     `json:"percentiles,omitempty"`
	Histogram      []HistBin        `json:"histogram,omitempty"`
	Failures       []ProfileFailure `json:"failures,omitempty"`
}

Profile contains profile-run summary fields.

type ProfileFailure added in v0.27.3

type ProfileFailure struct {
	Iteration  int           `json:"iteration,omitempty"`
	Warmup     bool          `json:"warmup,omitempty"`
	Reason     string        `json:"reason,omitempty"`
	Status     string        `json:"status,omitempty"`
	StatusCode int           `json:"statusCode,omitempty"`
	Duration   time.Duration `json:"duration,omitempty"`
	Failure    *Failure      `json:"failure,omitempty"`
}

ProfileFailure contains one failed profile iteration.

type ProfileOptions added in v0.28.2

type ProfileOptions struct {
	Enabled bool `json:"enabled,omitempty"`
}

ProfileOptions configures profile runs.

type Report

type Report struct {
	SchemaVersion string
	Version       string
	FilePath      string
	EnvName       string
	StartedAt     time.Time
	EndedAt       time.Time
	Duration      time.Duration
	Results       []Result
	Total         int
	Passed        int
	Failed        int
	Skipped       int
	StopReason    StopReason
}

Report contains the results of a headless run.

func Run

func Run(ctx context.Context, opt Options) (*Report, error)

Run executes a request or workflow file and returns a stable public report. Use Run for one-shot execution when you do not need to reuse a prepared plan.

Example
package main

import (
	"bytes"
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"

	"github.com/unkn0wn-root/resterm/headless"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, _ = fmt.Fprint(w, `{"ok":true}`)
	}))
	defer srv.Close()

	dir, err := os.MkdirTemp("", "headless-example-*")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "api.http")
	src := fmt.Sprintf("# @name ok\nGET %s\n", srv.URL)
	err = os.WriteFile(path, []byte(src), 0o600)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Run is the simplest entrypoint when you only need a single execution.
	rep, err := headless.Run(context.Background(), headless.Options{
		Source: headless.Source{Path: path},
	})
	if err != nil {
		fmt.Println(err)
		return
	}

	var out bytes.Buffer
	if err := rep.Encode(&out, headless.Text); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(rep.Passed, rep.Failed)
}
Output:
1 0

func RunPlan added in v0.29.1

func RunPlan(ctx context.Context, pl Plan) (*Report, error)

RunPlan executes a prepared plan and returns a stable public report. Use RunPlan with Build when you want to prepare once and execute the same validated plan multiple times.

Example
package main

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"

	"github.com/unkn0wn-root/resterm/headless"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, _ = fmt.Fprint(w, `{"ok":true}`)
	}))
	defer srv.Close()

	dir, err := os.MkdirTemp("", "headless-example-*")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "api.http")
	src := fmt.Sprintf("# @name ok\nGET %s\n", srv.URL)
	err = os.WriteFile(path, []byte(src), 0o600)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Build once when you want to reuse the same validated input across
	// repeated runs, retries, or concurrent callers.
	pl, err := headless.Build(headless.Options{
		Source: headless.Source{Path: path},
	})
	if err != nil {
		fmt.Println(err)
		return
	}

	rep1, err := headless.RunPlan(context.Background(), pl)
	if err != nil {
		fmt.Println(err)
		return
	}
	rep2, err := headless.RunPlan(context.Background(), pl)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(rep1.Passed, rep2.Passed)
}
Output:
1 1

func (*Report) Encode added in v0.28.2

func (r *Report) Encode(w io.Writer, f Format) error

Encode writes the report in the given format.

func (*Report) ExitCode added in v0.31.2

func (r *Report) ExitCode(mode ExitCodeMode) int

ExitCode returns the report exit code for the requested mode.

func (*Report) FailureCodes added in v0.31.2

func (r *Report) FailureCodes() []FailureCode

FailureCodes returns the unique failure codes present in the report.

func (*Report) HasFailures

func (r *Report) HasFailures() bool

HasFailures reports whether the report contains any failed results.

func (Report) MarshalJSON added in v0.27.3

func (r Report) MarshalJSON() ([]byte, error)

MarshalJSON writes the canonical report JSON format.

func (*Report) WriteJSON

func (r *Report) WriteJSON(w io.Writer) error

WriteJSON writes r as indented JSON.

func (*Report) WriteJUnit

func (r *Report) WriteJUnit(w io.Writer) error

WriteJUnit writes r as JUnit XML.

func (*Report) WriteText

func (r *Report) WriteText(w io.Writer) error

WriteText writes r as a text report.

type Result

type Result struct {
	Kind        Kind
	Name        string
	Method      string
	Target      string
	Environment string
	Status      Status
	Summary     string
	Duration    time.Duration
	Canceled    bool
	SkipReason  string
	Error       string
	ScriptError string
	Failure     *Failure
	HTTP        *HTTP
	GRPC        *GRPC
	Stream      *Stream
	Trace       *Trace
	Tests       []Test
	Compare     *Compare
	Profile     *Profile
	Steps       []Step
}

Result contains one executed request, workflow, compare run, or profile run.

func (Result) Failed

func (r Result) Failed() bool

Failed reports whether the result represents a failure.

func (Result) MarshalJSON added in v0.27.3

func (r Result) MarshalJSON() ([]byte, error)

MarshalJSON writes the canonical result JSON format.

type Selection added in v0.27.3

type Selection struct {
	Request  string `json:"request,omitempty"`
	Workflow string `json:"workflow,omitempty"`
	Tag      string `json:"tag,omitempty"`
	All      bool   `json:"all,omitempty"`
}

Selection narrows which request or workflow to run.

type Source added in v0.29.1

type Source struct {
	Path    string `json:"path,omitempty"`
	Content []byte `json:"-"`
}

Source identifies the request document to execute. Path is required and provides the logical file identity and relative-resolution anchor. Path may be synthetic when Content is provided. Content overrides the bytes loaded from Path when provided.

type StateOptions added in v0.27.3

type StateOptions struct {
	ArtifactDir    string `json:"artifactDir,omitempty"`
	StateDir       string `json:"stateDir,omitempty"`
	PersistGlobals bool   `json:"persistGlobals,omitempty"`
	PersistAuth    bool   `json:"persistAuth,omitempty"`
	History        bool   `json:"history,omitempty"`
}

StateOptions controls artifacts and persisted runtime state.

type Status

type Status string

Status reports whether a result passed, failed, or was skipped.

const (
	StatusPass Status = "pass"
	StatusFail Status = "fail"
	StatusSkip Status = "skip"
)

func (Status) IsValid added in v0.28.2

func (s Status) IsValid() bool

IsValid reports whether s is a known result status.

func (Status) String added in v0.28.2

func (s Status) String() string

String implements fmt.Stringer.

type Step

type Step struct {
	Name        string
	Method      string
	Target      string
	Environment string
	Branch      string
	Iteration   int
	Total       int
	Status      Status
	Summary     string
	Duration    time.Duration
	Canceled    bool
	SkipReason  string
	Error       string
	ScriptError string
	Failure     *Failure
	HTTP        *HTTP
	GRPC        *GRPC
	Stream      *Stream
	Trace       *Trace
	Tests       []Test
}

Step contains one workflow or compare step result.

func (Step) Failed

func (s Step) Failed() bool

Failed reports whether the step represents a failure.

func (Step) MarshalJSON added in v0.27.3

func (s Step) MarshalJSON() ([]byte, error)

MarshalJSON writes the canonical step JSON format.

type StopReason added in v0.31.2

type StopReason string

StopReason explains why a run stopped before all selected work completed. The zero value means the run completed normally.

const (
	// StopReasonFailFast means Options.FailFast stopped execution after a failure.
	StopReasonFailFast StopReason = "fail_fast"
)

type Stream

type Stream struct {
	Kind           string         `json:"kind,omitempty"`
	EventCount     int            `json:"eventCount,omitempty"`
	Summary        map[string]any `json:"summary,omitempty"`
	TranscriptPath string         `json:"transcriptPath,omitempty"`
}

Stream contains streaming response metadata.

type Test

type Test struct {
	Name    string        `json:"name,omitempty"`
	Message string        `json:"message,omitempty"`
	Passed  bool          `json:"passed"`
	Elapsed time.Duration `json:"elapsed,omitempty"`
}

Test contains one assertion result.

type Trace

type Trace struct {
	Duration     time.Duration `json:"duration,omitempty"`
	Error        string        `json:"error,omitempty"`
	Budget       *TraceBudget  `json:"budget,omitempty"`
	Breaches     []TraceBreach `json:"breaches,omitempty"`
	ArtifactPath string        `json:"artifactPath,omitempty"`
}

Trace contains trace summary metadata.

type TraceBreach

type TraceBreach struct {
	Kind   string        `json:"kind,omitempty"`
	Limit  time.Duration `json:"limit,omitempty"`
	Actual time.Duration `json:"actual,omitempty"`
	Over   time.Duration `json:"over,omitempty"`
}

TraceBreach contains one trace budget breach.

type TraceBudget

type TraceBudget struct {
	Total     time.Duration            `json:"total,omitempty"`
	Tolerance time.Duration            `json:"tolerance,omitempty"`
	Phases    map[string]time.Duration `json:"phases,omitempty"`
}

TraceBudget contains trace budget limits.

type UsageError added in v0.27.3

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

UsageError reports invalid input or options passed to the headless API.

func (UsageError) Error added in v0.27.3

func (e UsageError) Error() string

func (UsageError) Unwrap added in v0.27.3

func (e UsageError) Unwrap() error

Jump to

Keyboard shortcuts

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