model

package
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Jul 26, 2026 License: MIT Imports: 1 Imported by: 0

Documentation

Overview

Package model holds the domain types shared across shuck's packages: the GitHub data we collect, the failure detail we render, and the shape we persist to the cache. It imports nothing internal to avoid import cycles.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsCancelledConclusion added in v0.3.0

func IsCancelledConclusion(conclusion string) bool

IsCancelledConclusion reports whether a terminal conclusion is a cancellation. shuck surfaces cancelled jobs and drills their logs best-effort (to show what was interrupted), but cancellation alone never makes the exit code non-zero.

func IsDrillableConclusion added in v0.4.0

func IsDrillableConclusion(conclusion string) bool

IsDrillableConclusion reports whether a step's conclusion is worth pairing with the log's error sections: a genuine failure, or the cancellation marker GitHub puts on the step that was running when its job was cancelled.

func IsFailureConclusion

func IsFailureConclusion(conclusion string) bool

IsFailureConclusion reports whether a terminal conclusion counts as a CI failure worth drilling into or listing.

func SeverityRank added in v0.3.6

func SeverityRank(s SecuritySeverity) int

SeverityRank orders severities for sorting (higher is more severe). Unknown sorts last.

Types

type ActionTag added in v0.3.5

type ActionTag struct {
	Name string `json:"name"`
	SHA  string `json:"sha"`
}

ActionTag is a tag in a GitHub Actions repository paired with the commit SHA it resolves to. shuck uses it to pin a workflow `uses:` reference to an immutable SHA. The SHA is the peeled commit a checkout would land on, even for annotated tags.

type Annotation added in v0.4.1

type Annotation struct {
	Path        string `json:"path"`
	StartLine   int    `json:"start_line"`
	EndLine     int    `json:"end_line"`
	StartColumn int    `json:"start_column,omitempty"`
	EndColumn   int    `json:"end_column,omitempty"`
	Level       string `json:"level"` // notice | warning | failure
	Title       string `json:"title,omitempty"`
	Message     string `json:"message"`
}

Annotation is a GitHub check-run annotation: a structured file:line message attached to a job by a problem matcher (golangci-lint, go test, tsc, eslint, compilers, …). It points straight at the offending location, so shuck surfaces these alongside the scraped log excerpt.

type Artifact added in v0.4.2

type Artifact struct {
	ID        int64     `json:"id"`
	RunID     int64     `json:"run_id"`
	Name      string    `json:"name"`
	SizeBytes int64     `json:"size_bytes"`
	Expired   bool      `json:"expired"`
	CreatedAt time.Time `json:"created_at"`
	ExpiresAt time.Time `json:"expires_at"`
	Path      string    `json:"path,omitempty"`
}

Artifact is a file bundle a workflow run uploaded (actions/upload-artifact). shuck lists a run target's artifacts alongside its jobs; Path is set only when a download was requested, to the local directory the artifact's archive was extracted into.

type AuthorType added in v0.3.4

type AuthorType string

AuthorType classifies who wrote a review or comment, so the output can flag non-human reviewers.

const (
	AuthorHuman AuthorType = "human"
	AuthorBot   AuthorType = "bot"
	AuthorAI    AuthorType = "ai"
)

Author classifications.

type CodeScanningAlert added in v0.3.6

type CodeScanningAlert struct {
	Number      int              `json:"number"`
	State       string           `json:"state"`
	Severity    SecuritySeverity `json:"severity"`
	RuleID      string           `json:"rule_id"`
	Description string           `json:"description,omitempty"`
	Tool        string           `json:"tool,omitempty"`
	Path        string           `json:"path,omitempty"`
	StartLine   int              `json:"start_line,omitempty"`
	EndLine     int              `json:"end_line,omitempty"`
	Message     string           `json:"message,omitempty"`
	HTMLURL     string           `json:"html_url,omitempty"`
}

CodeScanningAlert is a single code scanning (e.g. CodeQL) finding.

type DependabotAlert added in v0.3.6

type DependabotAlert struct {
	Number             int              `json:"number"`
	State              string           `json:"state"`
	Severity           SecuritySeverity `json:"severity"`
	Ecosystem          string           `json:"ecosystem,omitempty"`
	Package            string           `json:"package,omitempty"`
	ManifestPath       string           `json:"manifest_path,omitempty"`
	VulnerableVersions string           `json:"vulnerable_version_range,omitempty"`
	FixedVersion       string           `json:"first_patched_version,omitempty"`
	GHSAID             string           `json:"ghsa_id,omitempty"`
	CVEID              string           `json:"cve_id,omitempty"`
	Summary            string           `json:"summary,omitempty"`
	HTMLURL            string           `json:"html_url,omitempty"`
}

