projectanalysis

package
v0.2.3 Latest Latest
Warning

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

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

Documentation

Overview

Package projectanalysis models immutable, tenant-scoped Project analysis snapshots.

Index

Constants

View Source
const ComplexityDeltaSchemaVersion = 1

ComplexityDeltaSchemaVersion is the wire schema version for complexity trends.

Variables

View Source
var (
	ErrCapabilityReason  = errors.New("source capability reason is invalid")
	ErrFileChangeStatus  = errors.New("file change status is invalid")
	ErrFileChangePaths   = errors.New("file change paths are invalid")
	ErrSourceNotRetained = errors.New("source artifact not retained")
	ErrSourceIntegrity   = errors.New("source artifact integrity mismatch")
	ErrSourceLimit       = errors.New("source artifact exceeds retained limit")
	ErrSourceUnsupported = errors.New("source artifact content is unsupported")
	ErrSourceTransient   = errors.New("source artifact temporarily unavailable")
)

Functions

func ChangedLineSet added in v0.2.0

func ChangedLineSet(changes []FileChange) map[string]map[int]bool

ChangedLineSet is the new-side changed lines of an analysis as file -> set of line numbers, the shape the new-code measurements consume. Only Added ranges count (Modified mirrors them; Removed lines no longer exist), a deleted or binary change contributes nothing, and paths are canonicalised so the set shares a key space with coverage and duplication data, which are canonicalised the same way.

The ranges are untrusted input. An invalid range, or a diff over maxChangedLines, yields nil: the new-code metrics then fail closed as unmeasured, which is the right answer for a diff that cannot be trusted to describe itself.

func IsShortLivedBranch added in v0.2.0

func IsShortLivedBranch(branch, defaultBranch string) bool

IsShortLivedBranch reports whether a branch is a transient feature/PR branch whose analyses are eligible for retention pruning.

Types

type Analysis

type Analysis struct {
	ID         string    `json:"id"`
	TenantID   string    `json:"tenant_id"`
	ProjectID  string    `json:"project_id"`
	ProjectKey string    `json:"project_key"`
	CreatedAt  time.Time `json:"created_at"`
	// Origin says whether the server produced this analysis or a pipeline pushed it. Absent on rows
	// written before the field existed, which the reader treats as OriginServer: every analysis
	// before the import route was a server analysis.
	Origin Origin `json:"origin,omitempty"`
	// CI is the pipeline's own account of the run, present only for OriginCI.
	CI                 *CIContext                        `json:"ci,omitempty"`
	SourceRef          string                            `json:"source_ref,omitempty"`
	SourceCommit       string                            `json:"source_commit,omitempty"`
	SourceRevision     SourceRevision                    `json:"source_revision,omitempty"`
	Capabilities       SourceCapabilities                `json:"capabilities,omitempty"`
	SourceManifest     SourceManifest                    `json:"source_manifest,omitempty"`
	Comparison         Comparison                        `json:"comparison,omitempty"`
	FileChanges        []FileChange                      `json:"file_changes,omitempty"`
	Annotations        []Annotation                      `json:"annotations,omitempty"`
	Measures           qualitygate.Snapshot              `json:"measures"`
	Gate               qualitygate.Result                `json:"gate"`
	GateInfo           GateInfo                          `json:"gate_info"`
	Issues             Counts                            `json:"issues"`
	InternalIssues     []Issue                           `json:"internal_issues"`
	NewCode            NewCode                           `json:"new_code"`
	Delta              *Delta                            `json:"delta"`
	Coverage           *measure.CoverageReport           `json:"coverage"`
	Duplication        measure.DuplicationReport         `json:"duplication"`
	Coupling           *measure.CouplingReport           `json:"coupling,omitempty"`
	BehavioralHotspots *measure.BehavioralHotspotsReport `json:"behavioral_hotspots,omitempty"`
	Rating             rating.Report                     `json:"rating"`
	Hotspots           hotspot.Summary                   `json:"hotspots"`
	NewHotspots        hotspot.Summary                   `json:"new_hotspots"`
	Snapshot           measure.Snapshot                  `json:"snapshot"`
}

Analysis is an append-only Project analysis snapshot. InternalIssues never crosses the HTTP boundary; it is only persisted to compute the next snapshot's identity set.

func Build

func Build(in Input) (Analysis, error)

Build returns one immutable snapshot and evaluates the built-in gate at creation.

func (Analysis) Branch added in v0.2.0

func (a Analysis) Branch() string

