package main import ( "bufio" "encoding/json" "fmt" "os" "path/filepath" "sort" "strconv" "strings" ) // Policy describes coverage threshold configuration. type Policy struct { MinimumStatementCoverage float64 `json:"minimum_statement_coverage"` CriticalPackages []PackagePolicy `json:"critical_packages"` } // PackagePolicy overrides defaults for a specific package. type PackagePolicy struct { Package string `json:"package"` MinimumStatementCoverage float64 `json:"minimum_statement_coverage"` Include bool `json:"include"` Exclusions []string `json:"exclusions"` } // Coverage aggregates covered and total statements for a package. type Coverage struct { Covered int64 Total int64 } // PackageResult is the policy-evaluated coverage result for one package. type PackageResult struct { Package string Covered int64 Total int64 Percent float64 Threshold float64 Pass bool } // LoadPolicy reads policy JSON from disk. func LoadPolicy(path string) (Policy, error) { f, err := openValidatedReadOnlyFile(path, ".json", "policy") if err != nil { return Policy{}, err } defer f.Close() var p Policy if err := json.NewDecoder(f).Decode(&p); err != nil { return Policy{}, fmt.Errorf("decode policy: %w", err) } if p.MinimumStatementCoverage <= 0 { p.MinimumStatementCoverage = 80.0 } return p, nil } // ParseCoverProfile parses a Go coverprofile and aggregates package coverage. func ParseCoverProfile(profilePath string, policy Policy) (map[string]Coverage, error) { f, err := openValidatedReadOnlyFile(profilePath, "", "coverage profile") if err != nil { return nil, err } defer f.Close() coverage := make(map[string]Coverage) s := bufio.NewScanner(f) lineNo := 0 for s.Scan() { lineNo++ line := strings.TrimSpace(s.Text()) if lineNo == 1 { if !strings.HasPrefix(line, "mode:") { return nil, fmt.Errorf("invalid coverage profile header") } continue } if line == "" { continue } parts := strings.Fields(line) if len(parts) != 3 { return nil, fmt.Errorf("invalid coverage line %d", lineNo) } fileAndRange := parts[0] numStmts, err := strconv.ParseInt(parts[1], 10, 64) if err != nil { return nil, fmt.Errorf("invalid statements count at line %d: %w", lineNo, err) } execCount, err := strconv.ParseInt(parts[2], 10, 64) if err != nil { return nil, fmt.Errorf("invalid execution count at line %d: %w", lineNo, err) } idx := strings.Index(fileAndRange, ":") if idx < 0 { return nil, fmt.Errorf("invalid file segment at line %d", lineNo) } filePath := fileAndRange[:idx] pkg := filepath.ToSlash(filepath.Dir(filePath)) if isExcludedFile(pkg, filePath, policy) { continue } agg := coverage[pkg] agg.Total += numStmts if execCount > 0 { agg.Covered += numStmts } coverage[pkg] = agg } if err := s.Err(); err != nil { return nil, fmt.Errorf("scan coverage profile: %w", err) } return coverage, nil } func openValidatedReadOnlyFile(path string, requiredExt string, label string) (*os.File, error) { cleaned := filepath.Clean(strings.TrimSpace(path)) if cleaned == "" || cleaned == "." { return nil, fmt.Errorf("invalid %s path", label) } if requiredExt != "" { ext := strings.ToLower(filepath.Ext(cleaned)) if ext != strings.ToLower(requiredExt) { return nil, fmt.Errorf("invalid %s file extension: got %q, want %q", label, ext, requiredExt) } } absPath, err := filepath.Abs(cleaned) if err != nil { return nil, fmt.Errorf("resolve %s path: %w", label, err) } info, err := os.Stat(absPath) if err != nil { return nil, fmt.Errorf("stat %s: %w", label, err) } if info.IsDir() { return nil, fmt.Errorf("%s path must be a file, got directory", label) } // #nosec G304 -- path is explicitly cleaned, normalized, and pre-validated as an existing file. f, err := os.Open(absPath) if err != nil { return nil, fmt.Errorf("open %s: %w", label, err) } return f, nil } // EvaluateCoverage evaluates package coverage against policy thresholds. func EvaluateCoverage(packages []string, byPackage map[string]Coverage, policy Policy) []PackageResult { results := make([]PackageResult, 0, len(packages)) for _, pkg := range packages { if !isPackageIncluded(pkg, policy) { continue } agg := byPackage[pkg] percent := 100.0 if agg.Total > 0 { percent = float64(agg.Covered) * 100.0 / float64(agg.Total) } threshold := thresholdForPackage(pkg, policy) pass := agg.Total == 0 || percent >= threshold results = append(results, PackageResult{ Package: pkg, Covered: agg.Covered, Total: agg.Total, Percent: percent, Threshold: threshold, Pass: pass, }) } sort.Slice(results, func(i, j int) bool { return results[i].Package < results[j].Package }) return results } func thresholdForPackage(pkg string, policy Policy) float64 { for _, entry := range policy.CriticalPackages { if entry.Package == pkg && entry.MinimumStatementCoverage > 0 { return entry.MinimumStatementCoverage } } if policy.MinimumStatementCoverage > 0 { return policy.MinimumStatementCoverage } return 80.0 } func isPackageIncluded(pkg string, policy Policy) bool { for _, entry := range policy.CriticalPackages { if entry.Package == pkg { return entry.Include } } return true } func isExcludedFile(pkg string, filePath string, policy Policy) bool { base := filepath.Base(filePath) // Exclude known generated artifacts and thin composition wiring. if strings.HasSuffix(base, "_gen.go") || base == "generated.go" || base == "models_gen.go" || base == "schema.resolvers.go" || base == "main.go" { return true } for _, entry := range policy.CriticalPackages { if entry.Package != pkg { continue } for _, ex := range entry.Exclusions { if ex == "" { continue } if strings.HasSuffix(filePath, ex) || strings.Contains(filePath, "/"+ex) { return true } } } return false }