pipeline

package
v3.89.1 Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2026 License: AGPL-3.0 Imports: 12 Imported by: 0

Documentation

Overview

Package pipeline is the owner of "run an analysis".

Both the CLI's scan family and the language server reach analysis through this package, which is what AGENTS.md means by "every capability has exactly one owner, reached through one options-struct entry function". Before this package existed, the analysis lived in cmd/runLocalScan: 1,600 lines, 40 positional parameters, and hard-wired to a terminal.

Reporter is the seam that made the extraction possible. The analysis emits progress and diagnostics through this interface instead of writing to a terminal, so the same code path can drive a spinner on stderr, an LSP $/progress token, or nothing at all in a test.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Level

type Level int

Level classifies a Reporter log line. It maps onto LSP MessageType (1=Error, 2=Warning, 3=Info) without translation.

const (
	LevelInfo Level = iota
	LevelWarn
	LevelError
)

func (Level) String

func (l Level) String() string

type LicensePolicy

type LicensePolicy struct {
	// Mode is "inclusive" or "individual".
	Mode string
	// AllowCSV is a comma-separated SPDX allowlist.
	AllowCSV string
	// AllowFile is a path to a newline-separated SPDX allowlist.
	AllowFile string
}

LicensePolicy is the licence policy as the scan-family flags express it, handed to the licence owner (runLicensePipeline) when that stage runs.

type Options

type Options struct {

	// Files are the manifests and SBOMs already detected under RootPath. The
	// caller runs detection so it can report and filter before committing to a
	// scan.
	Files []scan.DetectedFile

	// RootPath is the absolute directory being analysed.
	RootPath string

	// Depth bounds directory recursion during manifest detection (--depth).
	Depth int

	// Excludes are glob patterns removed from the walk (--exclude).
	Excludes []string

	NoSCA        bool
	NoSASTRules  bool
	NoSecrets    bool
	NoContainers bool
	NoIAC        bool
	NoLicenses   bool

	// NoExploits and NoRemediation drop the corresponding VDB enrichment
	// passes; the SCA lookup itself still runs.
	NoExploits    bool
	NoRemediation bool

	// SeverityThreshold is validated against scan.ValidSeverityThresholds.
	SeverityThreshold string
	// ExploitThreshold is validated against scan.ValidExploitThresholds.
	ExploitThreshold string
	BlockMalware     bool
	BlockEOL         bool
	BlockUnpinned    bool
	VersionLag       int
	CooldownDays     int

	// DisableDefaultRules drops the embedded corpus, leaving only RuleRefs.
	DisableDefaultRules bool
	// RuleRefs are external rule packs, cloned from RuleRegistry.
	RuleRefs []sast.RuleRef
	// RuleRegistry defaults to sast.DefaultRegistry when empty.
	RuleRegistry string
	// RuleID restricts the run to a single VNX-NNNN rule.
	RuleID string
	// LockedKinds restricts the run to these rule kinds, embedded and external
	// alike. Nil means "no lock", which is the generic scan command's
	// behaviour. The language server sets this per trigger: the keystroke path
	// runs sast/iac/oci only, because the 1,092 secrets rules cost roughly 20x
	// what every other kind costs combined.
	LockedKinds []string
	// SnippetContext shapes SARIF snippets: -1 picks a width from the finding
	// span, 0 disables snippets.
	SnippetContext int

	IgnoreGlobs          []string
	IgnoreGit            bool
	IgnoreBinaries       bool
	GitHistory           bool
	GitHistoryMaxCommits int
	GitHistoryMaxFiles   int
	// RespectGitignore prunes files matched by .gitignore.
	RespectGitignore bool

	SCAAutofix     bool
	SCAAutofixOpts fix.Options
	// AutofixResolved carries findings a previous autofix pass fixed, so the
	// confirmation re-scan can mark them resolved rather than re-reporting.
	AutofixResolved []*triage.TriageFinding

	License LicensePolicy

	GitCtx  *gitctx.GitContext
	SysInfo *gitctx.SystemInfo
	// SeedBOM and VulnetixSeedBOM carry components from an existing SBOM into
	// the produced document, so a scan never loses what a previous one found.
	SeedBOM         *cdx.BOM
	VulnetixSeedBOM *cdx.BOM

	// ShowPaths includes the dependency chain that introduced each package.
	ShowPaths bool
	// ResultsOnly suppresses all output when the run is clean.
	ResultsOnly bool
	// DryRun performs detection, parsing and memory reads with zero API calls.
	DryRun bool
	// NoProgress suppresses the live progress row. Kept here because it also
	// reaches callees that build their own display contexts.
	NoProgress bool
}

Options is everything an analysis run needs, as named fields.

This replaces the 40 positional parameters cmd/runLocalScan used to take, a signature where `true, noSCA, true, true, true` was a real call site and adding a parameter meant touching every caller. More importantly it is the entry point AGENTS.md asks for: one options struct that both the scan subcommands and the language server fill in, so neither owns a private version of "what a scan is".

