run

package
v0.4.8 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package run orchestrates an extraction: temp-dir lifecycle, worker pool, per-(repo, connector) dispatch, manifest assembly, and provenance.

Index

Constants

This section is empty.

Variables

View Source
var ErrPartial = errors.New("run: one or more connectors or clones reported errors; see manifest")

ErrPartial signals a completed run that produced an artifact but where at least one connector or clone reported an error. The cmd-layer maps this to exit code 2 (artifact present, manifest records the failure); any other non-nil error from Run maps to exit code 3 (fatal).

Functions

func InterruptSummary

func InterruptSummary(in InterruptSummaryInput) string

InterruptSummary formats the stderr block printed on graceful Ctrl-C. Pure: caller is responsible for assembling the input. The exact wording is part of the CLI surface and is asserted in cmd/xray tests.

func NewLogger

func NewLogger(verbose, quiet bool, extra ...io.Writer) *slog.Logger

NewLogger configures slog for a run. verbose lowers the level to Debug (per-API-call timing), quiet raises it to Error. The default is Info. Logs always go to stderr; tokens are never emitted by any caller in this package and there is no logging code path that accepts tokens. An optional extra writer receives the same output (used for the run log file).

func NewLoggerNoStderr

func NewLoggerNoStderr(verbose, quiet bool, writers ...io.Writer) *slog.Logger

NewLoggerNoStderr configures slog without writing to stderr. Used by cmd/xray when the TTY status grid owns stdout and stderr lines would visibly leak into the rendered grid; the run log file (or any other passed writers) still captures everything.

func Summarize

func Summarize(in SummaryInput) string

Summarize renders the post-run summary block. Pure: no filesystem, no DB, no network. Caller is responsible for assembling the inputs.

Types

type InflightJob

type InflightJob struct {
	Repo      string
	Connector string
}

InflightJob is one (repo, connector) pair that was being extracted when ctx was canceled.

type InterruptSummaryInput

type InterruptSummaryInput struct {
	Phase    string        // "clone", "extract", "postprocess"
	Inflight []InflightJob // populated only for the "extract" phase
	TempDir  string        // absolute path; "" if no temp dir was created
	Cleaned  bool          // true when the temp dir was removed (false with --keep-clones)
	ExitCode int           // 130 for graceful SIGINT
}

InterruptSummaryInput collects what InterruptSummary needs to render the stderr message produced when ctx is canceled mid-run.

type Options

type Options struct {
	Out         string
	Workers     int
	KeepClones  bool
	Connectors  []connector.Connector
	Logger      *slog.Logger
	ToolVersion string
	// Progress is the sink for run-time phase events. Nil resolves to a
	// no-op; the CLI selects a TTY grid / line log / NDJSON / no-op sink
	// based on the --output mode resolved in cmd/xray/output.go.
	Progress progress.Sink
	// OnTempDir, if non-nil, is invoked exactly once with the absolute
	// path of the per-run temp directory immediately after creation. The
	// CLI uses it so the signal handler can name the leaked path in the
	// double-Ctrl-C force-exit log line.
	OnTempDir func(string)
}

Options configures a single run. Zero values pick spec-mandated defaults (4 workers, ./xray-export-<UTC>.tar.gz output, info-level stderr logger).

type PartialFailure

type PartialFailure struct {
	Repo      string
	Connector string
	Reason    string
}

PartialFailure identifies one (repo, connector) pair that errored during a partial run.

func ExtractPartialFailures

func ExtractPartialFailures(provs []connector.Provenance) []PartialFailure

ExtractPartialFailures walks the manifest's provenance for non-empty Errors maps and returns one PartialFailure per (repo, connector). The reason is the first (sorted) error message — enough for the summary, the full set lives in manifest.json.

type Result

