repopolicy

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MPL-2.0 Imports: 31 Imported by: 0

Documentation

Overview

Package repopolicy enforces the repository's quality policy. It reads the central exception registry (.quality-exceptions.yml) and checks that .golangci.yml carries exactly the lint exceptions the registry lists; applies the registry's coverage and mutation scopes; rejects inline suppression directives in Go source; and verifies derived copies such as the third-party notices, the tool versions and the workflow action pins. The tools/qualitygate command exposes these checks to developers and CI.

Index

Constants

View Source
const (
	ToolLint     = "golangci-lint"
	ToolCoverage = "coverage"
	ToolMutation = "mutation"

	// EffectDisableLinter switches a whole linter off in .golangci.yml.
	EffectDisableLinter = "disable-linter"
	// EffectSettingItem adds items to a linter's ignore, disable or skip list.
	EffectSettingItem = "setting-item"
	// EffectExcludeDiagnostic adds one exclusion rule for one diagnostic in one file.
	EffectExcludeDiagnostic = "exclude-diagnostic"

	// KindDeprecatedRule marks a linter the tool itself has deprecated.
	KindDeprecatedRule = "deprecated-rule"
	// KindIncompatibleRule marks a rule that cannot be satisfied together with another enabled linter.
	KindIncompatibleRule = "incompatible-rule"
	// KindDuplicateRule marks a rule that another enabled linter already enforces.
	KindDuplicateRule = "duplicate-rule"
	// KindDesignIncompat marks a rule that contradicts a documented design decision.
	KindDesignIncompat = "design-incompatible"
	// KindIgnoredValue marks a value an ignore list accepts.
	KindIgnoredValue = "ignored-value"
	// KindFalsePositive marks a diagnostic that is wrong about the code.
	KindFalsePositive = "false-positive"
	// KindIntendedPattern marks a diagnostic about code that is deliberately written that way.
	KindIntendedPattern = "intended-pattern"
	// KindUnreachableBranch marks a statement no test can execute.
	KindUnreachableBranch = "unreachable-branch"
	// KindUnreachablePlat marks a statement that exists only for another operating system's run.
	KindUnreachablePlat = "unreachable-platform-branch"
	// KindGeneratedCode marks generated source.
	KindGeneratedCode = "generated-code"
	// KindEquivalentMutant marks a mutant that cannot change observable behavior.
	KindEquivalentMutant = "equivalent-mutant"
	// KindOutOfDomainMutant marks a mutant that only changes behavior outside the supported domain.
	KindOutOfDomainMutant = "out-of-domain-mutant"
)

Tool names as written in the registry's tool field.

View Source
const (
	ForeignSourceRecord = "third_party/pdf-sources.json"
)

ForeignSourceRecord is the sole source declaration used by ownership and dependency gates.

View Source
const GremlinsModule = "github.com/go-gremlins/gremlins"

GremlinsModule is the upstream source module of the reviewed mutation tool.

Variables

View Source
var (
	// ErrLintConfig reports a problem reading a golangci-lint document.
	ErrLintConfig = errors.New("golangci-lint data")
)
View Source
var ErrMutation = errors.New("mutation report")

ErrMutation reports an unreadable mutation report.

View Source
var ErrProfile = errors.New("coverage profile")

ErrProfile reports a malformed coverage profile or an unmergeable pair of profiles.

View Source
var (
	// ErrRegistry reports a malformed or invalid registry.
	ErrRegistry = errors.New("quality exception registry")
)
View Source
var (
	// ErrToolVersions reports a malformed tools/versions.env.
	ErrToolVersions = errors.New("tool versions")
)

Functions

func AnchoredPath

func AnchoredPath(file string) string

AnchoredPath returns the golangci-lint path pattern that matches exactly one repository file.

func ConfigWithoutRules

func ConfigWithoutRules(config []byte) ([]byte, error)

ConfigWithoutRules returns the configuration with its diagnostic exclusion rules removed, for the run that checks the rules still match something.