Deliberately absent: anything about presentation. Where results are written, how they are rendered, and whether there is a terminal at all are the caller's business. Progress and log output go through Reporter.

type Reporter

type Reporter interface {
	// Stage changes the current stage label without changing numeric progress.
	Stage(stage string)

	// Update sets numeric progress out of the total declared at construction,
	// and, when stage is non-empty, the stage label with it.
	Update(done int, stage string)

	// Logf writes one diagnostic line. Callers must not append a newline.
	Logf(level Level, format string, args ...any)

	// Degraded records that part of the analysis did not run to completion:
	// files skipped over the size cap, git history unavailable, a stage that
	// failed without failing the run. These are collected and surfaced, because
	// "no findings" and "did not look" must not be indistinguishable.
	Degraded(note string)

	// Degradations returns everything passed to Degraded, in order.
	Degradations() []string

	// Complete and Fail finalise the run exactly once. Subsequent calls are
	// ignored, so a deferred Complete after an early Fail is harmless.
	Complete(stage string)
	Fail(stage string)

	// Writer is the transitional escape hatch for callees that still take an
	// io.Writer directly (sast.LoadAllModules, autofix.RunInstall,
	// postScanSARIF). Everything written to it is ordinary log output. New code
	// should use Logf; this exists so the extraction could land without also
	// rewriting every callee's signature in the same change.
	Writer() io.Writer
}

Reporter receives progress, log output and degradation notices from an analysis run.

Implementations must be safe for concurrent use: the scan stages fan out across goroutines, and the language server evaluates shards in parallel.

A nil Reporter is not valid; use Discard() when output is not wanted.

func Discard

func Discard() Reporter

Discard returns a Reporter that produces no output. Use it for --silent runs and in tests that do not assert on progress.

type TerminalReporter

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

TerminalReporter drives the existing display.Progress activity: one live line on stderr, with log output routed through Progress.Writer so a log line clears and redraws the progress row instead of leaving duplicates behind.

This is the reporter the CLI uses, and it reproduces exactly what cmd/runLocalScan did inline before the extraction. The language server installs a different implementation that turns the same calls into $/progress notifications.

func NewTerminalReporter

func NewTerminalReporter(title string, total int, silent, noProgress bool) *TerminalReporter

NewTerminalReporter starts a progress activity titled `title` with `total` numbered steps, rendering to stderr.

The arguments mirror the CLI's own flags: silent suppresses everything, noProgress keeps log output but drops the live line. Both are honoured by display.Progress itself, so a disabled progress activity is a safe no-op rather than a nil that every call site has to check.

func NewTerminalReporterFrom

func NewTerminalReporterFrom(progress *display.Progress) *TerminalReporter

NewTerminalReporterFrom wraps an already-started progress activity. Use it when the caller owns the display context, for instance because it renders results through the same context after the analysis finishes.

func (*TerminalReporter) Complete

func (r *TerminalReporter) Complete(stage string)

func (*TerminalReporter) Degradations

func (r *TerminalReporter) Degradations() []string

func (*TerminalReporter) Degraded

func (r *TerminalReporter) Degraded(note string)

func (*TerminalReporter) Fail

func (r *TerminalReporter) Fail(stage string)

func (*TerminalReporter) Logf

func (r *TerminalReporter) Logf(level Level, format string, args ...any)

func (*TerminalReporter) Progress

func (r *TerminalReporter) Progress() *display.Progress

Progress exposes the underlying activity for the few call sites that still need it directly. Kept narrow on purpose: everything reachable through Reporter should go through Reporter.

func (*TerminalReporter) Stage

func (r *TerminalReporter) Stage(stage string)

func (*TerminalReporter) Update

func (r *TerminalReporter) Update(done int, stage string)

func (*TerminalReporter) Writer

func (r *TerminalReporter) Writer() io.Writer

type WriterReporter

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

WriterReporter writes plain lines to w and keeps a degradation ledger. It is the implementation used by tests that want to assert on output, and by any caller that has a writer but no terminal.

func NewWriterReporter

func NewWriterReporter(w io.Writer) *WriterReporter

NewWriterReporter returns a Reporter writing to w. A nil w discards.

func (*WriterReporter) Complete

func (r *WriterReporter) Complete(stage string)

func (*WriterReporter) Degradations

func (r *WriterReporter) Degradations() []string

func (*WriterReporter) Degraded

func (r *WriterReporter) Degraded(note string)

func (*WriterReporter) Fail

func (r *WriterReporter) Fail(stage string)

func (*WriterReporter) Logf

func (r *WriterReporter) Logf(level Level, format string, args ...any)

func (*WriterReporter) Stage

func (r *WriterReporter) Stage(stage string)

func (*WriterReporter) Update

func (r *WriterReporter) Update(_ int, stage string)

func (*WriterReporter) Writer

func (r *WriterReporter) Writer() io.Writer

Jump to

Keyboard shortcuts

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