probe

package module
v1.14.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 44 Imported by: 0

README

English | 日本語





PROBE





Probe is a powerful YAML-based workflow automation tool designed for testing, monitoring, and automation tasks.

GitHub Workflow Status GitHub Release Go Documentation

It is a single Go binary with no runtime to install, so the same file runs on your machine, in CI, and from a cron entry. The exit status reflects the result, and a file written as a test becomes a monitor by adding repeat. Probe uses plugin-based actions to execute workflows, making it highly flexible and extensible. Documentation: probe.linyo.ws

Architecture

Features

Similar software is usually one of two things: a test runner, or a prober that monitors. Most of them speak one protocol. Probe is both, across the protocols a web system is actually made of.

  • One file reaches the whole system. HTTP, gRPC, MySQL, PostgreSQL, SQLite, SMTP, IMAP, SSH, shell and a real browser are built in. A single run can call an endpoint, query the row it wrote, and read the mail it sent, with no glue between three tools.
  • Shared steps live in their own file. A scenario usually starts by logging in, and every scenario after the first repeats it. Put those steps in a job file with its endpoint in defaults, and any workflow runs it with uses: embedded, passing the credentials as vars and reading the token back from outputs. The job's steps appear nested under the step that called it.
  • The same file is a test and a monitor. Add repeat to a job and it runs on an interval, reporting 3/3 success (100.0%). There is no second, rewritten copy of the workflow for monitoring.
  • Jobs are a graph, not a list. needs declares only the order that matters, and everything else runs in parallel. probe dag prints that graph as ASCII or Mermaid. Scenario runners walk a file from top to bottom.
  • It behaves the same everywhere. One Go binary, nothing to install alongside it and no service to keep running, so your terminal, a CI step and a cron entry all do the same thing.
  • Actions are plugins. Each one is a separate process behind go-plugin, so a protocol Probe does not cover yet can be added without forking the binary.

Beyond that, a workflow has outputs to pass data between steps and jobs, test to assert on any response, retry, skipif, iteration, wait and timeout, defaults for settings shared across steps, and merging of several YAML files on one command line.

Understanding Probe covers how these fit together, and Comparison says where k6, Hurl, Venom, runn, Blackbox exporter or GitHub Actions is the better answer.

Quick Start

Install the binary:

go install github.com/linyows/probe/cmd/probe@latest

Write a workflow:

# health-check.yml
name: API Health Check
jobs:
- name: Check API Status
  steps:
  - name: Ping API
    uses: http
    with:
      url: https://api.example.com
      get: /health
    test: res.code == 200

Run it:

probe health-check.yml
API Health Check

⏺ Check API Status (Completed in 0.02s)
  ⎿ 0. ✓  Ping API

Total workflow time: 0.02s ✓ All jobs succeeded

Quickstart goes through this step by step, and Your First Workflow grows it into something you can leave running.

Built-in Actions

Action Use it for
http HTTP requests and their responses
db Queries against MySQL, PostgreSQL and SQLite
smtp Delivering mail
imap Reading a mailbox
mail-latency Measuring delivery latency from received messages
ssh Commands on a remote host
shell Commands on the machine running Probe
browser Driving a real browser
grpc gRPC calls
embedded Running another job file from a step
hello Printing a report line

Documentation

  • Guide — installation, the CLI, and the concepts behind workflows, jobs, steps and data flow
  • How-tos — API testing, monitoring, performance, environments and error handling
  • Tutorials — building a monitoring system, an API test pipeline, and multi-environment tests
  • Reference — YAML configuration, CLI options, built-in functions and environment variables

Runnable workflows live in examples/.

Contributing

Issues, feature requests and pull requests are all welcome.

License

MIT. See LICENSE.

Author

linyows

Documentation

Index

Constants

View Source
const (
	// ExitOK means every job succeeded.
	ExitOK = 0
	// ExitTestFailed means a test did not hold: it evaluated to false, could
	// not be evaluated, or did not evaluate to a boolean.
	ExitTestFailed = 1
	// ExitConfigError means the workflow or the command line was wrong, or a
	// report file could not be written, so the run could not do what it was
	// asked to.
	ExitConfigError = 2
	// ExitActionError means an action returned an error, such as a refused
	// connection or a timeout, so a test could not be checked at all.
	ExitActionError = 3
)

Exit codes of a probe run. They tell apart what a caller such as CI or cron has to do about a failure: a failed test points at the system under test, a configuration error at the workflow or the command line, and an action error at the environment, such as a target that cannot be reached.

View Source
const (
	// MaxLogStringLength is the maximum length for log output to prevent log bloat
	MaxLogStringLength = 200
	// MaxStringLength is the maximum length for general string processing
	MaxStringLength = 1000000
)
View Source
const (
	IconSuccess  = "✓ "
	IconError    = "✗ "
	IconTriangle = "△ "
	IconCircle   = "⏺"
	IconWait     = "🕐︎"
	IconSkip     = "⏭ "
	IconRetry    = "⟳"
)

Icon constants

View Source
const (
	// DefaultMaxRepeatCount is the default upper limit for repeat count
	DefaultMaxRepeatCount = 10000
	// DefaultMaxAttempts is the default upper limit for max attempts
	DefaultMaxAttempts = 10000
	// EnvMaxRepeatCount is the environment variable name for overriding max repeat count
	EnvMaxRepeatCount = "PROBE_MAX_REPEAT_COUNT"
	// EnvMaxAttempts is the environment variable name for overriding max attempts
	EnvMaxAttempts = "PROBE_MAX_ATTEMPTS"
)
View Source
const (
	ReportPassed   = "passed"
	ReportFailed   = "failed"
	ReportSkipped  = "skipped"
	ReportUntested = "untested" // A step that ran but has no test expression
)

Report statuses for the workflow, jobs and steps.

View Source
const (
	FailureAssertion = "assertion"  // The test expression evaluated to false
	FailureTestError = "test_error" // The test expression could not be evaluated
	FailureTestType  = "test_type"  // The test expression did not evaluate to a boolean
	FailureAction    = "action"     // The action itself returned an error
)

