feat: add summary to action output

This commit is contained in:
Ricardo Raposo 2025-09-18 15:26:59 +02:00
parent 34d8269ede
commit eb2310cec8
6 changed files with 38 additions and 35 deletions

View file

@ -111,6 +111,8 @@ outputs:
description: Check run URL description: Check run URL
url_html: url_html:
description: Check run URL HTML description: Check run URL HTML
summary:
description: The raw generated summary
runs: runs:
using: 'node20' using: 'node20'
main: 'dist/index.js' main: 'dist/index.js'

15
dist/index.js generated vendored
View file

@ -419,6 +419,7 @@ class TestReporter {
}); });
core.info('Summary content:'); core.info('Summary content:');
core.info(summary); core.info(summary);
core.setOutput('summary', summary);
core.summary.addRaw(`# ${shortSummary}`); core.summary.addRaw(`# ${shortSummary}`);
await core.summary.addRaw(summary).write(); await core.summary.addRaw(summary).write();
} }
@ -958,7 +959,8 @@ class DotnetTrxParser {
} }
} }
getTestClasses(trx) { getTestClasses(trx) {
if (trx.TestRun.TestDefinitions === undefined || trx.TestRun.Results === undefined || if (trx.TestRun.TestDefinitions === undefined ||
trx.TestRun.Results === undefined ||
!trx.TestRun.TestDefinitions.some(td => td.UnitTest && Array.isArray(td.UnitTest))) { !trx.TestRun.TestDefinitions.some(td => td.UnitTest && Array.isArray(td.UnitTest))) {
return []; return [];
} }
@ -974,7 +976,7 @@ class DotnetTrxParser {
})); }));
const testClasses = {}; const testClasses = {};
for (const r of unitTestsResults) { for (const r of unitTestsResults) {
const className = r.test.TestMethod[0].$.className ?? "Unclassified"; const className = r.test.TestMethod[0].$.className ?? 'Unclassified';
let tc = testClasses[className]; let tc = testClasses[className];
if (tc === undefined) { if (tc === undefined) {
tc = new TestClass(className); tc = new TestClass(className);
@ -1091,7 +1093,10 @@ class GolangJsonParser {
return this.getTestRunResult(path, events); return this.getTestRunResult(path, events);
} }
async getGolangTestEvents(path, content) { async getGolangTestEvents(path, content) {
return content.trim().split('\n').map((line, index) => { return content
.trim()
.split('\n')
.map((line, index) => {
try { try {
return JSON.parse(line); return JSON.parse(line);
} }
@ -1139,9 +1144,7 @@ class GolangJsonParser {
suite.groups.push(group); suite.groups.push(group);
} }
const lastEvent = eventGroup.at(-1); const lastEvent = eventGroup.at(-1);
const result = lastEvent.Action === 'pass' ? 'success' const result = lastEvent.Action === 'pass' ? 'success' : lastEvent.Action === 'skip' ? 'skipped' : 'failed';
: lastEvent.Action === 'skip' ? 'skipped'
: 'failed';
if (lastEvent.Elapsed === undefined) { if (lastEvent.Elapsed === undefined) {
throw new Error('missing elapsed on final test event'); throw new Error('missing elapsed on final test event');
} }

View file

@ -187,6 +187,7 @@ class TestReporter {
core.info('Summary content:') core.info('Summary content:')
core.info(summary) core.info(summary)
core.setOutput('summary', summary)
core.summary.addRaw(`# ${shortSummary}`) core.summary.addRaw(`# ${shortSummary}`)
await core.summary.addRaw(summary).write() await core.summary.addRaw(summary).write()
} else { } else {
@ -270,4 +271,4 @@ class TestReporter {
} }
} }
main() main()

View file

@ -62,8 +62,11 @@ export class DotnetTrxParser implements TestParser {
} }
private getTestClasses(trx: TrxReport): TestClass[] { private getTestClasses(trx: TrxReport): TestClass[] {
if (trx.TestRun.TestDefinitions === undefined || trx.TestRun.Results === undefined || if (
!trx.TestRun.TestDefinitions.some(td => td.UnitTest && Array.isArray(td.UnitTest))) { trx.TestRun.TestDefinitions === undefined ||
trx.TestRun.Results === undefined ||
!trx.TestRun.TestDefinitions.some(td => td.UnitTest && Array.isArray(td.UnitTest))
) {
return [] return []
} }
@ -81,7 +84,7 @@ export class DotnetTrxParser implements TestParser {
const testClasses: {[name: string]: TestClass} = {} const testClasses: {[name: string]: TestClass} = {}
for (const r of unitTestsResults) { for (const r of unitTestsResults) {
const className = r.test.TestMethod[0].$.className ?? "Unclassified" const className = r.test.TestMethod[0].$.className ?? 'Unclassified'
let tc = testClasses[className] let tc = testClasses[className]
if (tc === undefined) { if (tc === undefined) {
tc = new TestClass(className) tc = new TestClass(className)

View file

@ -1,8 +1,8 @@
import { ParseOptions, TestParser } from '../../test-parser' import {ParseOptions, TestParser} from '../../test-parser'
import { GoTestEvent } from './golang-json-types' import {GoTestEvent} from './golang-json-types'
import { getExceptionSource } from '../../utils/node-utils' import {getExceptionSource} from '../../utils/node-utils'
import { getBasePath, normalizeFilePath } from '../../utils/path-utils' import {getBasePath, normalizeFilePath} from '../../utils/path-utils'
import { import {
TestExecutionResult, TestExecutionResult,
@ -16,7 +16,7 @@ import {
export class GolangJsonParser implements TestParser { export class GolangJsonParser implements TestParser {
assumedWorkDir: string | undefined assumedWorkDir: string | undefined
constructor(readonly options: ParseOptions) { } constructor(readonly options: ParseOptions) {}
async parse(path: string, content: string): Promise<TestRunResult> { async parse(path: string, content: string): Promise<TestRunResult> {
const events = await this.getGolangTestEvents(path, content) const events = await this.getGolangTestEvents(path, content)
@ -24,13 +24,16 @@ export class GolangJsonParser implements TestParser {
} }
private async getGolangTestEvents(path: string, content: string): Promise<GoTestEvent[]> { private async getGolangTestEvents(path: string, content: string): Promise<GoTestEvent[]> {
return content.trim().split('\n').map((line, index) => { return content
try { .trim()
return JSON.parse(line) as GoTestEvent .split('\n')
} catch (e) { .map((line, index) => {
throw new Error(`Invalid JSON at ${path} line ${index + 1}\n\n${e}`) try {
} return JSON.parse(line) as GoTestEvent
}) } catch (e) {
throw new Error(`Invalid JSON at ${path} line ${index + 1}\n\n${e}`)
}
})
} }
private getTestRunResult(path: string, events: GoTestEvent[]): TestRunResult { private getTestRunResult(path: string, events: GoTestEvent[]): TestRunResult {
@ -65,7 +68,7 @@ export class GolangJsonParser implements TestParser {
let groupName: string | null let groupName: string | null
let rest: string[] let rest: string[]
[groupName, ...rest] = event.Test.split('/') ;[groupName, ...rest] = event.Test.split('/')
let testName = rest.join('/') let testName = rest.join('/')
if (!testName) { if (!testName) {
testName = groupName testName = groupName
@ -80,9 +83,8 @@ export class GolangJsonParser implements TestParser {
const lastEvent = eventGroup.at(-1)! const lastEvent = eventGroup.at(-1)!
const result: TestExecutionResult = lastEvent.Action === 'pass' ? 'success' const result: TestExecutionResult =
: lastEvent.Action === 'skip' ? 'skipped' lastEvent.Action === 'pass' ? 'success' : lastEvent.Action === 'skip' ? 'skipped' : 'failed'
: 'failed'
if (lastEvent.Elapsed === undefined) { if (lastEvent.Elapsed === undefined) {
throw new Error('missing elapsed on final test event') throw new Error('missing elapsed on final test event')
} }

View file

@ -1,12 +1,4 @@
export type GoTestAction = 'start' export type GoTestAction = 'start' | 'run' | 'pause' | 'cont' | 'pass' | 'bench' | 'fail' | 'output' | 'skip'
| 'run'
| 'pause'
| 'cont'
| 'pass'
| 'bench'
| 'fail'
| 'output'
| 'skip'
export type GoTestEvent = { export type GoTestEvent = {
Time: string Time: string