2025-09-06 04:47:32 +08:00
const fs = require ( 'fs' ) ;
const path = require ( 'path' ) ;
const baseConfig = require ( './jest.config.js' ) ;
const CODEOWNERS _MANIFEST _FILENAMES _BY _TEAM _PATH = 'codeowners-manifest/filenames-by-team.json' ;
const teamName = process . env . TEAM _NAME ;
if ( ! teamName ) {
console . error ( 'ERROR: TEAM_NAME environment variable is required' ) ;
process . exit ( 1 ) ;
}
2025-09-17 05:25:13 +08:00
const outputDir = ` ./coverage/by-team/ ${ createOwnerDirectory ( teamName ) } ` ;
2025-09-06 04:47:32 +08:00
const codeownersFilePath = path . join ( _ _dirname , CODEOWNERS _MANIFEST _FILENAMES _BY _TEAM _PATH ) ;
2025-10-07 04:09:59 +08:00
if ( ! fs . existsSync ( codeownersFilePath ) ) {
console . error ( ` Codeowners file not found at ${ codeownersFilePath } ... ` ) ;
console . error ( 'Please run: yarn codeowners-manifest first to generate the mapping file' ) ;
process . exit ( 1 ) ;
}
2025-09-06 04:47:32 +08:00
2025-10-07 04:09:59 +08:00
const codeownersData = JSON . parse ( fs . readFileSync ( codeownersFilePath , 'utf8' ) ) ;
const teamFiles = codeownersData [ teamName ] || [ ] ;
2025-09-06 04:47:32 +08:00
2025-10-07 04:09:59 +08:00
if ( teamFiles . length === 0 ) {
console . error ( ` ERROR: No files found for team " ${ teamName } " ` ) ;
console . error ( 'Available teams:' , Object . keys ( codeownersData ) . join ( ', ' ) ) ;
2025-09-06 04:47:32 +08:00
process . exit ( 1 ) ;
}
const sourceFiles = teamFiles . filter ( ( file ) => {
const ext = path . extname ( file ) ;
return (
[ '.ts' , '.tsx' , '.js' , '.jsx' ] . includes ( ext ) &&
! file . includes ( '.test.' ) &&
! file . includes ( '.spec.' ) &&
! file . includes ( '.story.' ) &&
! file . includes ( '.gen.ts' ) &&
! file . includes ( '.d.ts' ) &&
! file . endsWith ( '/types.ts' )
) ;
} ) ;
2025-10-07 04:09:59 +08:00
const testFiles = teamFiles . filter ( ( file ) => {
const ext = path . extname ( file ) ;
return [ '.ts' , '.tsx' , '.js' , '.jsx' ] . includes ( ext ) && ( file . includes ( '.test.' ) || file . includes ( '.spec.' ) ) ;
2025-09-06 04:47:32 +08:00
} ) ;
2025-10-07 04:09:59 +08:00
if ( testFiles . length === 0 ) {
console . log ( ` No test files found for team ${ teamName } ` ) ;
process . exit ( 0 ) ;
}
2025-09-06 04:47:32 +08:00
console . log (
2025-10-07 04:09:59 +08:00
` 🧪 Collecting coverage for ${ sourceFiles . length } testable files and running ${ testFiles . length } test files of ${ teamFiles . length } files owned by ${ teamName } . `
2025-09-06 04:47:32 +08:00
) ;
module . exports = {
... baseConfig ,
collectCoverage : true ,
2025-10-07 04:45:05 +08:00
coverageReporters : [ 'none' ] ,
2025-09-06 04:47:32 +08:00
coverageDirectory : '/tmp/jest-coverage-ignore' ,
coverageProvider : 'v8' ,
reporters : [
'default' ,
[
'jest-monocart-coverage' ,
{
name : ` Coverage Report - ${ teamName } owned files ` ,
outputDir : outputDir ,
2025-10-07 04:45:05 +08:00
reports : [ 'console-summary' , 'v8' , 'json' , 'lcov' ] ,
2025-10-07 21:46:51 +08:00
sourceFilter : ( coveredFile ) => sourceFiles . includes ( coveredFile ) ,
2025-09-06 04:47:32 +08:00
all : {
2025-10-07 03:54:11 +08:00
filter : ( filePath ) => sourceFiles . includes ( filePath ) ,
2025-09-06 04:47:32 +08:00
} ,
cleanCache : true ,
onEnd : ( coverageResults ) => {
console . log ( ` 📄 Coverage report saved to file:// ${ path . resolve ( outputDir ) } /index.html ` ) ;
2025-09-17 05:48:31 +08:00
// TODO: Emit coverage metrics https://github.com/grafana/grafana/issues/111208
2025-09-06 04:47:32 +08:00
} ,
} ,
] ,
] ,
testRegex : undefined ,
2025-10-07 04:09:59 +08:00
testMatch : testFiles . map ( ( file ) => ` <rootDir>/ ${ file } ` ) ,
2025-09-06 04:47:32 +08:00
} ;
2025-10-07 03:54:11 +08:00
/ * *
* Create a filesystem - safe directory structure for different owner types
* @ param { string } owner - CODEOWNERS owner ( username , team , or email )
* @ returns { string } Directory path relative to coverage / by - team /
* /
function createOwnerDirectory ( owner ) {
if ( owner . includes ( '@' ) && owner . includes ( '/' ) ) {
// Example: @grafana/dataviz-squad
const [ org , team ] = owner . substring ( 1 ) . split ( '/' ) ;
return ` teams/ ${ org } / ${ team } ` ;
} else if ( owner . startsWith ( '@' ) ) {
// Example: @jesdavpet
return ` users/ ${ owner . substring ( 1 ) } ` ;
} else {
// Example: user@domain.tld
const [ user , domain ] = owner . split ( '@' ) ;
return ` emails/ ${ user } -at- ${ domain } ` ;
}
}