DependabotAlert is a single vulnerable-dependency finding. GitHub's npm "malware" advisories surface here too; there is no separate malware endpoint.

type FailedStep

type FailedStep struct {
	Number  int          `json:"number"`
	Name    string       `json:"name"`
	Command string       `json:"command"`
	Kind    StepKind     `json:"kind"`
	Class   FailureClass `json:"class,omitempty"`
	Excerpt string       `json:"excerpt"`
}

FailedStep is the high-signal detail for a step that failed: what it ran and the extracted error excerpt from its logs.

type FailureClass added in v0.4.1

type FailureClass string

FailureClass is a coarse, heuristic category for why a step failed, so an agent or script can route a failure (fix code vs. re-run) without re-parsing the excerpt. It is a hint, never authoritative.

const (
	ClassUnknown FailureClass = ""
	ClassLint    FailureClass = "lint"    // linters / formatters / static analysis
	ClassTest    FailureClass = "test"    // a test suite reported failures
	ClassBuild   FailureClass = "build"   // compilation / build step
	ClassTimeout FailureClass = "timeout" // step or job timed out
	ClassOOM     FailureClass = "oom"     // killed for running out of memory
	ClassInfra   FailureClass = "infra"   // runner / network / registry trouble
)

Failure classes. The operational classes (timeout/oom/infra) signal a likely re-run; the rest point at code or config to fix. Empty means unclassified.

type JobResult

type JobResult struct {
	ID           int64          `json:"id"`
	RunID        int64          `json:"run_id"`
	Name         string         `json:"name"`
	Status       string         `json:"status"`
	Conclusion   string         `json:"conclusion"`
	RunAttempt   int            `json:"run_attempt"`
	WorkflowName string         `json:"workflow_name"`
	WorkflowPath string         `json:"workflow_path"`
	Steps        []StepOverview `json:"steps"`
	FailedSteps  []FailedStep   `json:"failed_steps"`
	// CheckRunID is the job's corresponding check-run ID, used to fetch the
	// job's annotations. 0 when it could not be resolved.
	CheckRunID int64 `json:"check_run_id,omitempty"`
	// Annotations are the job's check-run annotations (file:line messages from
	// problem matchers), fetched as cheap metadata when the job is drilled.
	Annotations []Annotation `json:"annotations,omitempty"`
	Inspected   bool         `json:"inspected"` // logs were drilled for this (id, attempt)
	// CompletedAt and RunStartedAt time the job against its run. The monitor
	// batches a run's failures until the run finishes, and the exception to
	// that is a job that failed early enough to be worth interrupting for; the
	// only way to tell is how far into the run it went red. Both are zero when
	// the API did not say, which reads as "not an early failure" — the
	// conservative direction, since it costs promptness rather than accuracy.
	CompletedAt  time.Time `json:"completed_at,omitzero"`
	RunStartedAt time.Time `json:"run_started_at,omitzero"`
}

JobResult is a single GitHub Actions job, including its step overview and (for failed jobs that were drilled) the per-step failure detail.

type OtherCheck

type OtherCheck struct {
	Name       string `json:"name"`
	Conclusion string `json:"conclusion"`
	URL        string `json:"url"`
}

OtherCheck is a non-Actions check (external app check run or legacy commit status). We list these by name/conclusion/url; no logs are available.

type PR

type PR struct {
	Owner      string    `json:"owner"`
	Repo       string    `json:"repo"`
	Number     int       `json:"number"`
	Title      string    `json:"title"`
	HeadSHA    string    `json:"head_sha"`
	HeadBranch string    `json:"head_branch"`
	UpdatedAt  time.Time `json:"updated_at"` // PR's last-updated time; feeds the cheap reviews-changed check

	// State, Draft, and Merged carry the PR's lifecycle. They exist for the
	// background monitor, which has to notice a PR being merged or closed to
	// stop watching it; the one-shot report paths ignore them.
	State  string `json:"state,omitempty"` // "open" or "closed"
	Draft  bool   `json:"draft,omitempty"`
	Merged bool   `json:"merged,omitempty"`
}

PR identifies a pull request and its head commit.

func (PR) Lifecycle added in v1.0.0

func (p PR) Lifecycle() string