func ExclusionRulesYAML

func ExclusionRulesYAML(entries []*Entry) (string, error)

ExclusionRulesYAML renders the registry's diagnostic exclusions as the `rules:` list that .golangci.yml must carry under linters.exclusions, ready to paste.

func InfallibleMethodPremiseIssues

func InfallibleMethodPremiseIssues(entries []*Entry, read SourceReader) []string

InfallibleMethodPremiseIssues checks every registered errcheck method exception against the selected Go SDK source. The registry remains the exception authority; this small check recognizes only the concrete library contracts the project has independently reviewed.

func LintConfigIssues

func LintConfigIssues(entries []*Entry, config []byte) ([]string, error)

LintConfigIssues compares the exceptions effective in a .golangci.yml document with the registry's golangci-lint entries and returns one message per missing, extra or broader item, plus violations of the pinned strict settings. A nil result means the file and the registry agree exactly.

func MutationDiscoveryIssues

func MutationDiscoveryIssues(discovery, campaign *MutationReport, hostFiles map[string]bool) []string

MutationDiscoveryIssues compares the campaign with all positions discovered by a separate, all-operator dry run on the same snapshot. A fragment cannot certify a completed campaign.

func MutationDiscoveryPreflightIssues added in v0.2.0

func MutationDiscoveryPreflightIssues(discovery *MutationReport, hostFiles map[string]bool) []string

MutationDiscoveryPreflightIssues rejects incomplete or out-of-scope discovery before any mutant executes.

func MutationExecutionEvidenceIssues

func MutationExecutionEvidenceIssues(report *MutationReport, open func(string) (io.ReadCloser, error)) []string

MutationExecutionEvidenceIssues binds each judged outcome to complete captured stdout/stderr. The reviewed native executor judges behavior; this check proves artifact identity and integrity.

func MutationOperators

func MutationOperators() []string

MutationOperators lists every operator gremlins v0.6.0 offers; the gate enables all of them.

func NoticeIssues

func NoticeIssues(root, goroot string, modules []LinkedModule) ([]string, error)

NoticeIssues verifies THIRD_PARTY_NOTICES.md against the modules actually linked into the release binaries: one row per linked module and no others, the version in each row, the existence of each listed license copy, and that every license file the module ships is reproduced byte-for-byte (up to whitespace) by a copy listed in its row. goroot is the Go toolchain root, whose LICENSE the standard-library row must reproduce when the toolchain ships one.

func OwnedGoDirectories

func OwnedGoDirectories(ctx context.Context, root string) ([]string, error)

OwnedGoDirectories finds the source directories that lint/format must consider, including hidden and testdata fixture packages omitted by Go's ./... pattern. It shares the directive scan's owned filesystem boundary; compiler build-tag filtering remains Go's responsibility.

func OwnedGoSources

func OwnedGoSources(ctx context.Context, root string) ([]string, error)

OwnedGoSources returns all owned Go files, including platform variants and standalone fixtures.

func ParseLinterInfo

func ParseLinterInfo(data []byte) (map[string]LinterInfo, error)

ParseLinterInfo reads the output of `golangci-lint linters --json`.

func ParseToolVersions

func ParseToolVersions(content string) (map[string]string, error)

ParseToolVersions parses the KEY=VALUE lines of tools/versions.env; blank lines and # comments are ignored.

func PremiseIssues

func PremiseIssues(entries []*Entry, known map[string]LinterInfo) []string

PremiseIssues checks the premise each lint exception stands on, against the linters the binary knows: that a deprecated-rule linter is still deprecated, that every named linter exists, and that the linters an incompatible or duplicate rule yields to are themselves still enabled.

func ReconstructForeignModule added in v0.2.0

func ReconstructForeignModule(ctx context.Context, root string, source ForeignSource, destination string) error

ReconstructForeignModule stages a verified canonical module ZIP and exact patch into an empty owned directory. Supplemental test assets are separate.

func RepositoryIssues

