Setup Code Coverage for Monorepo — SonarQube
In a Monorepo setup, generating a coverage report for each library or app separately is common.
However, tools like the Sonar scanner may encounter difficulties in combining these reports into a single comprehensive one.
This issue arises when running tests with tools like nx affected, where only affected projects generate coverage reports, leaving unaffected projects out.
Consequently, SonarQube may raise quality gate errors due to missing coverage data.
Project Structure
Propose Solution Implemented
To resolve this problem, a custom script can be added to merge coverage reports into one file.
Below is a simple JavaScript function named coveragemerger.js
for this purpose:
const glob = require('glob');
const fs = require('fs').promises;
const path = require('path');
const util = require('util');
const REPORTS_DIR_NAME = 'coverage';
const GREEN = '\x1b[32m%s\x1b[0m';
const BLUE = '\x1b[34m%s\x1b[0m';
const REPORTS_DIR_PATH = path.resolve(process.cwd(), REPORTS_DIR_NAME);
const globPromise = util.promisify(glob);
/**
* Fetches all lcov.info files from coverage directories, excluding node_modules.
* @returns {Promise<string[]>} A promise that resolves with an array of file paths.
*/
const getLcovFiles = function () {
return globPromise(`**/coverage/lcov.info`, { ignore: '**/node_modules/**' });
};
/**
* Creates a temp directory for all the reports.
* @returns {Promise<void>} A promise that resolves when the directory has been created.
*/
async function createTempDir() {
console.log(BLUE, `Creating a temp ${REPORTS_DIR_NAME} directory…`);
try {
await fs.mkdir(REPORTS_DIR_PATH, { recursive: true });
console.log(GREEN, 'Done!');
} catch (err) {
console.error('Error creating directory:', err);
}
}
(async function () {
try {
// Fetch all lcov.info files
const files = await getLcovFiles();
console.log("files are", files);
// Create temp directory
await createTempDir();
// Read all files and join their contents
const mergedReport = await Promise.all(files.map(file => fs.readFile(file, 'utf-8'))).then(contents => contents.join(''));
console.log(BLUE, `Copying the coverage report…`);
// Write the merged report to a new lcov.info file
await fs.writeFile(path.resolve(REPORTS_DIR_PATH, `lcov.info`), mergedReport);
console.log('Code coverage has been saved!');
} catch (err) {
console.error('Error:', err);
}
})();
To integrate this into your pipeline, add the following command to your Azure Pipeline file
- script: |
node coverageMerger.js
displayName: 'Merge Coverage Reports'
SonarQube Analysis Report
SonarQube Analysis — Monorepo
Reference:
use this site to check coverage from LCOV https://lcov-viewer.netlify.app/
Subscribe to my newsletter
Read articles from Vikas Yadav directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by