Failure kinds recorded on a StepFailure.

View Source
const DefaultSkillDir = ".claude/skills/probe"

DefaultSkillDir is where probe skill install puts the skill when no directory is given: the project-level skills directory of Claude Code.

View Source
const (
	// DefaultStepTimeout is the default timeout for action execution
	DefaultStepTimeout = 5 * time.Minute
)

Variables

View Source
var (
	BuiltinCmd = "builtin-actions"
	Handshake  = plugin.HandshakeConfig{ProtocolVersion: 1, MagicCookieKey: "probe", MagicCookieValue: "actions"}
	PluginMap  = map[string]plugin.Plugin{"actions": &ActionsPlugin{}}
)
View Source
var ErrNoStepSummary = errors.New("GITHUB_STEP_SUMMARY is not set; skipping the github-summary report")

ErrNoStepSummary is returned for a github-summary report when no path was given and GITHUB_STEP_SUMMARY is not set, as on a machine outside GitHub Actions. It is not a failure: the same command line can run anywhere.

View Source
var ErrStepSummaryFull = errors.New("the job summary has no room left under GitHub's 1 MiB limit; skipping the github-summary report")

ErrStepSummaryFull is returned when earlier writes have left no room in the job summary for even a shortened page. Writing anyway would push it past GitHub's limit and lose what the earlier steps wrote, so nothing is written.

Functions

func DiffJSON added in v0.4.0

func DiffJSON(src, target map[string]any) string

DiffJSON compares two `map[string]any` objects strictly and collects differences.

func GetTruncationMessage added in v0.9.0

func GetTruncationMessage() string

GetTruncationMessage returns a colored truncation message

func Guide added in v1.12.0

func Guide(topic string) (string, error)

Guide returns the Markdown page for a topic. An action's page can also be asked for as actions/<name>.

func GuideIndex added in v1.12.0

func GuideIndex() string

GuideIndex renders the list of topics probe guide prints without one.

func InstallSkill added in v1.12.0

func InstallSkill(dir string) (string, error)

InstallSkill writes SKILL.md into dir, creating it, and returns the path it wrote. An existing SKILL.md is replaced, so running it again after an upgrade brings the skill up to date.

The default directory is inside the project, which the user may have checked out from anywhere, so the file is written through replaceFile: a symlink at SKILL.md, or at .claude or another directory on the way, cannot redirect it to a file elsewhere.

func LogActionOutcome added in v1.10.0

func LogActionOutcome(log hclog.Logger, subject string, ret map[string]any, err error)

LogActionOutcome records how an action finished. subject names what was attempted, for example "http request", and is used to build the message.

func LogActionParams added in v1.10.0

func LogActionParams(log hclog.Logger, msg string, with map[string]any)

LogActionParams records the parameters an action received, truncating long values so that a large request body does not flood the log. Actions are separate processes, so their log records reach the workflow runner as JSON on stderr and are re-filtered there by the runner's own level.

func MatchJSON added in v0.4.0

func MatchJSON(src, target map[string]any) bool

MatchJSON compares two `map[string]any` objects strictly. All fields in `src` and `target` must match, including structure and values.

func ParseJSON added in v1.3.0

func ParseJSON(s string) (any, error)

ParseJSON parses a JSON string into a map[string]any or []any.

func Skill added in v1.12.0

func Skill() string

Skill returns the agent skill as Markdown.

func TruncateMapStringAny added in v0.21.0

func TruncateMapStringAny(params map[string]any, maxLen int) map[string]any

TruncateMapStringAny truncates long values in map[string]any for logging

func TruncateMapStringString added in v0.9.0

func TruncateMapStringString(params map[string]string, maxLen int) map[string]string

TruncateMapStringString truncates long values in map[string]string for logging

func TruncateString added in v0.9.0

func TruncateString(s string, maxLen int) string

TruncateString truncates a string if it exceeds the maximum length

Types

type ActionRunner added in v0.18.0

type ActionRunner interface {
	RunActions(name string, with map[string]any, opts RunOptions) (map[string]any, error)
}

ActionRunner defines the interface for running actions

type Actions

type Actions interface {
	Run(with map[string]any) (map[string]any, error)
}

type ActionsArgs

type ActionsArgs []string

type ActionsClient

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

func (*ActionsClient) Run

func (m *ActionsClient) Run(with map[string]any) (map[string]any, error)

type ActionsParams

type ActionsParams map[string]any

type ActionsPlugin

type ActionsPlugin struct {
	plugin.Plugin
	Impl Actions
}

func (*ActionsPlugin) GRPCClient

