Skip to content

Commit d68c071

Browse files
committed
feat: add status check functionality
1 parent 61f8f70 commit d68c071

File tree

11 files changed

+306
-6
lines changed

11 files changed

+306
-6
lines changed

CONTRIBUTING.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ project, do one of the following:
2323
your idea, open an issue to discuss it. This allows other contributors to
2424
point out any potential flaws or to help you flesh out your idea.
2525

26+
```bash
27+
git clone https://github.com/ctrf-io/github-test-reporter.git
28+
cd github-test-reporter
29+
npm install
30+
# Add your changes
31+
npm run all:action
32+
```
33+
34+
The `all:action` script builds and tests the action and stores the built action in the
35+
`dist` directory. GitHub Marketplace actions require build files to be present in the repository.
36+
2637
### Pull Requests
2738

2839
1. Fork the repository and create your branch from `main`.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ There are several inputs available
137137
summary: true # Post report to the job summary. Default is true
138138
pull-request: false # Comment on pull request with report. Default is false
139139
issue: '' # Issue number to comment on. Works with standard issues and pull-request. Default is no issue
140+
status-check: false # Create a status check for the workflow. Default is false
141+
status-check-name: 'Test Reporter Results' # Name of the status check. Default is GitHub Test Reporter Results
140142
community-report-name: 'summary-short' # Name of the community report to use. Default is summary-short
141143
title: '' # Set a custom title to display on the report.
142144
annotate: true # Add failed test annotations. Default is true

__tests__/github/handler.test.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import * as core from '@actions/core'
2+
import { createCheckRun } from '../../src/client/github/checks'
3+
import { createStatusCheck } from '../../src/github/handler'
4+
import { CtrfReport, Inputs } from '../../src/types'
5+
6+
// Mock dependencies
7+
jest.mock('@actions/core')
8+
jest.mock('@actions/github', () => ({
9+
context: {
10+
repo: {
11+
owner: 'test-owner',
12+
repo: 'test-repo'
13+
},
14+
sha: 'test-sha'
15+
}
16+
}))
17+
jest.mock('../../src/client/github/checks', () => ({
18+
createCheckRun: jest.fn()
19+
}))
20+
21+
describe('createStatusCheck', () => {
22+
const mockCore = jest.mocked(core)
23+
const mockCreateCheckRun = jest.mocked(createCheckRun)
24+
25+
beforeEach(() => {
26+
jest.clearAllMocks()
27+
mockCore.summary.stringify.mockReturnValue('Test summary')
28+
})
29+
30+
it('should create a successful check run when no tests failed', async () => {
31+
const inputs: Inputs = {
32+
statusCheckName: 'Test Status',
33+
statusCheck: true
34+
} as Inputs
35+
36+
const report: CtrfReport = {
37+
results: {
38+
summary: {
39+
failed: 0
40+
}
41+
}
42+
} as CtrfReport
43+
44+
await createStatusCheck(inputs, report)
45+
46+
expect(mockCreateCheckRun).toHaveBeenCalledWith(
47+
'test-owner',
48+
'test-repo',
49+
'test-sha',
50+
'Test Status',
51+
'completed',
52+
'success',
53+
'Test Results',
54+
'Test summary'
55+
)
56+
})
57+
58+
it('should create a failed check run when tests failed', async () => {
59+
const inputs: Inputs = {
60+
statusCheckName: 'Test Status',
61+
statusCheck: true
62+
} as Inputs
63+
64+
const report: CtrfReport = {
65+
results: {
66+
summary: {
67+
failed: 1
68+
}
69+
}
70+
} as CtrfReport
71+
72+
await createStatusCheck(inputs, report)
73+
74+
expect(mockCreateCheckRun).toHaveBeenCalledWith(
75+
'test-owner',
76+
'test-repo',
77+
'test-sha',
78+
'Test Status',
79+
'completed',
80+
'failure',
81+
'Test Results',
82+
'Test summary'
83+
)
84+
})
85+
86+
it('should truncate summary if it exceeds 65000 characters', async () => {
87+
const longSummary = 'a'.repeat(65001)
88+
mockCore.summary.stringify.mockReturnValue(longSummary)
89+
90+
const inputs: Inputs = {
91+
statusCheckName: 'Test Status',
92+
statusCheck: true
93+
} as Inputs
94+
95+
const report: CtrfReport = {
96+
results: {
97+
summary: {
98+
failed: 0
99+
}
100+
}
101+
} as CtrfReport
102+
103+
await createStatusCheck(inputs, report)
104+
105+
expect(mockCore.warning).toHaveBeenCalledWith(
106+
'Summary is too long to create a status check. Truncating...'
107+
)
108+
expect(mockCreateCheckRun).toHaveBeenCalledWith(
109+
'test-owner',
110+
'test-repo',
111+
'test-sha',
112+
'Test Status',
113+
'completed',
114+
'success',
115+
'Test Results',
116+
expect.stringMatching(/^a{65000}$/)
117+
)
118+
})
119+
})