Lifecycle collapses State, Draft, and Merged into the single word worth reporting: "merged" and "closed" are the two ways a PR ends, and a draft is open but not asking for review yet. It returns "" when the state was never populated.

type Report

type Report struct {
	PR         PR          `json:"pr"`
	Run        *RunInfo    `json:"run,omitempty"`
	FailedJobs []JobResult `json:"failed_jobs"`
	// CancelledJobs are jobs whose run was cancelled. Their logs are drilled
	// best-effort (a cancelled job's log shows what was running when it was
	// interrupted), but cancellation alone never flips the exit code.
	CancelledJobs []JobResult  `json:"cancelled_jobs"`
	RunningJobs   []RunningJob `json:"running_jobs"`
	OtherChecks   []OtherCheck `json:"other_checks"`
	// Artifacts are the file bundles attached to the inspected workflow run.
	// They are listed only for run/job targets (Run non-nil), where the run is
	// unambiguous.
	Artifacts []Artifact `json:"artifacts,omitempty"`
	Reviews   []Review   `json:"reviews,omitempty"`
	// ReviewsFingerprint is a cheap signature of the PR's review state, persisted
	// so a later run can skip the full review pull when nothing changed.
	ReviewsFingerprint string `json:"reviews_fingerprint,omitempty"`
	// ReviewsOnly is a presentation hint (not persisted): CI was not inspected,
	// so render shows only the reviews and omits the CI verdict.
	ReviewsOnly bool      `json:"-"`
	CheckedAt   time.Time `json:"checked_at"`
}

Report is the full inspection result for a target: what we render and (for PR targets) what we cache. Exactly one of PR / Run is meaningful: Run is non-nil for run/job URL targets, otherwise the report is PR-anchored.

func (*Report) HasFailures

func (r *Report) HasFailures() bool

HasFailures reports whether any failing checks were found.

func (*Report) IsTerminal

func (r *Report) IsTerminal() bool

IsTerminal reports whether every check has finished (no jobs still running).

type Review added in v0.3.4

type Review struct {
	Author      string         `json:"author"`
	AuthorType  AuthorType     `json:"author_type"`
	State       string         `json:"state"` // approved|changes_requested|commented|dismissed
	Body        string         `json:"body,omitempty"`
	SubmittedAt time.Time      `json:"submitted_at"`
	Threads     []ReviewThread `json:"threads,omitempty"`
}

Review is a submitted PR review: its author, verdict, top-level body, and the inline comment threads that originated in it.

type ReviewComment added in v0.3.4

type ReviewComment struct {
	Author     string     `json:"author"`
	AuthorType AuthorType `json:"author_type"`
	Body       string     `json:"body"`
}

ReviewComment is a single comment within a thread.

type ReviewThread added in v0.3.4

type ReviewThread struct {
	Path           string          `json:"path"`
	Line           int             `json:"line"`
	Resolved       bool            `json:"resolved"`
	Outdated       bool            `json:"outdated"`
	Collapsed      bool            `json:"collapsed"` // resolved || outdated
	CollapseReason string          `json:"collapse_reason,omitempty"`
	TotalComments  int             `json:"total_comments"`
	HiddenComments int             `json:"hidden_comments,omitempty"` // comments hidden by the per-thread limit
	Comments       []ReviewComment `json:"comments,omitempty"`        // empty when collapsed
}

ReviewThread is a conversation anchored to a code location. Resolved or outdated threads are collapsed: we report only why, not their contents.

type RunInfo added in v0.3.0

type RunInfo struct {
	Owner        string `json:"owner"`
	Repo         string `json:"repo"`
	RunID        int64  `json:"run_id"`
	JobID        int64  `json:"job_id,omitempty"`  // 0 when the whole run was targeted
	Attempt      int    `json:"attempt,omitempty"` // 0 when the latest attempt was used
	Title        string `json:"title"`
	HeadSHA      string `json:"head_sha"`
	HeadBranch   string `json:"head_branch"`
	WorkflowName string `json:"workflow_name"`
}

RunInfo identifies a workflow-run inspection: shuck was pointed at a run URL (the whole run) or a single-job URL rather than a PR. When a Report's Run is non-nil, render and jsonout show a run-oriented header in place of the PR line and there is no associated PR number.

type RunningJob

type RunningJob struct {
	Name         string    `json:"name"`
	Status       string    `json:"status"`
	WorkflowName string    `json:"workflow_name"`
	RunID        int64     `json:"run_id,omitempty"`
	RunAttempt   int       `json:"run_attempt,omitempty"`
	RunStartedAt time.Time `json:"run_started_at,omitzero"`
}

