From 7d13f347fea8f85ac4841aed2aa6f686c3dc01ef Mon Sep 17 00:00:00 2001 From: Vishal Vaibhav Date: Sun, 24 May 2026 10:38:24 +0530 Subject: [PATCH 1/2] feat: new comment format --- internal/plugin/reporter/github_pr.go | 170 ++++++++++++++++++++----- internal/plugin/reporter/utils.go | 8 +- internal/plugin/runner_test.go | 177 +------------------------- 3 files changed, 150 insertions(+), 205 deletions(-) diff --git a/internal/plugin/reporter/github_pr.go b/internal/plugin/reporter/github_pr.go index ba4a37d..8c917db 100644 --- a/internal/plugin/reporter/github_pr.go +++ b/internal/plugin/reporter/github_pr.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "io" + "sort" "strings" "github.com/pkg/errors" @@ -89,44 +90,46 @@ func (s *GithubPullRequest) createCommentBody(changedLinesWithCoverage domain.So modules := collectModules(changedLinesWithCoverage) - bodyLines := []string{ - "## šŸ“Š Code Coverage — Changed Lines\n", - "\n", - "> Coverage is measured **only for the lines this PR changes**, not the whole file or repo.\n", - "\n", - } + covered := changedLinesWithCoverage.TotalCoveredInstructions() + missed := changedLinesWithCoverage.TotalMissedInstructions() + linesWithData := changedLinesWithCoverage.TotalLinesWithData() + linesWithoutData := changedLinesWithCoverage.TotalLinesWithoutData() + + totalInstructions := covered + missed + totalLines := linesWithData + linesWithoutData + + coveredPct := toPercent(safeDiv(float32(covered), float32(totalInstructions), 1)) + missedPct := toPercent(safeDiv(float32(missed), float32(totalInstructions), 0)) + withDataPct := toPercent(safeDiv(float32(linesWithData), float32(totalLines), 1)) + withoutDataPct := toPercent(safeDiv(float32(linesWithoutData), float32(totalLines), 0)) + + var b strings.Builder + + b.WriteString("## šŸ›”ļø Patch Coverage Report\n\n") + b.WriteString("> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. ") + b.WriteString("There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n") if len(modules) > 0 { - bodyLines = append(bodyLines, fmt.Sprintf("*Modules: %v*\n\n", strings.Join(modules, ", "))) - } - - bodyLines = append(bodyLines, generateSummaryLines(changedLinesWithCoverage, func(linesWithDataCount int, linesWithoutDataCount int, covered int, missed int) []string { - totalLines := linesWithDataCount + linesWithoutDataCount - totalInstructions := covered + missed - - coveredPct := toPercent(safeDiv(float32(covered), float32(totalInstructions), 1)) - missedPct := toPercent(safeDiv(float32(missed), float32(totalInstructions), 0)) - withDataPct := toPercent(safeDiv(float32(linesWithDataCount), float32(totalLines), 1)) - withoutDataPct := toPercent(safeDiv(float32(linesWithoutDataCount), float32(totalLines), 0)) - - return []string{ - fmt.Sprintf("### %v Covered Instructions: %.f%% (%d)\n", coverageStatusEmoji(coveredPct), coveredPct, covered), - "\n", - "| Metric | Result | What it means |\n", - "| :-- | :-: | :-- |\n", - fmt.Sprintf("| 🟢 **Covered Instructions** | **%.f%%** (%d) | Changed code your tests executed. Higher is better. |\n", coveredPct, covered), - fmt.Sprintf("| šŸ”“ **Missed Instructions** | %.f%% (%d) | Changed code your tests never ran. Lower is better. |\n", missedPct, missed), - fmt.Sprintf("| šŸ“ˆ Lines With Coverage Data | %.f%% (%d) | Changed lines the coverage tool could track. |\n", withDataPct, linesWithDataCount), - fmt.Sprintf("| ⚪ Lines Without Coverage Data | %.f%% (%d) | Changed lines with no data: comments, blanks, declarations. |\n", withoutDataPct, linesWithoutDataCount), - } - })...) + fmt.Fprintf(&b, "*Modules:* %v\n\n", strings.Join(modules, ", ")) + } + + fmt.Fprintf(&b, "**Diff coverage:** `%.f%%` %v — `%d` of `%d` changed instructions covered\n\n", + coveredPct, coverageStatusEmoji(coveredPct), covered, totalInstructions) + + b.WriteString("| Metric | Value | |\n") + b.WriteString("| :-- | --: | :-- |\n") + fmt.Fprintf(&b, "| 🟢 Covered instructions | `%d` (%.f%%) | changed code your tests executed |\n", covered, coveredPct) + fmt.Fprintf(&b, "| šŸ”“ Missed instructions | `%d` (%.f%%) | changed code your tests never ran |\n", missed, missedPct) + fmt.Fprintf(&b, "| šŸ“ˆ Tracked changed lines | `%d` (%.f%%) | lines the coverage tool could measure |\n", linesWithData, withDataPct) + fmt.Fprintf(&b, "| ⚪ Untracked changed lines | `%d` (%.f%%) | comments, blanks, declarations |\n", linesWithoutData, withoutDataPct) + b.WriteString("\n") - body := strings.Join(bodyLines, "") - body += missedInstructionsSection(changedLinesWithCoverage) - body += "\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n" + b.WriteString(fileCoverageSection(changedLinesWithCoverage)) + b.WriteString(missedInstructionsSection(changedLinesWithCoverage)) + b.WriteString("\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n") data := map[string]string{ - "body": body, + "body": b.String(), } dataBytes, marshalErr := s.jsonClient.Marshal(data) @@ -138,6 +141,107 @@ func (s *GithubPullRequest) createCommentBody(changedLinesWithCoverage domain.So return bytes.NewBuffer(dataBytes), nil } +// fileCoverage holds the aggregated changed-line coverage for a single file. +type fileCoverage struct { + path string + covered int + missed int + linesWithData int + linesWithoutData int +} + +// fileCoverageSection renders a per-file breakdown of changed-line coverage, +// worst-covered files first so the riskiest changes surface at the top. +func fileCoverageSection(changedLinesWithCoverage domain.SourceLineCoverageReport) string { + files := collectFileCoverage(changedLinesWithCoverage) + + if len(files) == 0 { + return "" + } + + // Files whose only changed lines carry no coverage data (config, docs, + // generated, test-only) would just be a wall of "n/a" rows, so keep them + // out of the table and summarise the count underneath instead. + unmeasured := 0 + + var b strings.Builder + + b.WriteString("### Coverage by file\n\n") + b.WriteString("| File | Diff coverage | Covered / Missed |\n") + b.WriteString("| :-- | :-: | :-: |\n") + + for _, f := range files { + instructions := f.covered + f.missed + + if instructions == 0 { + unmeasured++ + continue + } + + pct := toPercent(safeDiv(float32(f.covered), float32(instructions), 1)) + fmt.Fprintf(&b, "| `%v` | %v %.f%% | %d / %d |\n", + f.path, coverageStatusEmoji(pct), pct, f.covered, f.missed) + } + + b.WriteString("\n") + + if unmeasured > 0 { + fmt.Fprintf(&b, "%d changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n", unmeasured) + } + + return b.String() +} + +// collectFileCoverage aggregates changed-line coverage per file, sorted with the +// lowest-covered files first (files with no measurable instructions last) so a +// reviewer sees the riskiest files at the top of the table. +func collectFileCoverage(changedLinesWithCoverage domain.SourceLineCoverageReport) []fileCoverage { + order := []string{} + byPath := map[string]*fileCoverage{} + + for _, line := range changedLinesWithCoverage { + path := filePath(line.SourceLine) + + fc, ok := byPath[path] + if !ok { + fc = &fileCoverage{path: path} + byPath[path] = fc + order = append(order, path) + } + + fc.covered += line.CoveredInstructionCount + fc.missed += line.MissedInstructionCount + + if line.HasData() { + fc.linesWithData++ + } else { + fc.linesWithoutData++ + } + } + + result := make([]fileCoverage, 0, len(order)) + for _, path := range order { + result = append(result, *byPath[path]) + } + + sort.SliceStable(result, func(i, j int) bool { + return fileCoveragePct(result[i]) < fileCoveragePct(result[j]) + }) + + return result +} + +// fileCoveragePct returns a file's changed-line coverage as a sortable value; +// files with no measurable instructions sort last (returned above 100%). +func fileCoveragePct(f fileCoverage) float32 { + instructions := f.covered + f.missed + if instructions == 0 { + return 101 + } + + return toPercent(safeDiv(float32(f.covered), float32(instructions), 1)) +} + // missedInstructionsSection renders a collapsible block listing each changed // line that was not executed by tests. Returns "" when nothing was missed. func missedInstructionsSection(changedLinesWithCoverage domain.SourceLineCoverageReport) string { diff --git a/internal/plugin/reporter/utils.go b/internal/plugin/reporter/utils.go index e0268a3..3696931 100644 --- a/internal/plugin/reporter/utils.go +++ b/internal/plugin/reporter/utils.go @@ -8,6 +8,12 @@ import ( ) func lineDescription(l domain.SourceLine) string { + return fmt.Sprintf("%v:%v", filePath(l), l.LineNumber) +} + +// filePath joins the non-empty path segments of a source line into a single +// file path (without the line number), used to group coverage by file. +func filePath(l domain.SourceLine) string { rawFileNameParts := []string{ l.Module, l.SrcDir, l.Pkg, l.FileName, } @@ -19,5 +25,5 @@ func lineDescription(l domain.SourceLine) string { } } - return fmt.Sprintf("%v:%v", strings.Join(fileNameParts, "/"), l.LineNumber) + return strings.Join(fileNameParts, "/") } diff --git a/internal/plugin/runner_test.go b/internal/plugin/runner_test.go index e1f64f0..6c83db5 100644 --- a/internal/plugin/runner_test.go +++ b/internal/plugin/runner_test.go @@ -108,38 +108,7 @@ Missed Instructions -> 3% (5) `, buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": `## šŸ“Š Code Coverage — Changed Lines - -> Coverage is measured **only for the lines this PR changes**, not the whole file or repo. - -### 🟢 Covered Instructions: 97% (177) - -| Metric | Result | What it means | -| :-- | :-: | :-- | -| 🟢 **Covered Instructions** | **97%** (177) | Changed code your tests executed. Higher is better. | -| šŸ”“ **Missed Instructions** | 3% (5) | Changed code your tests never ran. Lower is better. | -| šŸ“ˆ Lines With Coverage Data | 8% (182) | Changed lines the coverage tool could track. | -| ⚪ Lines Without Coverage Data | 92% (2216) | Changed lines with no data: comments, blanks, declarations. | - -
šŸ” Missed instructions (5) - -` + "```" + ` ---- internal/plugin/runner.go:72 -func GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader { ---- main.go:10 - err := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout) ---- main.go:12 - if err != nil { ---- main.go:13 - log.WithFields(log.Fields{ ---- main.go:17 - os.Exit(1) -` + - "```" + ` -
- -šŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only. -`, + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n**Diff coverage:** `97%` 🟢 — `177` of `182` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `177` (97%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `5` (3%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `182` (8%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `2216` (92%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `main.go` | šŸ”“ 0% | 0 / 4 |\n| `internal/plugin/runner.go` | 🟢 96% | 27 / 1 |\n| `internal/plugin/calculator/calculator.go` | 🟢 100% | 10 / 0 |\n| `internal/plugin/coverage/jacoco/report.go` | 🟢 100% | 29 / 0 |\n| `internal/plugin/domain/domain.go` | 🟢 100% | 19 / 0 |\n| `internal/plugin/reporter/reporter.go` | 🟢 100% | 25 / 0 |\n| `internal/plugin/sourcelines/unifieddiff/changed_source_loader.go` | 🟢 100% | 64 / 0 |\n| `internal/test/mocks/property_getter.go` | 🟢 100% | 3 / 0 |\n\n25 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (5)\n\n```\n--- internal/plugin/runner.go:72\nfunc GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n--- main.go:10\n\terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n--- main.go:12\n\tif err != nil {\n--- main.go:13\n\t\tlog.WithFields(log.Fields{\n--- main.go:17\n\t\tos.Exit(1)\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -189,38 +158,7 @@ Missed Instructions -> 3% (5) `, buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": `## šŸ“Š Code Coverage — Changed Lines - -> Coverage is measured **only for the lines this PR changes**, not the whole file or repo. - -### 🟢 Covered Instructions: 97% (177) - -| Metric | Result | What it means | -| :-- | :-: | :-- | -| 🟢 **Covered Instructions** | **97%** (177) | Changed code your tests executed. Higher is better. | -| šŸ”“ **Missed Instructions** | 3% (5) | Changed code your tests never ran. Lower is better. | -| šŸ“ˆ Lines With Coverage Data | 8% (182) | Changed lines the coverage tool could track. | -| ⚪ Lines Without Coverage Data | 92% (2216) | Changed lines with no data: comments, blanks, declarations. | - -
šŸ” Missed instructions (5) - -` + "```" + ` ---- internal/plugin/runner.go:72 -func GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader { ---- main.go:10 - err := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout) ---- main.go:12 - if err != nil { ---- main.go:13 - log.WithFields(log.Fields{ ---- main.go:17 - os.Exit(1) -` + - "```" + ` -
- -šŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only. -`, + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n**Diff coverage:** `97%` 🟢 — `177` of `182` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `177` (97%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `5` (3%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `182` (8%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `2216` (92%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `main.go` | šŸ”“ 0% | 0 / 4 |\n| `internal/plugin/runner.go` | 🟢 96% | 27 / 1 |\n| `internal/plugin/calculator/calculator.go` | 🟢 100% | 10 / 0 |\n| `internal/plugin/coverage/jacoco/report.go` | 🟢 100% | 29 / 0 |\n| `internal/plugin/domain/domain.go` | 🟢 100% | 19 / 0 |\n| `internal/plugin/reporter/reporter.go` | 🟢 100% | 25 / 0 |\n| `internal/plugin/sourcelines/unifieddiff/changed_source_loader.go` | 🟢 100% | 64 / 0 |\n| `internal/test/mocks/property_getter.go` | 🟢 100% | 3 / 0 |\n\n25 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (5)\n\n```\n--- internal/plugin/runner.go:72\nfunc GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n--- main.go:10\n\terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n--- main.go:12\n\tif err != nil {\n--- main.go:13\n\t\tlog.WithFields(log.Fields{\n--- main.go:17\n\t\tos.Exit(1)\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -260,32 +198,7 @@ Missed Instructions -> 27% (3) `, buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": `## šŸ“Š Code Coverage — Changed Lines - -> Coverage is measured **only for the lines this PR changes**, not the whole file or repo. - -*Modules: category-search* - -### 🟔 Covered Instructions: 73% (8) - -| Metric | Result | What it means | -| :-- | :-: | :-- | -| 🟢 **Covered Instructions** | **73%** (8) | Changed code your tests executed. Higher is better. | -| šŸ”“ **Missed Instructions** | 27% (3) | Changed code your tests never ran. Lower is better. | -| šŸ“ˆ Lines With Coverage Data | 22% (2) | Changed lines the coverage tool could track. | -| ⚪ Lines Without Coverage Data | 78% (7) | Changed lines with no data: comments, blanks, declarations. | - -
šŸ” Missed instructions (1) - -` + "```" + ` ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); -` + - "```" + ` -
- -šŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only. -`, + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `73%` 🟔 — `8` of `11` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `8` (73%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `3` (27%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `2` (22%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (78%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (1)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -326,32 +239,7 @@ Missed Instructions -> 27% (3) `, buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": `## šŸ“Š Code Coverage — Changed Lines - -> Coverage is measured **only for the lines this PR changes**, not the whole file or repo. - -*Modules: category-search* - -### 🟔 Covered Instructions: 73% (8) - -| Metric | Result | What it means | -| :-- | :-: | :-- | -| 🟢 **Covered Instructions** | **73%** (8) | Changed code your tests executed. Higher is better. | -| šŸ”“ **Missed Instructions** | 27% (3) | Changed code your tests never ran. Lower is better. | -| šŸ“ˆ Lines With Coverage Data | 22% (2) | Changed lines the coverage tool could track. | -| ⚪ Lines Without Coverage Data | 78% (7) | Changed lines with no data: comments, blanks, declarations. | - -
šŸ” Missed instructions (1) - -` + "```" + ` ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); -` + - "```" + ` -
- -šŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only. -`, + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `73%` 🟔 — `8` of `11` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `8` (73%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `3` (27%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `2` (22%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (78%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (1)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -394,33 +282,7 @@ Missed Instructions -> 12% (6) `, buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": `## šŸ“Š Code Coverage — Changed Lines - -> Coverage is measured **only for the lines this PR changes**, not the whole file or repo. - -*Modules: category-search* - -### 🟢 Covered Instructions: 88% (42) - -| Metric | Result | What it means | -| :-- | :-: | :-- | -| 🟢 **Covered Instructions** | **88%** (42) | Changed code your tests executed. Higher is better. | -| šŸ”“ **Missed Instructions** | 12% (6) | Changed code your tests never ran. Lower is better. | -| šŸ“ˆ Lines With Coverage Data | 53% (8) | Changed lines the coverage tool could track. | -| ⚪ Lines Without Coverage Data | 47% (7) | Changed lines with no data: comments, blanks, declarations. | - -
šŸ” Missed instructions (2) - -` + "```" + ` ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); ---- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12 - System.out.print("Something2"); -` + "```" + ` -
- -šŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only. -`, + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `88%` 🟢 — `42` of `48` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `42` (88%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `6` (12%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `8` (53%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (47%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n| `category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt` | 🟢 92% | 34 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (2)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n--- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -464,34 +326,7 @@ Missed Instructions -> 12% (6) `, buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": `## šŸ“Š Code Coverage — Changed Lines - -> Coverage is measured **only for the lines this PR changes**, not the whole file or repo. - -*Modules: category-search* - -### 🟢 Covered Instructions: 88% (42) - -| Metric | Result | What it means | -| :-- | :-: | :-- | -| 🟢 **Covered Instructions** | **88%** (42) | Changed code your tests executed. Higher is better. | -| šŸ”“ **Missed Instructions** | 12% (6) | Changed code your tests never ran. Lower is better. | -| šŸ“ˆ Lines With Coverage Data | 53% (8) | Changed lines the coverage tool could track. | -| ⚪ Lines Without Coverage Data | 47% (7) | Changed lines with no data: comments, blanks, declarations. | - -
šŸ” Missed instructions (2) - -` + "```" + ` ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); ---- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12 - System.out.print("Something2"); -` + - "```" + ` -
- -šŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only. -`, + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `88%` 🟢 — `42` of `48` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `42` (88%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `6` (12%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `8` (53%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (47%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n| `category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt` | 🟢 92% | 34 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (2)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n--- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) From fca7c2e03743111ab9565c098a868e347231e5b0 Mon Sep 17 00:00:00 2001 From: Vishal Vaibhav Date: Sun, 24 May 2026 10:52:53 +0530 Subject: [PATCH 2/2] feat: make console logs more richer --- internal/plugin/reporter/github_pr.go | 5 +- internal/plugin/reporter/simple.go | 127 ++++++++++++++++++++------ internal/plugin/runner_test.go | 125 +++---------------------- 3 files changed, 118 insertions(+), 139 deletions(-) diff --git a/internal/plugin/reporter/github_pr.go b/internal/plugin/reporter/github_pr.go index 8c917db..6633aab 100644 --- a/internal/plugin/reporter/github_pr.go +++ b/internal/plugin/reporter/github_pr.go @@ -107,7 +107,7 @@ func (s *GithubPullRequest) createCommentBody(changedLinesWithCoverage domain.So b.WriteString("## šŸ›”ļø Patch Coverage Report\n\n") b.WriteString("> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. ") - b.WriteString("There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n") + b.WriteString("It answers one thing — *did your tests run the code you just touched?*\n\n") if len(modules) > 0 { fmt.Fprintf(&b, "*Modules:* %v\n\n", strings.Join(modules, ", ")) @@ -123,6 +123,7 @@ func (s *GithubPullRequest) createCommentBody(changedLinesWithCoverage domain.So fmt.Fprintf(&b, "| šŸ“ˆ Tracked changed lines | `%d` (%.f%%) | lines the coverage tool could measure |\n", linesWithData, withDataPct) fmt.Fprintf(&b, "| ⚪ Untracked changed lines | `%d` (%.f%%) | comments, blanks, declarations |\n", linesWithoutData, withoutDataPct) b.WriteString("\n") + b.WriteString("**Lines** = the source lines you changed. **Instructions** = the executable units the coverage tool counts inside those lines — one line can hold several (e.g. JaCoCo bytecode), so the two counts differ.\n\n") b.WriteString(fileCoverageSection(changedLinesWithCoverage)) b.WriteString(missedInstructionsSection(changedLinesWithCoverage)) @@ -260,7 +261,7 @@ func missedInstructionsSection(changedLinesWithCoverage domain.SourceLineCoverag return "" } - return fmt.Sprintf("\n
šŸ” Missed instructions (%d)\n\n", missedLineCount) + + return fmt.Sprintf("\n
šŸ” Uncovered lines (%d)\n\n", missedLineCount) + "```\n" + missedInstructions + "```" + "\n
\n" } diff --git a/internal/plugin/reporter/simple.go b/internal/plugin/reporter/simple.go index 55f6e96..399fb1e 100644 --- a/internal/plugin/reporter/simple.go +++ b/internal/plugin/reporter/simple.go @@ -5,10 +5,13 @@ import ( "io" "log" + "strings" "github.com/target/pull-request-code-coverage/internal/plugin/domain" ) +const consoleRule = "──────────────────────────────────────────────────────────────" + type Simple struct { Out io.Writer WritingFuncf func(io.Writer, string, ...interface{}) (int, error) @@ -24,34 +27,51 @@ func NewSimple(out io.Writer) *Simple { } func (s *Simple) Write(changedLinesWithCoverage domain.SourceLineCoverageReport) error { - s.printf("Missed Instructions:\n") - for _, r := range changedLinesWithCoverage { - if r.MissedInstructionCount > 0 { - s.printf("--- %v\n", lineDescription(r.SourceLine)) - s.printf("%v\n", r.LineValue) - } - } + covered := changedLinesWithCoverage.TotalCoveredInstructions() + missed := changedLinesWithCoverage.TotalMissedInstructions() + linesWithData := changedLinesWithCoverage.TotalLinesWithData() + linesWithoutData := changedLinesWithCoverage.TotalLinesWithoutData() - summaryLines := generateSummaryLines(changedLinesWithCoverage, func(linesWithDataCount int, linesWithoutDataCount int, covered int, missed int) []string { - totalLines := linesWithDataCount + linesWithoutDataCount - totalInstructions := covered + missed + totalInstructions := covered + missed + totalLines := linesWithData + linesWithoutData - result := make([]string, 5) + coveredPct := toPercent(safeDiv(float32(covered), float32(totalInstructions), 1)) + missedPct := toPercent(safeDiv(float32(missed), float32(totalInstructions), 0)) + withDataPct := toPercent(safeDiv(float32(linesWithData), float32(totalLines), 1)) + withoutDataPct := toPercent(safeDiv(float32(linesWithoutData), float32(totalLines), 0)) - result[0] = "Code Coverage Summary:\n" - result[1] = fmt.Sprintf("Lines Without Coverage Data -> %.f%% (%d)\n", toPercent(safeDiv(float32(linesWithoutDataCount), float32(totalLines), 0)), linesWithoutDataCount) - result[2] = fmt.Sprintf("Lines With Coverage Data -> %.f%% (%d)\n", toPercent(safeDiv(float32(linesWithDataCount), float32(totalLines), 1)), linesWithDataCount) - result[3] = fmt.Sprintf("Covered Instructions -> %.f%% (%d)\n", toPercent(safeDiv(float32(covered), float32(totalInstructions), 1)), covered) - result[4] = fmt.Sprintf("Missed Instructions -> %.f%% (%d)\n", toPercent(safeDiv(float32(missed), float32(totalInstructions), 0)), missed) + // Build the whole report first and emit it in one write so it stays a + // contiguous block in the CI console instead of interleaving with logs. + var b strings.Builder - return result - }) + b.WriteString(consoleRule + "\n") + b.WriteString(" šŸ“Š Patch Coverage Report — changed lines only\n") + b.WriteString(consoleRule + "\n") - s.print("\n") - for _, line := range summaryLines { - s.print(line) + if modules := collectModules(changedLinesWithCoverage); len(modules) > 0 { + fmt.Fprintf(&b, " Modules: %s\n", strings.Join(modules, ", ")) } + fmt.Fprintf(&b, "\n Diff coverage: %.f%% %s — %d of %d changed instructions covered\n\n", + coveredPct, coverageStatusEmoji(coveredPct), covered, totalInstructions) + + b.WriteString(" Summary\n") + fmt.Fprintf(&b, " %-26s%3.f%% (%d)\n", "Covered instructions", coveredPct, covered) + fmt.Fprintf(&b, " %-26s%3.f%% (%d)\n", "Missed instructions", missedPct, missed) + fmt.Fprintf(&b, " %-26s%3.f%% (%d)\n", "Tracked changed lines", withDataPct, linesWithData) + fmt.Fprintf(&b, " %-26s%3.f%% (%d)\n", "Untracked changed lines", withoutDataPct, linesWithoutData) + + b.WriteString("\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n") + b.WriteString(" executable units the coverage tool counts inside them (one line can hold\n") + b.WriteString(" several, e.g. JaCoCo bytecode), so the two counts differ.\n\n") + + b.WriteString(fileCoverageConsoleSection(changedLinesWithCoverage)) + b.WriteString(uncoveredLinesConsoleSection(changedLinesWithCoverage)) + + b.WriteString(consoleRule + "\n") + + s.print(b.String()) + return nil } @@ -59,14 +79,67 @@ func (s *Simple) GetName() string { return "simple stdout reporter" } -func generateSummaryLines(changedLinesWithCoverage domain.SourceLineCoverageReport, formatter func(linesWithDataCount int, linesWithoutDataCount int, covered int, missed int) []string) []string { - linesWithDataCount := changedLinesWithCoverage.TotalLinesWithData() - linesWithoutDataCount := changedLinesWithCoverage.TotalLinesWithoutData() +// fileCoverageConsoleSection renders the per-file breakdown for the console, +// lowest-covered first, omitting files with no measurable lines. +func fileCoverageConsoleSection(changedLinesWithCoverage domain.SourceLineCoverageReport) string { + files := collectFileCoverage(changedLinesWithCoverage) - covered := changedLinesWithCoverage.TotalCoveredInstructions() - missed := changedLinesWithCoverage.TotalMissedInstructions() + var b strings.Builder + b.WriteString(" Coverage by file (lowest coverage first)\n") + + measured := 0 + unmeasured := 0 + + for _, f := range files { + instructions := f.covered + f.missed + + if instructions == 0 { + unmeasured++ + continue + } + + measured++ + pct := toPercent(safeDiv(float32(f.covered), float32(instructions), 1)) + fmt.Fprintf(&b, " %3.f%% %3d cov / %3d miss %s\n", pct, f.covered, f.missed, f.path) + } + + if measured == 0 { + b.WriteString(" (no files with measurable lines)\n") + } + + if unmeasured > 0 { + fmt.Fprintf(&b, " (%d file(s) with no measurable lines omitted)\n", unmeasured) + } + + b.WriteString("\n") + + return b.String() +} + +// uncoveredLinesConsoleSection lists each changed line that tests never ran. +func uncoveredLinesConsoleSection(changedLinesWithCoverage domain.SourceLineCoverageReport) string { + var rows []string + + for _, r := range changedLinesWithCoverage { + if r.MissedInstructionCount > 0 { + rows = append(rows, fmt.Sprintf(" - %s\n %s\n", lineDescription(r.SourceLine), r.LineValue)) + } + } + + var b strings.Builder + fmt.Fprintf(&b, " Uncovered lines (%d)\n", len(rows)) + + if len(rows) == 0 { + b.WriteString(" none šŸŽ‰\n") + } + + for _, row := range rows { + b.WriteString(row) + } + + b.WriteString("\n") - return formatter(linesWithDataCount, linesWithoutDataCount, covered, missed) + return b.String() } func toPercent(decimal float32) float32 { diff --git a/internal/plugin/runner_test.go b/internal/plugin/runner_test.go index 6c83db5..4922c7a 100644 --- a/internal/plugin/runner_test.go +++ b/internal/plugin/runner_test.go @@ -88,27 +88,10 @@ func TestDefaultRunner_Run_GoExample_WithSourceDir(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/example_go_unified.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: ---- internal/plugin/runner.go:72 -func GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader { ---- main.go:10 - err := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout) ---- main.go:12 - if err != nil { ---- main.go:13 - log.WithFields(log.Fields{ ---- main.go:17 - os.Exit(1) - -Code Coverage Summary: -Lines Without Coverage Data -> 92% (2216) -Lines With Coverage Data -> 8% (182) -Covered Instructions -> 97% (177) -Missed Instructions -> 3% (5) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n\n Diff coverage: 97% 🟢 — 177 of 182 changed instructions covered\n\n Summary\n Covered instructions 97% (177)\n Missed instructions 3% (5)\n Tracked changed lines 8% (182)\n Untracked changed lines 92% (2216)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n 0% 0 cov / 4 miss main.go\n 96% 27 cov / 1 miss internal/plugin/runner.go\n 100% 10 cov / 0 miss internal/plugin/calculator/calculator.go\n 100% 29 cov / 0 miss internal/plugin/coverage/jacoco/report.go\n 100% 19 cov / 0 miss internal/plugin/domain/domain.go\n 100% 25 cov / 0 miss internal/plugin/reporter/reporter.go\n 100% 64 cov / 0 miss internal/plugin/sourcelines/unifieddiff/changed_source_loader.go\n 100% 3 cov / 0 miss internal/test/mocks/property_getter.go\n (25 file(s) with no measurable lines omitted)\n\n Uncovered lines (5)\n - internal/plugin/runner.go:72\n func GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n - main.go:10\n \terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n - main.go:12\n \tif err != nil {\n - main.go:13\n \t\tlog.WithFields(log.Fields{\n - main.go:17\n \t\tos.Exit(1)\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n**Diff coverage:** `97%` 🟢 — `177` of `182` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `177` (97%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `5` (3%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `182` (8%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `2216` (92%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `main.go` | šŸ”“ 0% | 0 / 4 |\n| `internal/plugin/runner.go` | 🟢 96% | 27 / 1 |\n| `internal/plugin/calculator/calculator.go` | 🟢 100% | 10 / 0 |\n| `internal/plugin/coverage/jacoco/report.go` | 🟢 100% | 29 / 0 |\n| `internal/plugin/domain/domain.go` | 🟢 100% | 19 / 0 |\n| `internal/plugin/reporter/reporter.go` | 🟢 100% | 25 / 0 |\n| `internal/plugin/sourcelines/unifieddiff/changed_source_loader.go` | 🟢 100% | 64 / 0 |\n| `internal/test/mocks/property_getter.go` | 🟢 100% | 3 / 0 |\n\n25 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (5)\n\n```\n--- internal/plugin/runner.go:72\nfunc GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n--- main.go:10\n\terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n--- main.go:12\n\tif err != nil {\n--- main.go:13\n\t\tlog.WithFields(log.Fields{\n--- main.go:17\n\t\tos.Exit(1)\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. It answers one thing — *did your tests run the code you just touched?*\n\n**Diff coverage:** `97%` 🟢 — `177` of `182` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `177` (97%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `5` (3%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `182` (8%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `2216` (92%) | comments, blanks, declarations |\n\n**Lines** = the source lines you changed. **Instructions** = the executable units the coverage tool counts inside those lines — one line can hold several (e.g. JaCoCo bytecode), so the two counts differ.\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `main.go` | šŸ”“ 0% | 0 / 4 |\n| `internal/plugin/runner.go` | 🟢 96% | 27 / 1 |\n| `internal/plugin/calculator/calculator.go` | 🟢 100% | 10 / 0 |\n| `internal/plugin/coverage/jacoco/report.go` | 🟢 100% | 29 / 0 |\n| `internal/plugin/domain/domain.go` | 🟢 100% | 19 / 0 |\n| `internal/plugin/reporter/reporter.go` | 🟢 100% | 25 / 0 |\n| `internal/plugin/sourcelines/unifieddiff/changed_source_loader.go` | 🟢 100% | 64 / 0 |\n| `internal/test/mocks/property_getter.go` | 🟢 100% | 3 / 0 |\n\n25 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Uncovered lines (5)\n\n```\n--- internal/plugin/runner.go:72\nfunc GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n--- main.go:10\n\terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n--- main.go:12\n\tif err != nil {\n--- main.go:13\n\t\tlog.WithFields(log.Fields{\n--- main.go:17\n\t\tos.Exit(1)\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -138,27 +121,10 @@ func TestDefaultRunner_Run_GoExample(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/example_go_unified.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: ---- internal/plugin/runner.go:72 -func GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader { ---- main.go:10 - err := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout) ---- main.go:12 - if err != nil { ---- main.go:13 - log.WithFields(log.Fields{ ---- main.go:17 - os.Exit(1) - -Code Coverage Summary: -Lines Without Coverage Data -> 92% (2216) -Lines With Coverage Data -> 8% (182) -Covered Instructions -> 97% (177) -Missed Instructions -> 3% (5) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n\n Diff coverage: 97% 🟢 — 177 of 182 changed instructions covered\n\n Summary\n Covered instructions 97% (177)\n Missed instructions 3% (5)\n Tracked changed lines 8% (182)\n Untracked changed lines 92% (2216)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n 0% 0 cov / 4 miss main.go\n 96% 27 cov / 1 miss internal/plugin/runner.go\n 100% 10 cov / 0 miss internal/plugin/calculator/calculator.go\n 100% 29 cov / 0 miss internal/plugin/coverage/jacoco/report.go\n 100% 19 cov / 0 miss internal/plugin/domain/domain.go\n 100% 25 cov / 0 miss internal/plugin/reporter/reporter.go\n 100% 64 cov / 0 miss internal/plugin/sourcelines/unifieddiff/changed_source_loader.go\n 100% 3 cov / 0 miss internal/test/mocks/property_getter.go\n (25 file(s) with no measurable lines omitted)\n\n Uncovered lines (5)\n - internal/plugin/runner.go:72\n func GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n - main.go:10\n \terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n - main.go:12\n \tif err != nil {\n - main.go:13\n \t\tlog.WithFields(log.Fields{\n - main.go:17\n \t\tos.Exit(1)\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n**Diff coverage:** `97%` 🟢 — `177` of `182` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `177` (97%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `5` (3%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `182` (8%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `2216` (92%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `main.go` | šŸ”“ 0% | 0 / 4 |\n| `internal/plugin/runner.go` | 🟢 96% | 27 / 1 |\n| `internal/plugin/calculator/calculator.go` | 🟢 100% | 10 / 0 |\n| `internal/plugin/coverage/jacoco/report.go` | 🟢 100% | 29 / 0 |\n| `internal/plugin/domain/domain.go` | 🟢 100% | 19 / 0 |\n| `internal/plugin/reporter/reporter.go` | 🟢 100% | 25 / 0 |\n| `internal/plugin/sourcelines/unifieddiff/changed_source_loader.go` | 🟢 100% | 64 / 0 |\n| `internal/test/mocks/property_getter.go` | 🟢 100% | 3 / 0 |\n\n25 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (5)\n\n```\n--- internal/plugin/runner.go:72\nfunc GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n--- main.go:10\n\terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n--- main.go:12\n\tif err != nil {\n--- main.go:13\n\t\tlog.WithFields(log.Fields{\n--- main.go:17\n\t\tos.Exit(1)\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. It answers one thing — *did your tests run the code you just touched?*\n\n**Diff coverage:** `97%` 🟢 — `177` of `182` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `177` (97%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `5` (3%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `182` (8%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `2216` (92%) | comments, blanks, declarations |\n\n**Lines** = the source lines you changed. **Instructions** = the executable units the coverage tool counts inside those lines — one line can hold several (e.g. JaCoCo bytecode), so the two counts differ.\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `main.go` | šŸ”“ 0% | 0 / 4 |\n| `internal/plugin/runner.go` | 🟢 96% | 27 / 1 |\n| `internal/plugin/calculator/calculator.go` | 🟢 100% | 10 / 0 |\n| `internal/plugin/coverage/jacoco/report.go` | 🟢 100% | 29 / 0 |\n| `internal/plugin/domain/domain.go` | 🟢 100% | 19 / 0 |\n| `internal/plugin/reporter/reporter.go` | 🟢 100% | 25 / 0 |\n| `internal/plugin/sourcelines/unifieddiff/changed_source_loader.go` | 🟢 100% | 64 / 0 |\n| `internal/test/mocks/property_getter.go` | 🟢 100% | 3 / 0 |\n\n25 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Uncovered lines (5)\n\n```\n--- internal/plugin/runner.go:72\nfunc GetCoverageReportLoader(coverageType string, sourceDir string) coverage.Loader {\n--- main.go:10\n\terr := plugin.NewRunner().Run(os.LookupEnv, os.Stdin, os.Stdout)\n--- main.go:12\n\tif err != nil {\n--- main.go:13\n\t\tlog.WithFields(log.Fields{\n--- main.go:17\n\t\tos.Exit(1)\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -186,19 +152,10 @@ func TestDefaultRunner_Run(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/sample_unified.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); - -Code Coverage Summary: -Lines Without Coverage Data -> 78% (7) -Lines With Coverage Data -> 22% (2) -Covered Instructions -> 73% (8) -Missed Instructions -> 27% (3) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n Modules: category-search\n\n Diff coverage: 73% 🟔 — 8 of 11 changed instructions covered\n\n Summary\n Covered instructions 73% (8)\n Missed instructions 27% (3)\n Tracked changed lines 22% (2)\n Untracked changed lines 78% (7)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n 73% 8 cov / 3 miss category-search/src/main/java/com/tgt/CategorySearchApplication.java\n (3 file(s) with no measurable lines omitted)\n\n Uncovered lines (1)\n - category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `73%` 🟔 — `8` of `11` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `8` (73%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `3` (27%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `2` (22%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (78%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (1)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. It answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `73%` 🟔 — `8` of `11` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `8` (73%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `3` (27%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `2` (22%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (78%) | comments, blanks, declarations |\n\n**Lines** = the source lines you changed. **Instructions** = the executable units the coverage tool counts inside those lines — one line can hold several (e.g. JaCoCo bytecode), so the two counts differ.\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Uncovered lines (1)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -227,19 +184,10 @@ func TestDefaultRunner_Run_Vela(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/sample_unified.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); - -Code Coverage Summary: -Lines Without Coverage Data -> 78% (7) -Lines With Coverage Data -> 22% (2) -Covered Instructions -> 73% (8) -Missed Instructions -> 27% (3) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n Modules: category-search\n\n Diff coverage: 73% 🟔 — 8 of 11 changed instructions covered\n\n Summary\n Covered instructions 73% (8)\n Missed instructions 27% (3)\n Tracked changed lines 22% (2)\n Untracked changed lines 78% (7)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n 73% 8 cov / 3 miss category-search/src/main/java/com/tgt/CategorySearchApplication.java\n (3 file(s) with no measurable lines omitted)\n\n Uncovered lines (1)\n - category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `73%` 🟔 — `8` of `11` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `8` (73%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `3` (27%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `2` (22%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (78%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (1)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. It answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `73%` 🟔 — `8` of `11` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `8` (73%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `3` (27%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `2` (22%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (78%) | comments, blanks, declarations |\n\n**Lines** = the source lines you changed. **Instructions** = the executable units the coverage tool counts inside those lines — one line can hold several (e.g. JaCoCo bytecode), so the two counts differ.\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Uncovered lines (1)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -268,21 +216,10 @@ func TestDefaultRunner_Run_2_Source_Dirs(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/sample_unified_2_source_dirs.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); ---- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12 - System.out.print("Something2"); - -Code Coverage Summary: -Lines Without Coverage Data -> 47% (7) -Lines With Coverage Data -> 53% (8) -Covered Instructions -> 88% (42) -Missed Instructions -> 12% (6) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n Modules: category-search\n\n Diff coverage: 88% 🟢 — 42 of 48 changed instructions covered\n\n Summary\n Covered instructions 88% (42)\n Missed instructions 12% (6)\n Tracked changed lines 53% (8)\n Untracked changed lines 47% (7)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n 73% 8 cov / 3 miss category-search/src/main/java/com/tgt/CategorySearchApplication.java\n 92% 34 cov / 3 miss category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt\n (3 file(s) with no measurable lines omitted)\n\n Uncovered lines (2)\n - category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n - category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `88%` 🟢 — `42` of `48` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `42` (88%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `6` (12%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `8` (53%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (47%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n| `category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt` | 🟢 92% | 34 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (2)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n--- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. It answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `88%` 🟢 — `42` of `48` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `42` (88%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `6` (12%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `8` (53%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (47%) | comments, blanks, declarations |\n\n**Lines** = the source lines you changed. **Instructions** = the executable units the coverage tool counts inside those lines — one line can hold several (e.g. JaCoCo bytecode), so the two counts differ.\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n| `category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt` | 🟢 92% | 34 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Uncovered lines (2)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n--- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -312,21 +249,10 @@ func TestDefaultRunner_Run_2_Source_Dirs_Vela(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/sample_unified_2_source_dirs.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: ---- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52 - System.out.print("Something"); ---- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12 - System.out.print("Something2"); - -Code Coverage Summary: -Lines Without Coverage Data -> 47% (7) -Lines With Coverage Data -> 53% (8) -Covered Instructions -> 88% (42) -Missed Instructions -> 12% (6) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n Modules: category-search\n\n Diff coverage: 88% 🟢 — 42 of 48 changed instructions covered\n\n Summary\n Covered instructions 88% (42)\n Missed instructions 12% (6)\n Tracked changed lines 53% (8)\n Untracked changed lines 47% (7)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n 73% 8 cov / 3 miss category-search/src/main/java/com/tgt/CategorySearchApplication.java\n 92% 34 cov / 3 miss category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt\n (3 file(s) with no measurable lines omitted)\n\n Uncovered lines (2)\n - category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n - category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertRequestWasMade(t, "/repos/some_org/some_repo/issues/123/comments", "SOME_API_KEY", map[string]interface{}{ - "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. There's no base-branch diff here; it answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `88%` 🟢 — `42` of `48` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `42` (88%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `6` (12%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `8` (53%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (47%) | comments, blanks, declarations |\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n| `category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt` | 🟢 92% | 34 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Missed instructions (2)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n--- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", + "body": "## šŸ›”ļø Patch Coverage Report\n\n> Scope: **changed lines only** — the code this PR adds or edits, not whole files or the repo. It answers one thing — *did your tests run the code you just touched?*\n\n*Modules:* category-search\n\n**Diff coverage:** `88%` 🟢 — `42` of `48` changed instructions covered\n\n| Metric | Value | |\n| :-- | --: | :-- |\n| 🟢 Covered instructions | `42` (88%) | changed code your tests executed |\n| šŸ”“ Missed instructions | `6` (12%) | changed code your tests never ran |\n| šŸ“ˆ Tracked changed lines | `8` (53%) | lines the coverage tool could measure |\n| ⚪ Untracked changed lines | `7` (47%) | comments, blanks, declarations |\n\n**Lines** = the source lines you changed. **Instructions** = the executable units the coverage tool counts inside those lines — one line can hold several (e.g. JaCoCo bytecode), so the two counts differ.\n\n### Coverage by file\n\n| File | Diff coverage | Covered / Missed |\n| :-- | :-: | :-: |\n| `category-search/src/main/java/com/tgt/CategorySearchApplication.java` | 🟔 73% | 8 / 3 |\n| `category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt` | 🟢 92% | 34 / 3 |\n\n3 changed file(s) with no measurable lines (config, docs, generated, or test-only) omitted.\n\n\n
šŸ” Uncovered lines (2)\n\n```\n--- category-search/src/main/java/com/tgt/CategorySearchApplication.java:52\n System.out.print(\"Something\");\n--- category-search/src/main/kotlin/com/tgt/SomeOtherClass.kt:12\n System.out.print(\"Something2\");\n```\n
\n\nšŸ¤– Generated by pull-request-code-coverage — coverage for changed lines only.\n", }) propGetter.AssertExpectations(t) @@ -355,14 +281,7 @@ func TestDefaultRunner_Run_NoChanges(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/sample_unified.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: - -Code Coverage Summary: -Lines Without Coverage Data -> 100% (9) -Lines With Coverage Data -> 0% (0) -Covered Instructions -> 100% (0) -Missed Instructions -> 0% (0) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n Modules: category-search\n\n Diff coverage: 100% 🟢 — 0 of 0 changed instructions covered\n\n Summary\n Covered instructions 100% (0)\n Missed instructions 0% (0)\n Tracked changed lines 0% (0)\n Untracked changed lines 100% (9)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n (no files with measurable lines)\n (4 file(s) with no measurable lines omitted)\n\n Uncovered lines (0)\n none šŸŽ‰\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertNoRequestsWereMade(t) @@ -393,14 +312,7 @@ func TestDefaultRunner_Run_NoChanges_Vela(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/sample_unified.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: - -Code Coverage Summary: -Lines Without Coverage Data -> 100% (9) -Lines With Coverage Data -> 0% (0) -Covered Instructions -> 100% (0) -Missed Instructions -> 0% (0) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n Modules: category-search\n\n Diff coverage: 100% 🟢 — 0 of 0 changed instructions covered\n\n Summary\n Covered instructions 100% (0)\n Missed instructions 0% (0)\n Tracked changed lines 0% (0)\n Untracked changed lines 100% (9)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n (no files with measurable lines)\n (4 file(s) with no measurable lines omitted)\n\n Uncovered lines (0)\n none šŸŽ‰\n\n──────────────────────────────────────────────────────────────\n", buf.String()) requestAsserter.AssertNoRequestsWereMade(t) @@ -428,14 +340,7 @@ func TestDefaultRunner_RunNoCoverageData(t *testing.T) { err := NewRunner().Run(propGetter.GetProperty, MustOpen(t, "../test/sample_unified.diff"), &buf) assert.NoError(t, err) - assert.Equal(t, `Missed Instructions: - -Code Coverage Summary: -Lines Without Coverage Data -> 100% (9) -Lines With Coverage Data -> 0% (0) -Covered Instructions -> 100% (0) -Missed Instructions -> 0% (0) -`, buf.String()) + assert.Equal(t, "──────────────────────────────────────────────────────────────\n šŸ“Š Patch Coverage Report — changed lines only\n──────────────────────────────────────────────────────────────\n Modules: category-search\n\n Diff coverage: 100% 🟢 — 0 of 0 changed instructions covered\n\n Summary\n Covered instructions 100% (0)\n Missed instructions 0% (0)\n Tracked changed lines 0% (0)\n Untracked changed lines 100% (9)\n\n Note: \"lines\" are the source lines you changed; \"instructions\" are the\n executable units the coverage tool counts inside them (one line can hold\n several, e.g. JaCoCo bytecode), so the two counts differ.\n\n Coverage by file (lowest coverage first)\n (no files with measurable lines)\n (4 file(s) with no measurable lines omitted)\n\n Uncovered lines (0)\n none šŸŽ‰\n\n──────────────────────────────────────────────────────────────\n", buf.String()) propGetter.AssertExpectations(t) }