Branch is the normalized branch/tag this analysis was produced on. It falls back to the CI-reported branch, and is empty for a legacy analysis that recorded neither.

func (*Analysis) UnmarshalJSON

func (a *Analysis) UnmarshalJSON(data []byte) error

UnmarshalJSON handles legacy decoding where Snapshot might be empty or missing.

type Annotation added in v0.1.8

type Annotation struct {
	FindingKey string                 `json:"finding_key"`
	RuleKey    string                 `json:"rule_key,omitempty"`
	RuleName   string                 `json:"rule_name,omitempty"`
	RuleType   rule.Type              `json:"rule_type,omitempty"`
	Message    string                 `json:"message,omitempty"`
	Kind       finding.Kind           `json:"kind"`
	Severity   shared.Severity        `json:"severity"`
	Status     finding.Status         `json:"status"`
	Location   finding.SourceLocation `json:"location"`
	New        bool                   `json:"new"`
}

Annotation is an immutable, detection-time source marker. Current issue and hotspot triage is intentionally not copied here, so later reviews cannot rewrite historical analysis state.

func (Annotation) Validate added in v0.1.8

func (a Annotation) Validate() error

type BranchInfo added in v0.2.0

type BranchInfo struct {
	Name string     `json:"name"`
	Kind BranchKind `json:"kind"`
}

BranchInfo names a branch and its lifecycle classification, for the branches read model.

type BranchKind added in v0.2.0

type BranchKind string

