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
- Variables
- func AnchoredPath(file string) string
- func ConfigWithoutRules(config []byte) ([]byte, error)
- func ExclusionRulesYAML(entries []*Entry) (string, error)
- func InfallibleMethodPremiseIssues(entries []*Entry, read SourceReader) []string
- func LintConfigIssues(entries []*Entry, config []byte) ([]string, error)
- func MutationDiscoveryIssues(discovery, campaign *MutationReport, hostFiles map[string]bool) []string
- func MutationDiscoveryPreflightIssues(discovery *MutationReport, hostFiles map[string]bool) []string
- func MutationExecutionEvidenceIssues(report *MutationReport, open func(string) (io.ReadCloser, error)) []string
- func MutationOperators() []string
- func NoticeIssues(root, goroot string, modules []LinkedModule) ([]string, error)
- func OwnedGoDirectories(ctx context.Context, root string) ([]string, error)
- func OwnedGoSources(ctx context.Context, root string) ([]string, error)
- func ParseLinterInfo(data []byte) (map[string]LinterInfo, error)
- func ParseToolVersions(content string) (map[string]string, error)
- func PremiseIssues(entries []*Entry, known map[string]LinterInfo) []string
- func ReconstructForeignModule(ctx context.Context, root string, source ForeignSource, destination string) error
- func RepositoryIssues(entries []*Entry, read SourceReader) []string
- func ScanSourceLimits(ctx context.Context, root string) ([]string, error)
- func SourceClassificationIssues(owners map[string]string, files []string, compiled map[string]bool) []string
- func SourceLimitIssues(name string, source []byte) ([]string, error)
- func SourceOwners(config []byte, module string) (map[string]string, error)
- func ToolVersionIssues(versions map[string]string, goreleaserConfig string) []string
- func VerifyGolangciBinaryMetadata(file string) error
- func VerifyGolangciPatch(patch []byte, versions map[string]string) error
- func VerifyGolangciReportedIdentity(data []byte, expected SourceBuildIdentity) error
- func VerifyGremlinsBinaryMetadata(path string) error
- func WorkflowIssues(files map[string][]byte) []string
- type Block
- type CoverageInput
- type CoverageProfile
- type CoverageResult
- type DirectiveViolation
- type Entry
- type ForeignSource
- type ForeignTestInputs
- type Issue
- type LinkedModule
- type LinterInfo
- type Mutant
- type MutationReport
- type MutationResult
- type PackageCoverage
- type Registry
- type SourceBuildIdentity
- type SourceReader
Constants ¶
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.
const (
ForeignSourceRecord = "third_party/pdf-sources.json"
)
ForeignSourceRecord is the sole source declaration used by ownership and dependency gates.
const GremlinsModule = "github.com/go-gremlins/gremlins"
GremlinsModule is the upstream source module of the reviewed mutation tool.
Variables ¶
var ( // ErrLintConfig reports a problem reading a golangci-lint document. ErrLintConfig = errors.New("golangci-lint data") )
var ErrMutation = errors.New("mutation report")
ErrMutation reports an unreadable mutation report.
var ErrProfile = errors.New("coverage profile")
ErrProfile reports a malformed coverage profile or an unmergeable pair of profiles.
var ( // ErrRegistry reports a malformed or invalid registry. ErrRegistry = errors.New("quality exception registry") )
var ( // ErrToolVersions reports a malformed tools/versions.env. ErrToolVersions = errors.New("tool versions") )
Functions ¶
func AnchoredPath ¶
AnchoredPath returns the golangci-lint path pattern that matches exactly one repository file.
func ConfigWithoutRules ¶
ConfigWithoutRules returns the configuration with its diagnostic exclusion rules removed, for the run that checks the rules still match something.
func ExclusionRulesYAML ¶
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 ¶
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 ¶
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 ¶
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 ¶
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
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
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
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 ¶
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
VerifyGolangciBinaryMetadata rejects substituted commands and binaries for other native targets.
func VerifyGolangciPatch ¶ added in v0.2.0
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 ¶
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 ¶
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 ¶
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`.
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 ¶
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 ¶
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
ForeignTestInputs pins omitted upstream fixtures for isolated development tests; it does not change the canonical module ZIP source contract.
type LinkedModule ¶
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 ¶
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 ¶
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 ¶
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 ¶
LoadRegistry reads, parses and validates the registry file.
func ParseRegistry ¶
ParseRegistry parses registry content, rejecting unknown fields, attaching each entry's rationale comment, and validating the result.
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 ¶
SourceReader returns the content of a repository file given its slash-separated path.