func (p *ActionsPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (any, error)

func (*ActionsPlugin) GRPCServer

func (p *ActionsPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error

type ActionsServer

type ActionsServer struct {
	Impl Actions
	// contains filtered or unexported fields
}

func (*ActionsServer) Run

func (m *ActionsServer) Run(ctx context.Context, req *pb.RunRequest) (*pb.RunResponse, error)

type BufferedReporter added in v1.11.0

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

BufferedReporter keeps the original behaviour: a spinner during the run and the complete report at the end.

func NewBufferedReporter added in v1.11.0

func NewBufferedReporter(p *Printer) *BufferedReporter

NewBufferedReporter creates a reporter that prints the report at the end.

func (*BufferedReporter) Finish added in v1.11.0

func (r *BufferedReporter) Finish(rs *Result)

func (*BufferedReporter) JobDone added in v1.11.0

func (r *BufferedReporter) JobDone(jobID string, jr *JobResult)

func (*BufferedReporter) Start added in v1.11.0

func (r *BufferedReporter) Start(name, description string)

func (*BufferedReporter) StepDone added in v1.11.0

func (r *BufferedReporter) StepDone(jobID string, sr StepResult)

func (*BufferedReporter) StepStart added in v1.11.0

func (r *BufferedReporter) StepStart(jobID, stepName string)

type Config

type Config struct {
	Log     io.Writer
	Verbose bool
	Timing  bool
	// Output selects how the report is delivered while jobs run.
	Output OutputMode
	// Reports lists the report files written once the run has finished.
	Reports []ReportTarget
}

type DagAsciiJobNode added in v1.0.0

type DagAsciiJobNode struct {
	Job         *Job
	JobID       string
	Level       int      // Depth in DAG (0 = root)
	Width       int      // Box width
	Lines       []string // Rendered lines
	CenterX     int      // X coordinate of center (for connections)
	HasChildren bool     // Whether this job has dependent jobs
}

DagAsciiJobNode represents a rendered job node

type DagAsciiRenderer added in v1.0.0

type DagAsciiRenderer struct {
	DagRendererBase
	// contains filtered or unexported fields
}

DagAsciiRenderer renders detailed workflow graphs with job nodes and steps

func NewDagAsciiRenderer added in v1.0.0

func NewDagAsciiRenderer(w *Workflow) *DagAsciiRenderer

NewDagAsciiRenderer creates a new DagAsciiRenderer

func (*DagAsciiRenderer) Render added in v1.0.0

func (r *DagAsciiRenderer) Render() string

Render generates the detailed ASCII art graph

type DagMermaidRenderer added in v1.0.0

type DagMermaidRenderer struct {
	DagRendererBase
	// contains filtered or unexported fields
}

DagMermaidRenderer renders workflow graphs in Mermaid format

func NewDagMermaidRenderer added in v1.0.0

func NewDagMermaidRenderer(w *Workflow) *DagMermaidRenderer

NewDagMermaidRenderer creates a new DagMermaidRenderer

func (*DagMermaidRenderer) Render added in v1.0.0

func (r *DagMermaidRenderer) Render() string

Render generates the Mermaid flowchart representation

type DagRendererBase added in v1.1.0

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

DagRendererBase provides common functionality for DAG renderers

func NewDagRendererBase added in v1.1.0

func NewDagRendererBase(w *Workflow) DagRendererBase

NewDagRendererBase creates a new DagRendererBase

func (*DagRendererBase) ExpandPath added in v1.1.0

func (b *DagRendererBase) ExpandPath(path string) string

ExpandPath expands template variables in the path using evaluated workflow vars

func (*DagRendererBase) GetEvaluatedVars added in v1.1.0

func (b *DagRendererBase) GetEvaluatedVars() map[string]any

GetEvaluatedVars returns evaluated vars with lazy loading

func (*DagRendererBase) ResolvePath added in v1.1.0

func (b *DagRendererBase) ResolvePath(path string) string

ResolvePath resolves a (potentially relative) path using a fixed priority order:

  1. If the path is absolute, it is returned as-is.
  2. If workflow.basePath is set, first try the path relative to the workflow directory (workflow.basePath/path).
  3. If not found, try the path relative to the parent of the workflow directory (for project-root relative paths; parentDir/path).
  4. If still not found, fall back to resolving the path from the current working directory using filepath.Abs, which matches the runtime's default behavior.

type ErrorType added in v0.7.0

type ErrorType string

ErrorType represents different categories of errors

const (
	ErrorTypeValidation    ErrorType = "validation"
	ErrorTypeExecution     ErrorType = "execution"
	ErrorTypeConfiguration ErrorType = "configuration"
	ErrorTypeNetwork       ErrorType = "network"
	ErrorTypeFile          ErrorType = "file"
	ErrorTypeAction        ErrorType = "action"
	ErrorTypeDependency    ErrorType = "dependency"
)

type Executor added in v0.8.0

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

Executor handles job execution with buffered output

func NewExecutor added in v0.8.0

func NewExecutor(w *Workflow, job *Job) *Executor

NewExecutor creates a new job executor

func (*Executor) Execute added in v0.8.0

func (e *Executor) Execute(ctx JobContext) bool

Execute runs a job with buffered output

type ExitStatus added in v0.19.0

type ExitStatus int

ExitStatus represents the unified status across all actions

const (
	ExitStatusSuccess ExitStatus = 0 // Action succeeded
	ExitStatusFailure ExitStatus = 1 // Action failed
)

func (ExitStatus) Int added in v0.19.0

func (e ExitStatus) Int() int

Int returns the ExitStatus as an int for comparison

func (ExitStatus) String added in v0.19.0

func (e ExitStatus) String() string

String returns the ExitStatus as a string

type Expr added in v0.2.0

type Expr struct{}

func (*Expr) Eval added in v0.3.0

func (e *Expr) Eval(input string, env any) (any, error)

func (*Expr) EvalOrEvalTemplate added in v0.4.0

func (e *Expr) EvalOrEvalTemplate(input string, env any) (string, error)

func (*Expr) EvalTemplate added in v0.2.0

func (e *Expr) EvalTemplate(input string, env any) (string, error)

func (*Expr) EvalTemplateMap added in v0.4.0

func (e *Expr) EvalTemplateMap(input map[string]any, env any) map[string]any

func (*Expr) EvalTemplateWithTypePreservation added in v0.21.0

func (e *Expr) EvalTemplateWithTypePreservation(input string, env any) (any, error)

func (*Expr) Options added in v0.4.0

func (e *Expr) Options(env any) []ex.Option

Options builds the expr options used to compile every workflow expression.

Two guards that used to live here have been removed because neither did anything. ex.DisableBuiltin had no effect on all / any / one / filter / map / count: expr's parser recognises those as predicate builtins before it looks at the disabled set (parser.go, the `predicates` table), so the calls were dead and the functions have always been reachable. A per-key blocklist that filtered the environment was equally inert, because the filtered copy only ever reached the type checker while ex.Run receives the caller's env, and enforcing it would have broken the documented way of reading credentials into `vars`.

What still bounds an expression is the length check in validateExpression, the evaluation timeout in executeWithTimeout, and the argument limits on the functions registered below.

type FailureReport added in v1.12.0

type FailureReport struct {
	Kind     string         `json:"kind"`
	Message  string         `json:"message"`
	Request  map[string]any `json:"request,omitempty"`
	Response map[string]any `json:"response,omitempty"`
}

FailureReport says why a step failed.

type GuideTopic added in v1.12.0

type GuideTopic struct {
	Name  string // what to pass to probe guide
	Group string // the heading it is listed under
	Title string // the page's first heading
	// contains filtered or unexported fields
}

GuideTopic is one page probe guide can print.

func GuideTopics added in v1.12.0

func GuideTopics() []GuideTopic

GuideTopics lists every topic, references first, then one per action, then the concepts.

type Interval added in v0.6.0

type Interval struct {
	time.Duration
}

Interval represents a time interval that can be specified as a number (seconds) or duration string

func (Interval) MarshalYAML added in v0.6.0

func (i Interval) MarshalYAML() (any, error)

MarshalYAML implements custom YAML marshaling for Interval

func (*Interval) UnmarshalYAML added in v0.6.0

func (i *Interval) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements custom YAML unmarshaling for Interval

type Job

type Job struct {
	Name     string   `yaml:"name" validate:"required"`
	ID       string   `yaml:"id,omitempty"`
	Needs    []string `yaml:"needs,omitempty"`
	Steps    []*Step  `yaml:"steps" validate:"required"`
	Repeat   *Repeat  `yaml:"repeat"`
	Defaults any      `yaml:"defaults"`
	SkipIf   string   `yaml:"skipif,omitempty"`
}

func LoadEmbeddedJob added in v1.1.0

func LoadEmbeddedJob(path string) (*Job, error)

LoadEmbeddedJob loads a job definition from an embedded YAML file

func (*Job) RunIndependently added in v0.18.0

func (j *Job) RunIndependently(vars map[string]any, printer *Printer, jobID string) (bool, map[string]any, string, string, time.Duration)

RunIndependently executes a job independently with its own context and result tracking Returns success/failure status, outputs, report, error message, and duration

func (*Job) Start

func (j *Job) Start(ctx JobContext) error

type JobContext

type JobContext struct {
	Vars map[string]any `expr:"vars"`
	Config
	Failed bool
	// Current job ID for this context
	CurrentJobID string
	// Repeat tracking
	IsRepeating   bool
	RepeatCurrent int
	RepeatTotal   int
	StepCounters  map[int]StepRepeatCounter // step index -> counter

	// Print writer
	Printer *Printer
	// Result for managing job-level output
	Result *Result
	// Job scheduler for managing job dependencies and execution
	JobScheduler *JobScheduler
	// Shared outputs across all jobs (accessible via expressions as "outputs")
	Outputs *Outputs `expr:"outputs"`
	// contains filtered or unexported fields
}

JobContext provides context data for job execution

func (*JobContext) SetFailed added in v0.2.0

func (j *JobContext) SetFailed()

SetFailed marks the job context as failed

type JobReport added in v1.12.0

type JobReport struct {
	ID         string       `json:"id"`
	Name       string       `json:"name"`
	Status     string       `json:"status"`
	StartedAt  time.Time    `json:"started_at"`
	DurationMs int64        `json:"duration_ms"`
	Steps      []StepReport `json:"steps"`
}

JobReport is one job of a Report.

type JobResult added in v0.8.0

type JobResult struct {
	JobName     string
	JobID       string
	Status      string
	StartTime   time.Time
	EndTime     time.Time
	Success     bool
	StepResults []StepResult // Store all step results for this job
	// contains filtered or unexported fields
}

JobResult stores execution results for a job

type JobScheduler added in v0.5.0

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

func NewJobScheduler added in v0.5.0

func NewJobScheduler() *JobScheduler

func (*JobScheduler) AddJob added in v0.5.0

func (js *JobScheduler) AddJob(job *Job) error

func (*JobScheduler) AllJobsCompleted added in v0.5.0

func (js *JobScheduler) AllJobsCompleted() bool

func (*JobScheduler) CanRunJob added in v0.5.0

func (js *JobScheduler) CanRunJob(jobID string) bool

func (*JobScheduler) GetRepeatInfo added in v0.5.0

func (js *JobScheduler) GetRepeatInfo(jobID string) (current, target int)

GetRepeatInfo returns current repeat counter and target for a job

func (*JobScheduler) GetRunnableJobs added in v0.5.0

func (js *JobScheduler) GetRunnableJobs() []string

func (*JobScheduler) IncrementRepeatCounter added in v0.5.0

func (js *JobScheduler) IncrementRepeatCounter(jobID string)

IncrementRepeatCounter increments the repeat counter for a job

func (*JobScheduler) MarkJobsWithFailedDependencies added in v0.6.0

func (js *JobScheduler) MarkJobsWithFailedDependencies() []string

MarkJobsWithFailedDependencies marks jobs as failed if their dependencies have failed. It iterates until no more jobs are newly marked, propagating failures transitively through multi-level dependency chains.

func (*JobScheduler) SetJobStatus added in v0.5.0

func (js *JobScheduler) SetJobStatus(jobID string, status JobStatus, success bool)

func (*JobScheduler) ShouldRepeatJob added in v0.5.0

func (js *JobScheduler) ShouldRepeatJob(jobID string) bool

ShouldRepeatJob checks if a job should be repeated

func (*JobScheduler) ValidateDependencies added in v0.5.0

func (js *JobScheduler) ValidateDependencies() error

type JobStatus added in v0.5.0

type JobStatus int
const (
	JobPending JobStatus = iota
	JobRunning
	JobCompleted
	JobFailed
)

type LogLevel added in v0.7.0

type LogLevel int

LogLevel defines different logging levels

const (
	LogLevelDebug LogLevel = iota
	LogLevelInfo
	LogLevelWarn
	LogLevelError
)

type Masker added in v1.12.0

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

Masker hides secret values in everything Probe prints or writes. It starts with the secrets the workflow declares and learns the values of credential headers as actions are about to send them, so that a token obtained at run time is hidden too. A nil Masker hides only credential headers in the maps passed to Map, and learns nothing.

func NewMasker added in v1.12.0

func NewMasker(secrets []string, env map[string]string) *Masker

NewMasker builds a Masker for the environment variables named in secrets. Each value is replaced by <secret:NAME>. A name that is not set, or set to an empty string, has nothing to hide and is skipped.

func (*Masker) Learn added in v1.12.0

func (m *Masker) Learn(data map[string]any)

Learn registers the values of credential headers found anywhere in data, so that they are hidden from then on. It is called with an action's parameters before the action runs, which is what keeps them out of the action's own log records.

func (*Masker) Map added in v1.12.0

func (m *Masker) Map(data map[string]any) map[string]any

Map returns a copy of a request or response with secret values hidden in every string, and the values of credential headers replaced outright. The original is left untouched, since tests and outputs still need the real values. A nil map stays nil.

func (*Masker) String added in v1.12.0

func (m *Masker) String(s string) string

String hides every secret value in s.

func (*Masker) Writer added in v1.12.0

func (m *Masker) Writer(w io.Writer) io.Writer

Writer wraps w so that secret values are hidden in what is written to it. Every caller writes whole messages or lines, so a value is never split across two writes. The wrapper consults the masker on each write, so values learned later are hidden too.

type MockActionRunner added in v0.18.0

type MockActionRunner struct {
	Results map[string]map[string]any
	Errors  map[string]error
}

MockActionRunner implements ActionRunner for testing

func NewMockActionRunner added in v0.18.0

func NewMockActionRunner() *MockActionRunner

NewMockActionRunner creates a new mock action runner

func (*MockActionRunner) RunActions added in v0.18.0

func (m *MockActionRunner) RunActions(name string, with map[string]any, opts RunOptions) (map[string]any, error)

RunActions returns the mocked result or error for the given action

func (*MockActionRunner) SetError added in v0.18.0

func (m *MockActionRunner) SetError(actionName string, err error)

SetError sets the expected error for an action

func (*MockActionRunner) SetResult added in v0.18.0

func (m *MockActionRunner) SetResult(actionName string, result map[string]any)

SetResult sets the expected result for an action

type NameTakenError added in v1.14.0

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

NameTakenError reports an output whose name was taken before it was published, so that outputs.<name> holds something else. It is a warning: the step's value is kept under its id when that can be.

func (*NameTakenError) Error added in v1.14.0

func (e *NameTakenError) Error() string

type OutputMode added in v1.11.0

type OutputMode int

OutputMode selects how a workflow run delivers its report.

const (
	// OutputModeAuto picks spinner on an interactive terminal and stream otherwise.
	OutputModeAuto OutputMode = iota
	// OutputModeSpinner shows a spinner while running and prints the whole
	// report once every job has finished.
	OutputModeSpinner
	// OutputModeStream prints each job block as soon as it is final and logs
	// step progress to stderr while jobs are still running.
	OutputModeStream
)

func ParseOutputMode added in v1.11.0

func ParseOutputMode(s string) (OutputMode, error)

ParseOutputMode converts a user supplied name into an OutputMode.

func (OutputMode) String added in v1.11.0

func (m OutputMode) String() string

type Outputs added in v0.7.0

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

Outputs manages step outputs across the entire workflow

func NewOutputs added in v0.7.0

func NewOutputs() *Outputs

NewOutputs creates a new Outputs instance

func (*Outputs) Get added in v0.7.0

func (o *Outputs) Get(stepID string) (map[string]any, bool)

Get retrieves outputs for a step (existing functionality)

func (*Outputs) GetAll added in v0.7.0

func (o *Outputs) GetAll() map[string]any

GetAll returns all outputs (safe copy for expression evaluation). A run's own outputs stand in front of its parent's.

func (*Outputs) GetAllWithFlat added in v0.15.0

func (o *Outputs) GetAllWithFlat() map[string]any

GetAllWithFlat returns all outputs including flat access for expression evaluation

func (*Outputs) GetConflicts added in v0.15.0

func (o *Outputs) GetConflicts() map[string][]string

GetConflicts returns information about conflicted output names

func (*Outputs) GetFlat added in v0.15.0

func (o *Outputs) GetFlat(outputName string) (any, bool)

GetFlat retrieves output by name directly (new functionality)

func (*Outputs) Set added in v0.7.0

func (o *Outputs) Set(stepID string, outputs map[string]any) error

Set stores outputs for a step with flat access support

type PluginActionRunner added in v0.18.0

type PluginActionRunner struct{}

PluginActionRunner implements ActionRunner using the plugin system

func (*PluginActionRunner) RunActions added in v0.18.0

func (p *PluginActionRunner) RunActions(name string, with map[string]any, opts RunOptions) (map[string]any, error)

RunActions executes an action using the plugin system

type Printer added in v0.7.0

type Printer struct {
	Buffer    map[string]*strings.Builder
	BufferIDs []string // Order preservation
	// contains filtered or unexported fields
}

Printer implements PrintWriter for console print

func NewPrinter added in v0.7.0

func NewPrinter(verbose bool, bufferIDs []string) *Printer

NewPrinter creates a new console print writer

func (*Printer) AddSpinnerSuffix added in v0.8.0

func (p *Printer) AddSpinnerSuffix(txt string)

func (*Printer) Fprint added in v0.18.0

func (p *Printer) Fprint(w io.Writer, a ...any)

func (*Printer) Fprintf added in v0.18.0

func (p *Printer) Fprintf(w io.Writer, f string, a ...any)

func (*Printer) Fprintln added in v0.18.0

func (p *Printer) Fprintln(w io.Writer, a ...any)

func (*Printer) GenerateReport added in v0.15.0

func (p *Printer) GenerateReport(rs *Result) string

GenerateReport generates a complete workflow report string using Result data

func (*Printer) GenerateReportOnlySteps added in v0.16.2

func (p *Printer) GenerateReportOnlySteps(rs *Result) string

func (*Printer) LogDebug added in v0.7.0

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

LogDebug prints debug messages (only in verbose mode)

func (*Printer) LogError added in v0.7.0

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

LogError prints error messages to stderr

func (*Printer) LogWarn added in v0.7.0

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

LogWarn prints a warning to the error writer: something the user should know about that does not make the run fail.

func (*Printer) Masker added in v1.12.0

func (p *Printer) Masker() *Masker

Masker returns the masker the printer applies. It is nil when none was installed, and on a nil Printer, which some contexts run without.

func (*Printer) PrintEchoContent added in v0.10.0

func (p *Printer) PrintEchoContent(content string)

PrintEchoContent prints echo content with proper indentation in verbose mode

func (*Printer) PrintError added in v0.7.0

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

PrintError prints an error message

func (*Printer) PrintHeader added in v0.8.0

func (p *Printer) PrintHeader(name, description string)

PrintHeader prints the workflow name and description

func (*Printer) PrintMapData added in v0.10.0

func (p *Printer) PrintMapData(data map[string]any)

PrintMapData prints map data with proper formatting for nested structures

func (*Printer) PrintReport added in v0.8.0

func (p *Printer) PrintReport(rs *Result)

PrintReport prints a complete workflow report using Result data

func (*Printer) PrintRequestResponse added in v0.10.0

func (p *Printer) PrintRequestResponse(stepIdx int, stepName string, req, res map[string]any, rt string)

PrintRequestResponse prints request and response data with proper formatting

func (*Printer) PrintSeparator added in v0.7.0

func (p *Printer) PrintSeparator()

PrintSeparator prints a separator line for verbose output

func (*Printer) PrintTestResult added in v0.10.0

func (p *Printer) PrintTestResult(success bool, testExpr string, context any)

PrintTestResult prints test result in verbose mode

func (*Printer) PrintVerbose added in v0.7.0

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

PrintVerbose prints verbose output (only if verbose mode is enabled)

func (*Printer) Reporter added in v1.11.0

func (p *Printer) Reporter() Reporter

Reporter returns the installed output strategy, or nil when none was set.

func (*Printer) SetBufferIDs added in v1.11.0

func (p *Printer) SetBufferIDs(ids []string)

SetBufferIDs records the job order the report is rendered in. Workflow.Start sets it once job IDs are assigned, because a caller cannot know an ID that the scheduler generates for a job that omitted one.

func (*Printer) SetMasker added in v1.12.0

func (p *Printer) SetMasker(m *Masker)

SetMasker installs the masker applied to everything the printer writes.

func (*Printer) SetReporter added in v1.11.0

func (p *Printer) SetReporter(r Reporter)

SetReporter installs the output strategy used for this run.

func (*Printer) StartSpinner added in v0.8.0

func (p *Printer) StartSpinner()

func (*Printer) StepStart added in v1.11.0

func (p *Printer) StepStart(jobID, stepName string)

StepStart announces that a step began. The buffered reporter turns this into the spinner suffix, the stream reporter into a stderr progress line.

func (*Printer) StopSpinner added in v0.8.0

func (p *Printer) StopSpinner()

type Probe

type Probe struct {
	FilePath string

	Config Config
	// contains filtered or unexported fields
}

func New

func New(path string, v bool) *Probe

func (*Probe) DagAscii added in v1.0.0

func (p *Probe) DagAscii() (string, error)

DagAscii returns the ASCII art representation of the workflow job dependencies with steps

func (*Probe) DagMermaid added in v1.0.0

func (p *Probe) DagMermaid() (string, error)

DagMermaid returns the Mermaid format representation of the workflow job dependencies

func (*Probe) Do

func (p *Probe) Do() error

func (*Probe) ExitStatus added in v0.2.0

func (p *Probe) ExitStatus() int

func (*Probe) Load

func (p *Probe) Load() error

type ProbeError added in v0.7.0

type ProbeError struct {
	Type      ErrorType
	Operation string
	Message   string
	Cause     error
	Context   map[string]any
}

ProbeError is the base error type with context information

func NewActionError added in v0.7.0

func NewActionError(operation, message string, cause error) *ProbeError

func NewConfigurationError added in v0.7.0

func NewConfigurationError(operation, message string, cause error) *ProbeError

func NewExecutionError added in v0.7.0

func NewExecutionError(operation, message string, cause error) *ProbeError

func NewFileError added in v0.7.0

func NewFileError(operation, message string, cause error) *ProbeError

func NewProbeError added in v0.7.0

func NewProbeError(errorType ErrorType, operation, message string, cause error) *ProbeError

NewProbeError creates a new ProbeError

func (*ProbeError) Error added in v0.7.0

func (e *ProbeError) Error() string

func (*ProbeError) Is added in v0.7.0

func (e *ProbeError) Is(target error) bool

func (*ProbeError) Unwrap added in v0.7.0

func (e *ProbeError) Unwrap() error

func (*ProbeError) WithContext added in v0.7.0

func (e *ProbeError) WithContext(key string, value any) *ProbeError

WithContext adds context information to the error

type Repeat

type Repeat struct {
	Count    int      `yaml:"count" validate:"required,gte=0"`
	Interval Interval `yaml:"interval"`
	Async    bool     `yaml:"async,omitempty"`
}

Repeat defines the repeat configuration for jobs

func (*Repeat) Validate added in v0.25.0

func (r *Repeat) Validate() error

Validate performs custom validation for Repeat

type RepeatReport added in v1.12.0

type RepeatReport struct {
	Total   int `json:"total"`
	Success int `json:"success"`
	Failure int `json:"failure"`
}

RepeatReport records the outcome of every iteration of a repeated job.

type Report added in v1.12.0

type Report struct {
	Name        string        `json:"name"`
	Description string        `json:"description,omitempty"`
	Status      string        `json:"status"`
	StartedAt   time.Time     `json:"started_at"`
	FinishedAt  time.Time     `json:"finished_at"`
	DurationMs  int64         `json:"duration_ms"`
	Summary     ReportSummary `json:"summary"`
	Jobs        []JobReport   `json:"jobs"`
}

Report is the result of a workflow run in a form meant for machines: the JSON file is this structure as is, and the other formats are rendered from it.

func BuildReport added in v1.12.0

func BuildReport(name, description string, rs *Result, order []string, startedAt, finishedAt time.Time) *Report

BuildReport assembles a Report from the results of a run. Jobs are listed in the given order, which is the order they are declared in the workflow.

func (*Report) Mask added in v1.12.0

func (r *Report) Mask(m *Masker)

Mask hides secrets in every text the report carries, and credential headers in failed steps' requests and responses. It masks the data before it is rendered, because JSON and XML escape quotes, backslashes and ampersands, and a secret containing one would no longer match in the rendered file.

func (*Report) Write added in v1.12.0

func (r *Report) Write(t ReportTarget) error

Write renders the report in the target's format and writes it to the target's path, creating parent directories as needed.

func (*Report) WriteJSON added in v1.12.0

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

WriteJSON writes the report as indented JSON.

func (*Report) WriteJUnit added in v1.12.0

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

WriteJUnit writes the report as JUnit XML.

func (*Report) WriteMarkdown added in v1.12.0

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

WriteMarkdown writes the report as a Markdown page: a summary line, a table of jobs, and a section for every failed step with its test, the reason it failed, and the request and response. The page is meant to be read as is, for example as a GitHub job summary or by a coding agent.

type ReportCount added in v1.12.0

type ReportCount struct {
	Total    int `json:"total"`
	Passed   int `json:"passed"`
	Failed   int `json:"failed"`
	Skipped  int `json:"skipped"`
	Untested int `json:"untested,omitempty"`
}

ReportCount is a tally by status.

type ReportFormat added in v1.12.0

type ReportFormat string

ReportFormat names a report file format.

const (
	ReportJSON     ReportFormat = "json"
	ReportJUnit    ReportFormat = "junit"
	ReportMarkdown ReportFormat = "markdown"
	// ReportGitHubSummary appends the Markdown page to the GitHub Actions job
	// summary, the file GITHUB_STEP_SUMMARY names.
	ReportGitHubSummary ReportFormat = "github-summary"
)

type ReportSummary added in v1.12.0

type ReportSummary struct {
	Jobs  ReportCount `json:"jobs"`
	Steps ReportCount `json:"steps"`
}

ReportSummary counts jobs and steps by status.

type ReportTarget added in v1.12.0

type ReportTarget struct {
	Format ReportFormat
	Path   string
}

ReportTarget is one report file to write after a run.

func ParseReportTargets added in v1.12.0

func ParseReportTargets(s string) ([]ReportTarget, error)

ParseReportTargets parses a comma separated list of format[=path] entries, such as "junit=out/junit.xml,json". A format without a path is written to its default file name in the current directory.

type Reporter added in v1.11.0

type Reporter interface {
	Start(name, description string)
	StepStart(jobID, stepName string)
	StepDone(jobID string, sr StepResult)
	JobDone(jobID string, jr *JobResult)
	Finish(rs *Result)
}

Reporter decides when the parts of a workflow report reach the user. Jobs run concurrently, so implementations are called from several goroutines and must serialize their own writes.

type ResponseTime added in v0.18.0

type ResponseTime struct {
	Duration string  `expr:"duration"`
	Sec      float64 `expr:"sec"`
}

ResponseTime provides response time information for expressions

type Result added in v0.8.0

type Result struct {
	Jobs map[string]*JobResult
	// contains filtered or unexported fields
}

Result manages execution results for multiple jobs

func NewResult added in v0.8.0

func NewResult() *Result

NewResult creates a new Result instance

func (*Result) AddStepResult added in v0.8.0

func (rs *Result) AddStepResult(jobID string, stepResult StepResult)

AddStepResult adds a StepResult to the specified job result

func (*Result) SetReporter added in v1.11.0

func (rs *Result) SetReporter(r Reporter)

SetReporter installs the reporter notified when steps and jobs finish.

type RetryReport added in v1.12.0

type RetryReport struct {
	Attempts int `json:"attempts"`
	Max      int `json:"max"`
}

RetryReport records how many attempts a retried step took.

type RunOptions added in v1.11.0

type RunOptions struct {
	// Verbose raises the action's log level to debug.
	Verbose bool
	// Quiet silences the action's own log records. It is set for a retry
	// attempt that still has another attempt left: actions have no notion of
	// being retried, so a failure there would otherwise be reported at error
	// level even though the step goes on to succeed.
	Quiet bool
	// Masker hides the workflow's secrets in the action's log records.
	Masker *Masker
}

RunOptions controls how a single action invocation is run and logged.

type StatusType added in v0.6.0

type StatusType int

StatusType represents the status of execution

const (
	StatusSuccess StatusType = iota
	StatusError
	StatusWarning
	StatusSkipped
)

type Step

type Step struct {
	Name      string            `yaml:"name"`
	ID        string            `yaml:"id,omitempty"`
	Uses      string            `yaml:"uses" validate:"required"`
	With      map[string]any    `yaml:"with"`
	Test      string            `yaml:"test"`
	Echo      string            `yaml:"echo"`
	Vars      map[string]any    `yaml:"vars"`
	Iteration []map[string]any  `yaml:"iteration"`
	Wait      string            `yaml:"wait,omitempty"`
	SkipIf    string            `yaml:"skipif,omitempty"`
	Outputs   map[string]string `yaml:"outputs,omitempty"`
	Retry     *StepRetry        `yaml:"retry,omitempty"`
	Timeout   Interval          `yaml:"timeout,omitempty"`

	Idx  int   `yaml:"-"`
	Expr *Expr `yaml:"-"`
	// contains filtered or unexported fields
}

func (*Step) Do added in v0.5.0

func (st *Step) Do(jCtx *JobContext)

func (*Step) DoTest added in v0.5.0

func (st *Step) DoTest(printer *Printer) (string, bool)

func (*Step) SetCtx added in v0.4.0

func (st *Step) SetCtx(j JobContext, override map[string]any)

type StepContext added in v0.5.0

type StepContext struct {
	Vars        map[string]any `expr:"vars"`
	Res         map[string]any `expr:"res"`
	Req         map[string]any `expr:"req"`
	RT          ResponseTime   `expr:"rt"`
	Report      string         `expr:"report"`
	Outputs     map[string]any `expr:"outputs"`
	Status      int            `expr:"status"`
	RepeatIndex int            `expr:"repeat_index"`
}

StepContext provides context data for step expression evaluation

type StepFailure added in v1.12.0

type StepFailure struct {
	Kind    string
	Message string
	// Request and Response are what the action sent and received. They are left
	// nil when the action asked not to be dumped (res.dump: false).
	Request  map[string]any
	Response map[string]any
}

StepFailure describes a failed step without terminal formatting, so that reports can serialize it.

type StepRepeatCounter added in v0.6.0

type StepRepeatCounter struct {
	SuccessCount int
	FailureCount int
	Name         string
	LastResult   bool
	RepeatTotal  int      // Total number of times the step should be repeated
	EchoOutputs  []string // Formatted echo output captured per iteration
}

StepRepeatCounter tracks the execution results of repeated steps

type StepReport added in v1.12.0

type StepReport struct {
	Index      int            `json:"index"`
	Name       string         `json:"name"`
	Status     string         `json:"status"`
	Test       string         `json:"test,omitempty"`
	DurationMs int64          `json:"duration_ms"`
	Retry      *RetryReport   `json:"retry,omitempty"`
	Repeat     *RepeatReport  `json:"repeat,omitempty"`
	Echo       string         `json:"echo,omitempty"`
	Failure    *FailureReport `json:"failure,omitempty"`
}

StepReport is one step of a JobReport.

type StepResult added in v0.6.0

type StepResult struct {
	Index         int
	Name          string
	Status        StatusType
	StartedAt     time.Time
	RT            string
	RTSec         float64
	WaitTime      string
	TestOutput    string
	EchoOutput    string
	Report        string
	HasTest       bool
	RetryAttempt  int                // Number of attempts made (0 = retry not performed, 1 = succeeded first try)
	RetryMax      int                // Maximum retry attempts configured
	RepeatCounter *StepRepeatCounter // For repeat execution information
	// The fields below feed the report files. Unlike StartedAt and RT they are
	// recorded whether or not --timing is set, and they carry no terminal styling.
	Test    string        // The test expression, empty when the step has none
	Elapsed time.Duration // Wall time from the action's start to the result
	Failure *StepFailure  // Why the step failed; nil unless Status is StatusError
}

StepResult represents the result of a step execution

type StepRetry added in v0.19.0

type StepRetry struct {
	MaxAttempts  int      `yaml:"max_attempts" validate:"required,gte=1"`
	Interval     Interval `yaml:"interval"`
	InitialDelay Interval `yaml:"initial_delay,omitempty"`
}

StepRetry defines the retry configuration for steps until success (status 0)

func (*StepRetry) Validate added in v0.25.0

func (s *StepRetry) Validate() error

Validate performs custom validation for StepRetry

type StreamReporter added in v1.11.0

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

StreamReporter prints the report incrementally.

A job block is only printed once the job is final, which keeps blocks from interleaving even though jobs run concurrently. Blocks are held back until every earlier job in workflow order has been printed, so the finished report is identical to the buffered one. Step level progress goes to stderr, which is what keeps a CI log alive while the first job is still running.

func NewStreamReporter added in v1.11.0

func NewStreamReporter(p *Printer) *StreamReporter

NewStreamReporter creates a reporter that flushes job blocks as they finish.

func (*StreamReporter) Finish added in v1.11.0

func (r *StreamReporter) Finish(rs *Result)

func (*StreamReporter) JobDone added in v1.11.0

func (r *StreamReporter) JobDone(jobID string, jr *JobResult)

func (*StreamReporter) Start added in v1.11.0

func (r *StreamReporter) Start(name, description string)

func (*StreamReporter) StepDone added in v1.11.0

func (r *StreamReporter) StepDone(jobID string, sr StepResult)

func (*StreamReporter) StepStart added in v1.11.0

func (r *StreamReporter) StepStart(jobID, stepName string)

type Workflow

type Workflow struct {
	Name        string         `yaml:"name" validate:"required"`
	Description string         `yaml:"description,omitempty"`
	Jobs        []Job          `yaml:"jobs" validate:"required"`
	Vars        map[string]any `yaml:"vars"`
	// Secrets names environment variables whose values must not appear in
	// anything Probe prints or writes.
	Secrets []string `yaml:"secrets,omitempty"`
	// contains filtered or unexported fields
}

func (*Workflow) Env added in v0.3.0

func (w *Workflow) Env() map[string]string

func (*Workflow) RenderDagAscii added in v1.0.0

func (w *Workflow) RenderDagAscii() string

RenderDagAscii renders the workflow job dependencies as ASCII art with steps

func (*Workflow) RenderDagMermaid added in v1.0.0

func (w *Workflow) RenderDagMermaid() string

RenderDagMermaid returns the Mermaid format representation of workflow job dependencies

func (*Workflow) SetExitStatus added in v0.2.0

func (w *Workflow) SetExitStatus(isErr bool)

func (*Workflow) Start

func (w *Workflow) Start(c Config) error

Start executes the workflow with the given configuration

Directories

Path Synopsis
Package actions maps the action names usable in a step's `uses` to the built-in plugins that implement them.
Package actions maps the action names usable in a step's `uses` to the built-in plugins that implement them.
db
ssh
Package binary turns raw response payloads into either printable text or a file on disk, based on the declared MIME type.
Package binary turns raw response payloads into either printable text or a file on disk, based on the declared MIME type.
cmd
probe command
Package dag provides generic graph algorithms that work with any data structure.
Package dag provides generic graph algorithms that work with any data structure.
testserver command
testserver command
Package mapping converts between untyped action parameter maps and tagged Go structs.
Package mapping converts between untyped action parameter maps and tagged Go structs.

Jump to

Keyboard shortcuts

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