func RepositoryIssues(entries []*Entry, read SourceReader) []string

RepositoryIssues checks, without running any tool, that every entry's path, function and anchor still exist in the source tree. An entry that points at code which has been renamed or removed fails here, before the slower gates would report it as stale.

func ScanSourceLimits added in v0.2.0

func ScanSourceLimits(ctx context.Context, root string) ([]string, error)

ScanSourceLimits checks physical file size and exported declarations in every owned Go source. Compiler selection and source display directives cannot hide tests, fixtures or platform variants.

func SourceClassificationIssues added in v0.2.0

func SourceClassificationIssues(owners map[string]string, files []string, compiled map[string]bool) []string

SourceClassificationIssues requires every owned file to compile for a supported variant and every non-test Go source to have one production or test-support owner. Tests retain their import policy.

func SourceLimitIssues added in v0.2.0

func SourceLimitIssues(name string, source []byte) ([]string, error)

SourceLimitIssues enforces the same thresholds protected in the native lint configuration. The native max-public-structs rule counts exported type declarations, including aliases.

func SourceOwners added in v0.2.0

func SourceOwners(config []byte, module string) (map[string]string, error)

SourceOwners derives exact production and test-support directory classifications from native depguard rules. Import matching remains depguard's responsibility; this only validates the declaration shape.

func ToolVersionIssues

func ToolVersionIssues(versions map[string]string, goreleaserConfig string) []string

ToolVersionIssues checks that tools/versions.env, the one source of tool versions, defines every tool and that the copies derived from it agree: the GoReleaser configuration's schema reference.

func VerifyGolangciBinaryMetadata added in v0.2.0

func VerifyGolangciBinaryMetadata(file string) error

VerifyGolangciBinaryMetadata rejects substituted commands and binaries for other native targets.

func VerifyGolangciPatch added in v0.2.0

func VerifyGolangciPatch(patch []byte, versions map[string]string) error

VerifyGolangciPatch binds the checked-in patch to the same pin used by the installed build.

func VerifyGolangciReportedIdentity added in v0.2.0

func VerifyGolangciReportedIdentity(data []byte, expected SourceBuildIdentity) error

VerifyGolangciReportedIdentity checks every source/patch identity field, not only the version label.

func VerifyGremlinsBinaryMetadata

func VerifyGremlinsBinaryMetadata(path string) error

VerifyGremlinsBinaryMetadata checks the concrete source-built command, independently of printed identity. Source builds have devel module metadata; that is not proof of an official tagged module binary.

func WorkflowIssues

func WorkflowIssues(files map[string][]byte) []string

WorkflowIssues checks the properties of GitHub workflow files that review would otherwise have to remember: third-party actions are pinned to a full commit with the release tag noted beside it, every workflow states its permissions, checkout does not persist credentials, the Go toolchain comes from go.mod, tool versions come from tools/versions.env rather than literals, and nothing runs with a pull request's secrets. files maps a path (a workflow or a composite action file) to its content; a file with a top-level runs key is a composite action and is checked step by step only.

Types

type Block

type Block struct {
	File      string
	StartLine int
	StartCol  int
	EndLine   int
	EndCol    int
	Stmts     int
	Count     int
}

Block is one statement block of a Go coverage profile.

type CoverageInput

type CoverageInput struct {
	// Profile is the merged unit and executable coverage.
	Profile *CoverageProfile
	// Read returns the repository's source files.
	Read SourceReader
	// Module is the module path that prefixes the profile's file names.
	Module string
	// GOOS is the operating system the profile was measured on.
	GOOS string
	// Entries are the registry entries to apply; entries of other tools are ignored.
	Entries []*Entry
	// Threshold is the minimum reachable coverage in percent.
	Threshold float64
}

CoverageInput is everything EvaluateCoverage judges.

type CoverageProfile

type CoverageProfile struct {
	Mode   string
	Blocks []Block
}

CoverageProfile is a merged text-format coverage profile.

