@@ -30,15 +30,15 @@ export function evaluateCoverage(projects: string[], thresholds: ThresholdConfig
3030 core . info ( 'No coverage thresholds defined, skipping evaluation' ) ;
3131 return true ; // No thresholds defined, pass by default
3232 }
33-
33+
3434 let allProjectsPassed = true ;
3535 const coverageResults : ProjectCoverageResult [ ] = [ ] ;
36-
36+
3737 core . info ( `Evaluating coverage for ${ projects . length } projects` ) ;
38-
38+
3939 for ( const project of projects ) {
4040 const projectThresholds = getProjectThresholds ( project , thresholds ) ;
41-
41+
4242 // Skip projects with null thresholds
4343 if ( projectThresholds === null ) {
4444 core . info ( `Coverage evaluation skipped for ${ project } ` ) ;
@@ -50,9 +50,9 @@ export function evaluateCoverage(projects: string[], thresholds: ThresholdConfig
5050 } ) ;
5151 continue ;
5252 }
53-
53+
5454 const coveragePath = path . resolve ( process . cwd ( ) , `coverage/${ project } /coverage-summary.json` ) ;
55-
55+
5656 if ( ! fs . existsSync ( coveragePath ) ) {
5757 core . warning ( `No coverage report found for ${ project } at ${ coveragePath } ` ) ;
5858 coverageResults . push ( {
@@ -64,42 +64,42 @@ export function evaluateCoverage(projects: string[], thresholds: ThresholdConfig
6464 allProjectsPassed = false ;
6565 continue ;
6666 }
67-
67+
6868 try {
6969 const coverageData = JSON . parse ( fs . readFileSync ( coveragePath , 'utf8' ) ) ;
7070 const summary = coverageData . total as CoverageSummary ;
71-
71+
7272 let projectPassed = true ;
7373 const failedMetrics : string [ ] = [ ] ;
74-
74+
7575 // Check each metric if threshold is defined
7676 if ( projectThresholds . lines !== undefined && summary . lines . pct < projectThresholds . lines ) {
7777 projectPassed = false ;
7878 failedMetrics . push ( `lines: ${ summary . lines . pct . toFixed ( 2 ) } % < ${ projectThresholds . lines } %` ) ;
7979 }
80-
80+
8181 if ( projectThresholds . statements !== undefined && summary . statements . pct < projectThresholds . statements ) {
8282 projectPassed = false ;
8383 failedMetrics . push ( `statements: ${ summary . statements . pct . toFixed ( 2 ) } % < ${ projectThresholds . statements } %` ) ;
8484 }
85-
85+
8686 if ( projectThresholds . functions !== undefined && summary . functions . pct < projectThresholds . functions ) {
8787 projectPassed = false ;
8888 failedMetrics . push ( `functions: ${ summary . functions . pct . toFixed ( 2 ) } % < ${ projectThresholds . functions } %` ) ;
8989 }
90-
90+
9191 if ( projectThresholds . branches !== undefined && summary . branches . pct < projectThresholds . branches ) {
9292 projectPassed = false ;
9393 failedMetrics . push ( `branches: ${ summary . branches . pct . toFixed ( 2 ) } % < ${ projectThresholds . branches } %` ) ;
9494 }
95-
95+
9696 if ( ! projectPassed ) {
9797 core . error ( `Project ${ project } failed coverage thresholds: ${ failedMetrics . join ( ', ' ) } ` ) ;
9898 allProjectsPassed = false ;
9999 } else {
100100 core . info ( `Project ${ project } passed all coverage thresholds` ) ;
101101 }
102-
102+
103103 coverageResults . push ( {
104104 project,
105105 thresholds : projectThresholds ,
@@ -122,10 +122,10 @@ export function evaluateCoverage(projects: string[], thresholds: ThresholdConfig
122122 allProjectsPassed = false ;
123123 }
124124 }
125-
125+
126126 // Post results to PR comment
127127 postCoverageComment ( coverageResults ) ;
128-
128+
129129 return allProjectsPassed ;
130130}
131131
@@ -134,9 +134,15 @@ export function evaluateCoverage(projects: string[], thresholds: ThresholdConfig
134134 */
135135function formatCoverageComment ( results : ProjectCoverageResult [ ] , artifactUrl : string ) : string {
136136 let comment = '## Test Coverage Results\n\n' ;
137+
138+ if ( results . length === 0 ) {
139+ comment += 'No projects were evaluated for coverage.\n' ;
140+ return comment ;
141+ }
142+
137143 comment += '| Project | Metric | Threshold | Actual | Status |\n' ;
138144 comment += '|---------|--------|-----------|--------|--------|\n' ;
139-
145+
140146 results . forEach ( result => {
141147 if ( result . status === 'SKIPPED' ) {
142148 comment += `| ${ result . project } | All | N/A | N/A | ⏩ SKIPPED |\n` ;
@@ -147,28 +153,28 @@ function formatCoverageComment(results: ProjectCoverageResult[], artifactUrl: st
147153 metrics . forEach ( ( metric , index ) => {
148154 // Skip metrics that don't have a threshold
149155 if ( ! result . thresholds [ metric ] ) return ;
150-
156+
151157 const threshold = result . thresholds [ metric ] ;
152158 const actual = result . actual [ metric ] . toFixed ( 2 ) ;
153159 const status = actual >= threshold ? '✅ PASSED' : '❌ FAILED' ;
154-
160+
155161 // Only include project name in the first row for this project
156162 const projectCell = index === 0 ? result . project : '' ;
157-
163+
158164 comment += `| ${ projectCell } | ${ metric } | ${ threshold } % | ${ actual } % | ${ status } |\n` ;
159165 } ) ;
160166 }
161167 } ) ;
162-
168+
163169 // Add overall status
164170 const overallStatus = results . every ( r => r . status !== 'FAILED' ) ? '✅ PASSED' : '❌ FAILED' ;
165171 comment += `\n### Overall Status: ${ overallStatus } \n` ;
166-
172+
167173 // Add link to detailed HTML reports
168174 if ( artifactUrl ) {
169175 comment += `\n📊 [View Detailed HTML Coverage Reports](${ artifactUrl } )\n` ;
170176 }
171-
177+
172178 return comment ;
173179}
174180
@@ -178,12 +184,24 @@ function formatCoverageComment(results: ProjectCoverageResult[], artifactUrl: st
178184function postCoverageComment ( results : ProjectCoverageResult [ ] ) : void {
179185 // The actual artifact URL will be provided by GitHub Actions in the workflow
180186 const artifactUrl = process . env . COVERAGE_ARTIFACT_URL || '' ;
181-
187+
182188 const comment = formatCoverageComment ( results , artifactUrl ) ;
183-
189+
184190 // Write to a file that will be used by thollander/actions-comment-pull-request action
185191 const gitHubCommentsFile = path . resolve ( process . cwd ( ) , 'coverage-report.txt' ) ;
186192 fs . writeFileSync ( gitHubCommentsFile , comment ) ;
187-
193+
188194 core . info ( 'Coverage results saved for PR comment' ) ;
189195}
196+
197+ /**
198+ * Generates a coverage report when no projects are affected
199+ */
200+ export function generateEmptyCoverageReport ( ) : void {
201+ const comment = '## Test Coverage Results\n\n⏩ No projects were affected by this change that require coverage evaluation.\n' ;
202+
203+ const gitHubCommentsFile = path . resolve ( process . cwd ( ) , 'coverage-report.txt' ) ;
204+ fs . writeFileSync ( gitHubCommentsFile , comment ) ;
205+
206+ core . info ( 'Empty coverage report generated (no affected projects)' ) ;
207+ }
0 commit comments