(result summary, maxFailures int, failuresOut string, githubJob string)
| 276 | } |
| 277 | |
| 278 | func renderMarkdown(result summary, maxFailures int, failuresOut string, githubJob string) string { |
| 279 | failures := result.Failures |
| 280 | visibleFailures := failures |
| 281 | if maxFailures > 0 && len(failures) > maxFailures { |
| 282 | visibleFailures = failures[:maxFailures] |
| 283 | } |
| 284 | packageNames := map[string]struct{}{} |
| 285 | for _, item := range failures { |
| 286 | packageNames[item.Package] = struct{}{} |
| 287 | } |
| 288 | |
| 289 | var builder strings.Builder |
| 290 | writeBuilderf(&builder, "## Go test failures (%d in %d packages)\n\n", len(failures), len(packageNames)) |
| 291 | writeBuilderf(&builder, "Duration: %s · Packages with failures: %d", formatSeconds(result.DurationSeconds), result.PackageFailureCount) |
| 292 | if githubJob != "" { |
| 293 | writeBuilderf(&builder, " · Job: %s", escapeMarkdownLine(githubJob)) |
| 294 | } |
| 295 | writeBuilderString(&builder, "\n\n") |
| 296 | writeBuilderString(&builder, "| Package | Test | Elapsed |\n") |
| 297 | writeBuilderString(&builder, "|---|---|---|\n") |
| 298 | for _, item := range visibleFailures { |
| 299 | writeBuilderf(&builder, "| %s | %s | %s |\n", |
| 300 | escapeTableCell(item.Package), |
| 301 | escapeTableCell(item.Test), |
| 302 | formatSeconds(item.Elapsed), |
| 303 | ) |
| 304 | } |
| 305 | writeBuilderString(&builder, "\n") |
| 306 | |
| 307 | for _, item := range visibleFailures { |
| 308 | output := item.Output |
| 309 | if output == "" { |
| 310 | output = "No output recorded." |
| 311 | } |
| 312 | output = strings.ReplaceAll(strings.ToValidUTF8(output, ""), "```", "``") |
| 313 | writeBuilderf(&builder, "<details>\n<summary><code>%s</code> :: <code>%s</code> (%s)</summary>\n\n", |
| 314 | html.EscapeString(item.Package), |
| 315 | html.EscapeString(item.Test), |
| 316 | formatSeconds(item.Elapsed), |
| 317 | ) |
| 318 | writeBuilderString(&builder, "```text\n") |
| 319 | writeBuilderString(&builder, output) |
| 320 | if !strings.HasSuffix(output, "\n") { |
| 321 | writeBuilderString(&builder, "\n") |
| 322 | } |
| 323 | writeBuilderString(&builder, "```\n\n</details>\n\n") |
| 324 | } |
| 325 | |
| 326 | if omitted := len(failures) - len(visibleFailures); omitted > 0 { |
| 327 | writeBuilderf(&builder, "_... and %d more failed tests omitted.", omitted) |
| 328 | if failuresOut != "" { |
| 329 | writeBuilderString(&builder, " Download the failures-only artifact for the full list.") |
| 330 | } |
| 331 | writeBuilderString(&builder, "_\n") |
| 332 | } |
| 333 | return builder.String() |
| 334 | } |
| 335 |
no test coverage detected