func MergeProfiles

func MergeProfiles(profiles ...*CoverageProfile) (*CoverageProfile, error)

MergeProfiles sums execution counts of identical blocks across profiles that share one mode and one set of instrumented packages, as unit-test and executable-subprocess profiles do.

func ParseCoverageProfile

func ParseCoverageProfile(reader io.Reader) (*CoverageProfile, error)

ParseCoverageProfile reads a text-format coverage profile as written by `go test -coverprofile` or `go tool covdata textfmt`.

func (*CoverageProfile) Write

func (p *CoverageProfile) Write(writer io.Writer) error

Write renders the profile in text format.

type CoverageResult

type CoverageResult struct {
	// Packages lists the adjusted coverage of each package, ordered by name.
	Packages []PackageCoverage
	// Problems lists registry entries that no longer describe the profile and other gate failures.
	Problems []string
	// NotEvaluated lists entries skipped because they apply to another operating system.
	NotEvaluated []string
	// Raw is the coverage of every statement, before any exclusion.
	Raw PackageCoverage
	// Adjusted is the coverage of the reachable statements: the statements left after exclusions.
	Adjusted PackageCoverage
	// Excluded is the number of statements removed by registry entries.
	Excluded int
}

CoverageResult is the outcome of applying the registry to a merged profile.

func EvaluateCoverage

func EvaluateCoverage(input CoverageInput) CoverageResult

EvaluateCoverage applies the coverage entries to the profile and checks the threshold. An entry is stale, and reported as a problem, when it matches no block or when a block it excludes was in fact executed: an exception must describe code the tests cannot reach.

type DirectiveViolation

type DirectiveViolation struct {
	File    string
	Kind    string
	Comment string
	Line    int
}

DirectiveViolation is one prohibited suppression comment.

func DirectivesIn

func DirectivesIn(name string, content []byte) ([]DirectiveViolation, error)

DirectivesIn reports the prohibited directives in one Go source file.

func ScanDirectives

func ScanDirectives(ctx context.Context, root string) ([]DirectiveViolation, error)

ScanDirectives parses every Go file under root, hidden directories included, and reports each comment that is a tool-suppression directive. Parsing the comments, not the text, keeps string literals and prose out of the findings, and leaves //go:build, //go:embed, //go:generate, //line and SPDX notices alone. A file that does not parse is an error: it cannot be shown clean. Files are read through an os.Root, so a symbolic link cannot lead the scan outside root.

func (DirectiveViolation) String

func (v DirectiveViolation) String() string

String formats the violation for a test or gate message.

type Entry

type Entry struct {
	// Setting is the dotted .golangci.yml path of the list a setting-item entry extends.
	Setting string `yaml:"setting,omitempty"`
	// Operator is the mutation operator of a mutation entry, e.g. CONDITIONALS_BOUNDARY.
	Operator string `yaml:"operator,omitempty"`
	// Anchor is the exact trimmed source line at which an excluded block or mutant starts.
	Anchor string `yaml:"anchor,omitempty"`
	// Function names the function a coverage entry applies to: Name or Receiver.Name.
	Function string `yaml:"function,omitempty"`
	// GOOS restricts an entry to one operating system; empty applies everywhere.
	GOOS string `yaml:"goos,omitempty"`
	// Source is an optional regular expression matching the diagnosed source line.
	Source string `yaml:"source,omitempty"`
	// Message is a regular expression matching the diagnostic text of a diagnostic exclusion.
	Message string `yaml:"message,omitempty"`
	// Path is one repository file, as a slash-separated path.
	Path string `yaml:"path,omitempty"`
	// Linter names the linter an entry applies to.
	Linter string `yaml:"linter,omitempty"`
	// Effect is how a golangci-lint entry reaches .golangci.yml.
	Effect string `yaml:"effect,omitempty"`
	// RetainedProperty states what stays protected despite the exception.
	RetainedProperty string `yaml:"retained_property"`
	// Kind is the justification kind.
	Kind string `yaml:"kind"`
	// Tool is one of the Tool constants.
	Tool string `yaml:"tool"`
	// ID is the stable identifier.
	ID string `yaml:"id"`
	// Rationale is the YAML comment attached above the entry; it is not a YAML field.
	Rationale string `yaml:"-"`
	// Values are the exact items a setting-item entry adds.
	Values []string `yaml:"values,omitempty"`
	// ConflictsWith lists enabled linters that cannot be satisfied together with the excepted rule.
	ConflictsWith []string `yaml:"conflicts_with,omitempty"`
	// SupersededBy lists enabled linters that already enforce the excepted rule.
	SupersededBy []string `yaml:"superseded_by,omitempty"`
	// Column is the exact physical byte column of a mutation's operator token.
	Column *int `yaml:"column,omitempty"`
	// Statuses lists the judged mutation outcomes the entry accepts: lived or timed-out.
	Statuses []string `yaml:"statuses,omitempty"`
}