RunningJob is a job not yet in a terminal state.

RunID and RunAttempt are what let the monitor ask "is this run finished?" rather than only "is anything finished?": a run's failures are held until none of its own jobs are still going, so a slow unrelated workflow cannot sit on them.

type SecretLocation added in v0.3.6

type SecretLocation struct {
	Path      string `json:"path,omitempty"`
	StartLine int    `json:"start_line,omitempty"`
	EndLine   int    `json:"end_line,omitempty"`
}

SecretLocation is one place a leaked secret was found. Only file locations are surfaced (commit/PR-comment locations are skipped).

type SecretScanningAlert added in v0.3.6

type SecretScanningAlert struct {
	Number      int              `json:"number"`
	State       string           `json:"state"`
	SecretType  string           `json:"secret_type"`
	DisplayName string           `json:"secret_type_display_name,omitempty"`
	Resolution  string           `json:"resolution,omitempty"`
	Locations   []SecretLocation `json:"locations,omitempty"`
	HTMLURL     string           `json:"html_url,omitempty"`
}

SecretScanningAlert is a single secret scanning finding. It deliberately has no field for the raw secret value: shuck never reads it from the API, so the secret cannot leak into output, JSON, or the cache.

type SecurityReport added in v0.3.6

type SecurityReport struct {
	Owner string `json:"owner"`
	Repo  string `json:"repo"`
	State string `json:"state"` // the requested state filter (open|all|...)

	CodeScanning   SecuritySource `json:"code_scanning"`
	SecretScanning SecuritySource `json:"secret_scanning"`
	Dependabot     SecuritySource `json:"dependabot"`

	CodeScanningAlerts   []CodeScanningAlert   `json:"code_scanning_alerts"`
	SecretScanningAlerts []SecretScanningAlert `json:"secret_scanning_alerts"`
	DependabotAlerts     []DependabotAlert     `json:"dependabot_alerts"`

	CheckedAt time.Time `json:"checked_at"`
}

SecurityReport is the assembled security posture for one repository: the per-source fetch outcome plus the alerts each returned.

func (*SecurityReport) TotalAlerts added in v0.3.6

func (r *SecurityReport) TotalAlerts() int

TotalAlerts reports how many alerts were collected across all sources.

type SecuritySeverity added in v0.3.6

type SecuritySeverity string

SecuritySeverity is the normalized severity scale shuck sorts security alerts on. Code scanning's note/warning/error and the GHAS critical/high/medium/low levels are both mapped onto it so every source ranks consistently.

const (
	SeverityCritical SecuritySeverity = "critical"
	SeverityHigh     SecuritySeverity = "high"
	SeverityMedium   SecuritySeverity = "medium"
	SeverityLow      SecuritySeverity = "low"
	SeverityWarning  SecuritySeverity = "warning"
	SeverityNote     SecuritySeverity = "note"
	SeverityUnknown  SecuritySeverity = "unknown"
)

Normalized severities, highest first.

type SecuritySource added in v0.3.6

type SecuritySource struct {
	Status  SourceStatus `json:"status"`
	Message string       `json:"message,omitempty"`
}

SecuritySource records how a single source responded.

type SourceStatus added in v0.3.6

type SourceStatus string

SourceStatus is the outcome of querying one security-alert source, so the output can distinguish "enabled and clean" from "not enabled" or "no access".

const (
	StatusOK        SourceStatus = "ok"        // queried successfully (alerts may be empty)
	StatusDisabled  SourceStatus = "disabled"  // feature not enabled, or state N/A for this source
	StatusForbidden SourceStatus = "forbidden" // token lacks the required access
	StatusError     SourceStatus = "error"     // a genuine error reaching the source
)

Per-source fetch outcomes.

type StepKind

type StepKind string

StepKind classifies how a step ran, derived from its log group header.

const (
	KindAction  StepKind = "action" // uses: owner/action@ref
	KindBash    StepKind = "bash"   // run: shell command
	KindUnknown StepKind = ""
)

Step command kinds, derived from a step's log group header.

type StepOverview

type StepOverview struct {
	Number     int    `json:"number"`
	Name       string `json:"name"`
	Status     string `json:"status"`
	Conclusion string `json:"conclusion"`
}

StepOverview is one entry in a job's authoritative ordered step list.

Jump to

Keyboard shortcuts

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