action.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ inputs:
111111
description: 'Add annotations to failed tests in the GitHub Actions UI.'
112112
required: false
113113
default: true
114+
status-check:
115+
description: 'Create a status check for the workflow.'
116+
required: false
117+
default: false
118+
status-check-name:
119+
description: 'Name of the status check.'
120+
required: false
121+
default: 'GitHub Test Reporter Results'
114122
community-report-name:
115123
description: 'Name of the community report to use.'
116124
required: false

badges/coverage.svg

Lines changed: 1 addition & 1 deletion
Loading

dist/index.js

Lines changed: 70 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/client/github/checks.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { createGitHubClient } from '.'
2+
3+
/**
4+
* Creates a check run for a specific commit.
5+
*
6+
* @param owner - The owner of the repository (organization or user).
7+
* @param repo - The name of the repository.
8+
* @param sha - The SHA of the commit to update.
9+
* @param name - The name of the check run.
10+
* @param status - The current status ('queued' | 'in_progress' | 'completed').
11+
* @param conclusion - The final conclusion ('success' | 'failure' | 'neutral' | 'cancelled' | 'skipped' | 'timed_out' | 'action_required').
12+
* @param title - The title of the check run.
13+
* @param summary - A summary of the check run.
14+
* @param detailsUrl - The URL of the integrator's site that has the full details of the check.
15+
*
16+
* @returns A promise that resolves to the response data from GitHub's API.
17+
*/
18+
export async function createCheckRun(
19+
owner: string,
20+
repo: string,
21+
sha: string,
22+
name: string,
23+
status: 'queued' | 'in_progress' | 'completed',
24+
conclusion?:
25+
| 'success'
26+
| 'failure'
27+
| 'neutral'
28+
| 'cancelled'
29+
| 'skipped'
30+
| 'timed_out'
31+
| 'action_required',
32+
title?: string,
33+
summary?: string,
34+
detailsUrl?: string
35+
): Promise<void> {
36+
const octokit = await createGitHubClient()
37+
await octokit.checks.create({
38+
owner,
39+
repo,
40+
head_sha: sha,
41+
name,
42+
status,
43+
conclusion,
44+
output:
45+
title && summary
46+
? {
47+
title,
48+
summary
49+
}
50+
: undefined,
51+
details_url: detailsUrl
52+
})
53+
}

src/core/inputs.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ export function getCliInputs(args: Arguments): Inputs {
4747
uploadArtifact: false,
4848
integrationsConfig: {},
4949
groupBy: groupBy,
50-
alwaysGroupBy: false
50+
alwaysGroupBy: false,
51+
statusCheck: false,
52+
statusCheckName: 'GitHub Test Reporter Results'
5153
}
5254
}
5355

@@ -113,6 +115,9 @@ export function getInputs(): Inputs {
113115
alwaysGroupBy: core.getInput('always-group-by').toLowerCase() === 'true',
114116
integrationsConfig: JSON.parse(
115117
core.getInput('integrations-config') || '{}'
116-
) as IntegrationsConfig
118+
) as IntegrationsConfig,
119+
statusCheck: core.getInput('status-check').toLowerCase() === 'true',
120+
statusCheckName:
121+
core.getInput('status-check-name') || 'Test Reporter Results'
117122
}
118123
}

0 commit comments

Comments
 (0)