Entry is one registry exception. Which fields apply depends on Tool and Effect; Validate rejects entries with missing or surplus fields.

func StaleDiagnosticEntries

func StaleDiagnosticEntries(entries []*Entry, issues []Issue, hostGOOS string) []*Entry

StaleDiagnosticEntries returns the diagnostic exclusions that match no issue of an unexcluded lint run on hostGOOS. An entry restricted to another operating system is not judged here.

type ForeignSource added in v0.2.0

type ForeignSource struct {
	TestInputs     ForeignTestInputs `json:"test_inputs,omitzero"`
	Root           string            `json:"root"`
	Module         string            `json:"module"`
	Version        string            `json:"version"`
	Repository     string            `json:"repository"`
	Revision       string            `json:"revision"`
	SourceArtifact string            `json:"source_artifact"`
	SourceSHA256   string            `json:"source_sha256"`
	ModuleSum      string            `json:"module_sum"`
	GoModSum       string            `json:"go_mod_sum"`
	Patch          string            `json:"patch"`
	PatchSHA256    string            `json:"patch_sha256"`
	License        string            `json:"license"`
	Completeness   string            `json:"completeness"`
}

ForeignSource identifies one complete immutable module ZIP plus the reviewed local patch. Its identity is validated against reconstructed file bytes, separately from behavioral checks.

func ForeignSourcesContext added in v0.2.0

func ForeignSourcesContext(ctx context.Context, root string) ([]ForeignSource, error)

ForeignSourcesContext validates the three exact declared foreign roots before granting their ownership boundary, under the calling operation lifetime. Roots without either foreign tree or the record retain ordinary source discovery.

type ForeignTestInputs added in v0.2.0

type ForeignTestInputs struct {
	URL    string `json:"url"`
	SHA256 string `json:"sha256"`
}

ForeignTestInputs pins omitted upstream fixtures for isolated development tests; it does not change the canonical module ZIP source contract.

type Issue

type Issue struct {
	Linter string
	File   string
	Text   string
	Source string
	Line   int
}

Issue is one diagnostic from golangci-lint's JSON report.

func ParseIssues

func ParseIssues(data []byte, root string) ([]Issue, error)

ParseIssues reads golangci-lint JSON output, reporting file names relative to root with forward slashes.

type LinkedModule

type LinkedModule struct {
	Path    string
	Version string
	Dir     string
}

LinkedModule is a third-party module linked into a release binary.

func LinkedModules

func LinkedModules(ctx context.Context, root, ownModule string) ([]LinkedModule, error)

LinkedModules returns the third-party modules linked into ./cmd/pdfconcat for each release operating system, ordered by path.

type LinterInfo

type LinterInfo struct {
	Name       string `json:"name"`
	Deprecated bool   `json:"deprecated"`
}

LinterInfo is what the golangci-lint binary reports about one linter.

type Mutant

type Mutant struct {
	File               string
	Type               string
	Status             string
	DiscoveryStatus    string
	ExecutionReference string
	Line               int
	Column             int
}