BranchKind classifies a branch by lifecycle. A long-lived branch (main, develop, a release line, or the project's configured default) accumulates history that is kept indefinitely; a short-lived branch (a feature or pull-request branch) is transient and its analyses are eligible for retention pruning.

const (
	BranchLongLived  BranchKind = "long_lived"
	BranchShortLived BranchKind = "short_lived"
)

func ClassifyBranch added in v0.2.0

func ClassifyBranch(branch, defaultBranch string) BranchKind

ClassifyBranch returns the lifecycle kind of a branch. The project's configured default branch (SourceBinding.DefaultBranch) is always long-lived. A branch matching a well-known long-lived convention (main/master/develop, release/*, hotfix/*, support/*, ...) is long-lived. An empty or unrecognized branch is treated as long-lived so retention never prunes an analysis it cannot classify; only a branch positively recognized as short-lived becomes prune-eligible.

type CIContext added in v0.2.0

type CIContext struct {
	// Provider names the CI system, for example "github-actions", "gitlab-ci", "jenkins".
	Provider string `json:"provider,omitempty"`
	// RunURL links back to the pipeline run that produced the analysis.
	RunURL string `json:"run_url,omitempty"`
	// RunID is the provider's identifier for the run.
	RunID string `json:"run_id,omitempty"`
	// Branch is the branch or ref the pipeline built.
	Branch string `json:"branch,omitempty"`
	// Actor is who or what triggered the run, in the provider's own terms.
	Actor string `json:"actor,omitempty"`
	// PullRequest is the forge change identifier: GitHub/Bitbucket PR number or GitLab MR IID.
	PullRequest string `json:"pull_request,omitempty"`
	// TargetBranch is the base/destination branch of the pull/merge request.
	TargetBranch string `json:"target_branch,omitempty"`
	// RepoSlug is the forge repository identity, normally owner/name or namespace/project.
	RepoSlug string `json:"repo_slug,omitempty"`
	// HeadSHA is the forge-reported pull/merge-request head commit, not a synthetic merge commit.
	HeadSHA string `json:"head_sha,omitempty"`
}

CIContext is what a pipeline says about the run that produced an analysis. Every field is the pipeline's own claim, carried so the history page can name the branch, link the run and attribute the actor; none of it is verified by the server, and none of it participates in the gate.

func (CIContext) Empty added in v0.2.0

func (c CIContext) Empty() bool

Empty reports whether the pipeline said nothing about itself.

func (CIContext) Normalize added in v0.2.0

func (c CIContext) Normalize() (CIContext, error)

Normalize trims every field and rejects a context that could not have come from a pipeline: an over-long field, a run URL that is not an absolute http(s) URL, or control characters. It is deliberately lenient about what a valid branch, provider, or forge change id is, because those conventions belong to the provider, and strict about the shape a link must have before the dashboard renders it as one.

type Capability added in v0.1.8

type Capability struct {
	Available bool              `json:"available"`
	Reason    UnavailableReason `json:"reason,omitempty"`
}

Capability says whether one analysis-time Code feature can be served. An unavailable capability always carries a safe reason; available capabilities never carry one.

func (Capability) Validate added in v0.1.8

func (c Capability) Validate() error

type Comparison added in v0.1.8

type Comparison struct {
	Available          bool              `json:"available"`
	Reason             UnavailableReason `json:"reason,omitempty"`
	BaseRef            string            `json:"base_ref,omitempty"`
	BaseCommit         string            `json:"base_commit,omitempty"`
	MergeBase          string            `json:"merge_base,omitempty"`
	PreviousAnalysisID string            `json:"previous_analysis_id,omitempty"`
	BaseManifest       SourceManifest    `json:"base_manifest,omitempty"`
}

Comparison contains the immutable Git-derived facts needed for historical diff rendering. BaseManifest points to analysis-owned base-side artifacts.

func (Comparison) Validate added in v0.1.8

func (c Comparison) Validate() error

type ComplexityDelta added in v0.2.0

type ComplexityDelta struct {
	Version            int                            `json:"version"`
	BaselineAnalysisID string                         `json:"baseline_analysis_id,omitempty"`
	BaselineCreatedAt  time.Time                      `json:"baseline_created_at,omitempty"`
	BaselineSourceRef  string                         `json:"baseline_source_ref,omitempty"`
	Reason             string                         `json:"reason,omitempty"`
	Nodes              map[string]ComplexityNodeDelta `json:"nodes,omitempty"`
}

ComplexityDelta is immutable trend evidence tied to the exact baseline analysis used at record time.

type ComplexityNodeDelta added in v0.2.0

type ComplexityNodeDelta struct {
	Kind         measure.NodeKind     `json:"kind"`
	Cyclomatic   int                  `json:"cyclomatic"`
	Cognitive    int                  `json:"cognitive"`
	Availability measure.Availability `json:"availability"`
	Reason       string               `json:"reason,omitempty"`
}

ComplexityNodeDelta is a signed, path-scoped complexity change. A nil value is represented by AvailabilityUnavailable and a reason; zero is a measured delta and must remain distinguishable.

type Counts

type Counts struct {
	Total      int            `json:"total"`
	ByKind     map[string]int `json:"by_kind"`
	BySeverity map[string]int `json:"by_severity"`
	ByStatus   map[string]int `json:"by_status"`
}

Counts groups issues along the dimensions exposed by Activity.

type Delta

type Delta struct {
	Issues     Counts             `json:"issues"`
	Measures   map[string]float64 `json:"measures"`
	Ratings    map[string]int     `json:"ratings"`
	Complexity *ComplexityDelta   `json:"complexity,omitempty"`
}

Delta is a signed comparison with the immediately previous successful analysis.

type DiffHunk added in v0.1.8

type DiffHunk struct {
	OldStart int       `json:"old_start"`
	OldLines int       `json:"old_lines"`
	NewStart int       `json:"new_start"`
	NewLines int       `json:"new_lines"`
	Rows     []DiffRow `json:"rows"`
}

DiffHunk is an immutable, normalized section of one file change.

func (DiffHunk) Validate added in v0.1.8

func (h DiffHunk) Validate() error

type DiffRow added in v0.1.8

type DiffRow struct {
	Kind           DiffRowKind `json:"kind"`
	OldLine        int         `json:"old_line,omitempty"`
	NewLine        int         `json:"new_line,omitempty"`
	Text           string      `json:"text"`
	NoFinalNewline bool        `json:"no_final_newline,omitempty"`
}

DiffRow is one normalized unified row. A missing side is represented by zero, never a magic line-number sentinel.

func (DiffRow) Validate added in v0.1.8

func (r DiffRow) Validate() error

type DiffRowKind added in v0.1.8

type DiffRowKind string

DiffRowKind identifies one persisted unified-diff row. Rows retain both sides' line numbers so split rendering never needs to rerun Git.

const (
	DiffRowContext DiffRowKind = "context"
	DiffRowAdded   DiffRowKind = "added"
	DiffRowRemoved DiffRowKind = "removed"
)

func (DiffRowKind) Valid added in v0.1.8

func (k DiffRowKind) Valid() bool

type FileChange added in v0.1.8

type FileChange struct {
	Status   FileStatus  `json:"status"`
	OldPath  string      `json:"old_path,omitempty"`
	NewPath  string      `json:"new_path,omitempty"`
	Binary   bool        `json:"binary"`
	ModeOld  string      `json:"mode_old,omitempty"`
	ModeNew  string      `json:"mode_new,omitempty"`
	Added    []LineRange `json:"added,omitempty"`
	Removed  []LineRange `json:"removed,omitempty"`
	Modified []LineRange `json:"modified,omitempty"`
	Hunks    []DiffHunk  `json:"hunks,omitempty"`
}

FileChange contains persisted file-level comparison metadata. Hunk content and line mappings are added separately; the API never re-runs Git for historical analyses.

func (FileChange) Validate added in v0.1.8

func (c FileChange) Validate() error

type FileStatus added in v0.1.8

type FileStatus string

FileStatus is the complete persisted Git-style status used by source and diff views.

const (
	FileStatusAdded    FileStatus = "added"
	FileStatusModified FileStatus = "modified"
	FileStatusDeleted  FileStatus = "deleted"
	FileStatusRenamed  FileStatus = "renamed"
	FileStatusCopied   FileStatus = "copied"
	FileStatusModeOnly FileStatus = "mode_only"
)

func (FileStatus) String added in v0.1.8

func (s FileStatus) String() string

func (FileStatus) Valid added in v0.1.8

func (s FileStatus) Valid() bool

type GateInfo

type GateInfo struct {
	Key    string `json:"key,omitempty"`
	Name   string `json:"name"`
	Source string `json:"source"`
}

GateInfo records which policy produced the immutable evaluated result.

type Input

type Input struct {
	ID                       string
	TenantID                 shared.ID
	ProjectID                shared.ID
	ProjectKey               string
	CreatedAt                time.Time
	Origin                   Origin
	CI                       *CIContext
	SourceRef                string
	SourceCommit             string
	SourceRevision           SourceRevision
	Capabilities             SourceCapabilities
	SourceManifest           SourceManifest
	Comparison               Comparison
	FileChanges              []FileChange
	Annotations              []Annotation
	Findings                 []finding.Finding
	Gate                     qualitygate.Gate
	GateSource               string
	GateExempt               map[string]bool
	LinesOfCode              int
	Coverage                 *measure.CoverageReport
	Duplication              *measure.DuplicationReport // nil when no duplication walk ran, like Coverage
	Coupling                 *measure.CouplingReport
	BehavioralHotspots       *measure.BehavioralHotspotsReport
	AnalysisTruncated        bool
	Previous                 *Analysis
	ComplexityBaseline       *Analysis
	ComplexityBaselineReason string
	Hotspots                 hotspot.Summary
	NewHotspots              hotspot.Summary
	Snapshot                 measure.Snapshot
}

Input supplies one completed scan's project-facing facts. Findings must be the merged root and code-quality findings, not two independently counted lists.

type Issue

type Issue struct {
	Key      string          `json:"key"`
	Kind     finding.Kind    `json:"kind"`
	Severity shared.Severity `json:"severity"`
	Status   finding.Status  `json:"status"`
}

Issue is the compact, stable identity retained to derive the next New Code period.

type LineRange added in v0.1.8

type LineRange struct {
	Start int `json:"start"`
	End   int `json:"end"`
}

LineRange is a one-based inclusive range in one diff side.

func (LineRange) Valid added in v0.1.8

func (r LineRange) Valid() bool

type NewCode

type NewCode struct {
	PreviousID string        `json:"previous_id,omitempty"`
	Counts     Counts        `json:"counts"`
	Rating     NewCodeRating `json:"rating"`
}

NewCode retains the derived period state used by the default gate.

type NewCodeRating

type NewCodeRating struct {
	Security        rating.Grade  `json:"security"`
	Reliability     rating.Grade  `json:"reliability"`
	Maintainability *rating.Grade `json:"maintainability"`
}

NewCodeRating omits maintainability until Project scans retain changed-line LOC.

type Origin added in v0.2.0

type Origin string

Origin says which side produced an analysis: the server acquiring the source and scanning it itself, or a CI job that ran synapse-cli on its own checkout and pushed the result.

The distinction matters to a reader of the history page. A server analysis carries the source the server retained and a comparison it computed; a CI analysis carries whatever the pipeline chose to send, and its branch and commit are the pipeline's word rather than the server's. Both are real analyses with a real gate verdict, and the page must not pretend they are the same kind of thing.

const (
	// OriginServer is an analysis the server produced by acquiring and scanning the source itself.
	OriginServer Origin = "server"
	// OriginCI is an analysis a pipeline produced with synapse-cli and pushed through the import route.
	OriginCI Origin = "ci"
)

func (Origin) Valid added in v0.2.0

func (o Origin) Valid() bool

Valid reports whether o is a known origin.

type ScanKind added in v0.1.8

type ScanKind string

ScanKind identifies the acquisition mode that produced an analysis snapshot.

const (
	ScanKindGit     ScanKind = "git"
	ScanKindArchive ScanKind = "archive"
	ScanKindLocal   ScanKind = "local"
)

func (ScanKind) Valid added in v0.1.8

func (k ScanKind) Valid() bool

type SourceCapabilities added in v0.1.8

type SourceCapabilities struct {
	Source       Capability `json:"source"`
	Comparison   Capability `json:"comparison"`
	UnifiedDiff  Capability `json:"unified_diff"`
	SplitDiff    Capability `json:"split_diff"`
	Highlighting Capability `json:"highlighting"`
}

SourceCapabilities describes what a historical Code request may truthfully render.

func (SourceCapabilities) Validate added in v0.1.8

func (c SourceCapabilities) Validate() error

type SourceCapture added in v0.1.8

type SourceCapture struct {
	Capabilities SourceCapabilities `json:"capabilities"`
	Manifest     SourceManifest     `json:"manifest"`
}

SourceCapture is the pipeline result needed to publish an immutable source manifest. Capture errors are represented as unavailable capabilities rather than failing analysis.

type SourceFile added in v0.1.8

type SourceFile struct {
	Path      string            `json:"path"`
	Digest    string            `json:"digest,omitempty"`
	Bytes     int64             `json:"bytes"`
	Lines     int               `json:"lines"`
	Generated bool              `json:"generated"`
	Available bool              `json:"available"`
	Reason    UnavailableReason `json:"reason,omitempty"`
}

SourceFile records one captured head or base artifact without storing source bytes in the analysis payload. Digest addresses content in the owned artifact store.

func (SourceFile) Validate added in v0.1.8

func (f SourceFile) Validate() error

type SourceManifest added in v0.1.8

type SourceManifest struct {
	Files     []SourceFile  `json:"files"`
	Truncated bool          `json:"truncated,omitempty"`
	Writer    *SourceWriter `json:"writer,omitempty"`
	Digest    string        `json:"digest,omitempty"`
}

SourceManifest is the analysis-owned source capture inventory. It is immutable after publication and reconciled against measure.Snapshot.Nodes before persistence.

func (SourceManifest) ArtifactDigest added in v0.1.8

func (m SourceManifest) ArtifactDigest() string

ArtifactDigest returns a stable identity for the manifest's immutable inventory. Legacy manifests derive it on read because their serialized payload predates Digest.

func (*SourceManifest) SetArtifactDigest added in v0.1.8

func (m *SourceManifest) SetArtifactDigest()

type SourceRevision added in v0.1.8

type SourceRevision struct {
	Kind       ScanKind `json:"kind"`
	Head       string   `json:"head,omitempty"`
	Base       string   `json:"base,omitempty"`
	MergeBase  string   `json:"merge_base,omitempty"`
	AnalysisID string   `json:"analysis_id,omitempty"`
}

SourceRevision identifies the immutable head and, where available, comparison base.

type SourceWriter added in v0.1.8

type SourceWriter struct {
	Actor       string    `json:"actor"`
	ToolVersion string    `json:"tool_version"`
	PublishedAt time.Time `json:"published_at"`
}

SourceWriter is the authenticated provenance of a sanctioned source contribution. It lives inside manifest.json so the manifest digest seals who published it, with which client version, and when the server accepted the contribution.

func (SourceWriter) Validate added in v0.1.8

func (w SourceWriter) Validate() error

type UnavailableReason added in v0.1.8

type UnavailableReason string

UnavailableReason is a safe, stable explanation for an unavailable Code capability.

const (
	UnavailableNotRetained       UnavailableReason = "not_retained"
	UnavailableCaptureFailed     UnavailableReason = "capture_failed"
	UnavailableAlreadyRetained   UnavailableReason = "already_retained"
	UnavailableFirstAnalysis     UnavailableReason = "first_analysis"
	UnavailableNoComparableBase  UnavailableReason = "no_comparable_base"
	UnavailableUnsupportedTarget UnavailableReason = "unsupported_target"
	UnavailableLimitExceeded     UnavailableReason = "limit_exceeded"
	UnavailableBinary            UnavailableReason = "binary"
	UnavailableNonUTF8           UnavailableReason = "non_utf8"
)

func (UnavailableReason) Valid added in v0.1.8

func (r UnavailableReason) Valid() bool

Jump to

Keyboard shortcuts

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