type Result struct {
	ArtifactPath string
	SHA256       string
	Size         int64
	Duration     time.Duration
	Manifest     manifest.Manifest

	// RateLimitWaits and RateLimitWaitSeconds are the cumulative wait
	// count and total wait time across every connector's ratelimit
	// transport, drained from the progress.RateLimitCounter that the CLI
	// tees alongside the user-facing sink. Populated by the cmd layer
	// after Run returns (Run itself does not aggregate the counter).
	RateLimitWaits       int
	RateLimitWaitSeconds int

	// Interrupted is true iff Run returned because ctx was canceled.
	Interrupted      bool
	InterruptedPhase string        // "clone", "extract", "postprocess"
	InflightJobs     []InflightJob // populated only during "extract" cancel
	TempDir          string        // absolute path; non-empty whenever cleanup ran (or was skipped via KeepClones)
}

Result is everything the CLI needs after a successful (or partial) run to render the post-run summary block (issue #84). ArtifactPath is always set when Run returns either nil or ErrPartial; the other fields are derived from the same data the manifest records.

On graceful interrupt (Run returns context.Canceled), ArtifactPath is "" and the Interrupt* fields are populated so the cmd layer can render the stderr summary.

func Run

func Run(ctx context.Context, cfg *config.Config, opts Options) (Result, error)

Run is the entry point for `xray run`. It clones every repo, dispatches every (repo, connector) pair across the worker pool, assembles the manifest, packages the artifact, and removes the temp dir (unless opts.KeepClones is set).

Returns the absolute path of the produced .tar.gz. Errors are returned only when the run could not produce an artifact at all; per-connector failures are reported in the manifest's extraction_provenance and cause a non-nil error to be returned (so the CLI exits non-zero) while still completing artifact production.

type RunSummary

type RunSummary struct {
	Kind       string            `json:"kind"`
	OK         bool              `json:"ok"`
	DurationS  int               `json:"duration_s"`
	Artifact   SummaryArtifact   `json:"artifact"`
	Rows       map[string]any    `json:"rows"`
	Provenance SummaryProvenance `json:"provenance"`
	Partial    []PartialFailure  `json:"partial"`
}

RunSummary is the JSON-shape of the run-summary event emitted in --output json mode. The wire shape is documented in docs/spec.md and versioned independently of the artifact SchemaVersion.

func BuildRunSummary

func BuildRunSummary(in SummaryInput, ok bool) RunSummary

BuildRunSummary assembles the JSON-shape companion to the human summary. ok is false when the run was partial.

type SummaryArtifact

type SummaryArtifact struct {
	Path          string `json:"path"`
	SizeBytes     int64  `json:"size_bytes"`
	SHA256        string `json:"sha256"`
	SchemaVersion int    `json:"schema_version"`
	LogPath       string `json:"log_path,omitempty"`
}

SummaryArtifact mirrors the human-readable Artifact block.

type SummaryInput

type SummaryInput struct {
	Manifest             manifest.Manifest
	ArtifactPath         string
	SHA256               string
	Size                 int64
	Duration             time.Duration
	LogPath              string
	PartialFails         []PartialFailure
	RateLimitWaits       int
	RateLimitWaitSeconds int
}

SummaryInput is everything Summarize needs. It is a thin pass-through so the caller assembles the inputs once and the renderer stays pure.

type SummaryProvenance

type SummaryProvenance struct {
	EndpointsAccessible   int `json:"endpoints_accessible"`
	EndpointsTotal        int `json:"endpoints_total"`
	EndpointsInaccessible int `json:"endpoints_inaccessible"`
	PerRowErrors          int `json:"per_row_errors"`
	RateLimitTruncated    int `json:"rate_limit_truncated"`
	RateLimitWaits        int `json:"rate_limit_waits"`
	RateLimitWaitSeconds  int `json:"rate_limit_wait_seconds"`
	PartialPaginations    int `json:"partial_paginations"`
}

SummaryProvenance collapses the per-row provenance stream into the aggregate counters the customer sees. RateLimitTruncated counts connectors whose pagination was cut off by the rate-limit budget; RateLimitWaits + RateLimitWaitSeconds come from progress.RateLimitCounter (the CLI tees one alongside the user-facing sink) so the summary reports the actual cumulative wait the customer paid, not just the count of budget-truncated connectors.

Jump to

Keyboard shortcuts

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