Mutant is one mutation gremlins generated.

type MutationReport

type MutationReport struct {
	TerminationReason string
	Mutants           []Mutant
	Complete          bool
}

MutationReport is a parsed gremlins JSON report.

func ParseMutationReport

func ParseMutationReport(data []byte) (*MutationReport, error)

ParseMutationReport reads the JSON written by `gremlins unleash --output`.

type MutationResult

type MutationResult struct {
	// Counts maps each status to its number of mutants, including excluded and other-platform ones.
	Counts map[string]int
	// Problems lists the failures: survivors, timeouts, uncovered mutants, stale entries.
	Problems []string
	// Evaluated is the number of mutants judged: those in files compiled for the host platform.
	Evaluated int
	// OtherPlatform is the number of mutants in files not compiled for the host platform, which
	// only that platform's native run judges.
	OtherPlatform int
	// Accepted is the number of unfavourable mutants removed by registry entries.
	Accepted int
}

MutationResult is the outcome of judging a report against the registry.

func EvaluateMutation

func EvaluateMutation(report *MutationReport, entries []*Entry, hostFiles map[string]bool, read SourceReader) MutationResult

EvaluateMutation fails every mutant that was not killed and is not rejected as not viable, unless a registry entry accepts a judged outcome exactly, and fails every entry that accepts nothing. Final NOT COVERED outcomes are incomplete judgments and can never be excepted. Mutants in files outside hostFiles are not judged on this platform. read returns a repository file's content.

func (*MutationResult) SummaryLines

func (r *MutationResult) SummaryLines() []string

SummaryLines renders the status counts in a stable order for the gate's output.

type PackageCoverage

type PackageCoverage struct {
	Package string
	Total   int
	Covered int
}

PackageCoverage is the statement coverage of one package.

func (PackageCoverage) Percent

func (c PackageCoverage) Percent() float64

Percent returns covered statements as a percentage; an empty package counts as fully covered.

type Registry

type Registry struct {
	// Exceptions lists every exception to a quality gate.
	Exceptions []*Entry `yaml:"exceptions"`
	// CoverageThresholdPercent is the minimum reachable statement coverage.
	CoverageThresholdPercent float64 `yaml:"coverage_threshold_percent"`
	// Version is the registry format version.
	Version int `yaml:"version"`
}

Registry is the parsed .quality-exceptions.yml.

func LoadRegistry

func LoadRegistry(file string) (*Registry, error)

LoadRegistry reads, parses and validates the registry file.

func ParseRegistry

func ParseRegistry(content []byte) (*Registry, error)

ParseRegistry parses registry content, rejecting unknown fields, attaching each entry's rationale comment, and validating the result.

func (*Registry) For

func (r *Registry) For(tool string) []*Entry

For returns the entries of one tool, in registry order.

func (*Registry) Validate

func (r *Registry) Validate() error

Validate checks the structure of every entry and the uniqueness of identifiers and exact coverage scopes. It reports every problem it finds, not only the first.

type SourceBuildIdentity

type SourceBuildIdentity struct {
	Version string `json:"version"`
	Commit  string `json:"commit"`
	Date    string `json:"date"`
}

SourceBuildIdentity is the reproducible metadata and cache namespace of the reviewed source build. Date describes the upstream source tag, and Commit names the patch digest rather than a VCS commit.

func GolangciBuildIdentity

func GolangciBuildIdentity(versions map[string]string) (SourceBuildIdentity, error)

GolangciBuildIdentity derives metadata from the authoritative upstream and patch pins.

func GremlinsBuildIdentity

func GremlinsBuildIdentity(versions map[string]string) (SourceBuildIdentity, error)

GremlinsBuildIdentity identifies the reviewed executor source variant without inventing VCS metadata.

type SourceReader

type SourceReader func(file string) ([]byte, error)

SourceReader returns the content of a repository file given its slash-separated path.

Jump to

Keyboard shortcuts

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