import { directoryExists, readJsonFile, writeJsonFile, } from '../utilities/fileutils'; import { existsSync, unlinkSync } from 'fs'; import { ensureDirSync } from 'fs-extra'; import { ProjectGraphNode } from '../core/project-graph'; import { join } from 'path'; import { appRootPath } from '@nrwl/workspace/src/utilities/app-root'; import { cacheDirectory, readCacheDirectoryProperty, } from '../utilities/cache-directory'; const resultsDir = cacheDirectory( appRootPath, readCacheDirectoryProperty(appRootPath) ); const resultsFile = join(resultsDir, 'results.json'); interface NxResults { command: string; results: { [key: string]: boolean }; } export class WorkspaceResults { public startedWithFailedProjects: boolean; private commandResults: NxResults = { command: this.command, results: {}, }; get failedProjects() { return Object.entries(this.commandResults.results) .filter(([_, result]) => !result) .map(([project]) => project); } public get hasFailure() { return Object.values(this.commandResults.results).some((result) => !result); } constructor( private command: string, private projects: Record ) { const resultsExists = existsSync(resultsFile); this.startedWithFailedProjects = false; if (resultsExists) { try { const commandResults = readJsonFile(resultsFile); this.startedWithFailedProjects = commandResults.command === command; if (this.startedWithFailedProjects) { this.commandResults = commandResults; this.invalidateOldResults(); } } catch { /** * If we got here it is likely that RESULTS_FILE is not valid JSON. * It is safe to continue, and it does not make much sense to give the * user feedback as the file will be updated automatically. */ } } } getResult(projectName: string): boolean { return this.commandResults.results[projectName]; } saveResults() { try { if (!existsSync(resultsDir)) { ensureDirSync(resultsDir); } } catch (e) { if (!directoryExists(resultsDir)) { throw new Error(`Failed to create directory: ${resultsDir}`); } } if (Object.values(this.commandResults.results).includes(false)) { writeJsonFile(resultsFile, this.commandResults); } else if (existsSync(resultsFile)) { unlinkSync(resultsFile); } } setResult(projectName: string, result: boolean) { this.commandResults.results[projectName] = result; } private invalidateOldResults() { Object.keys(this.commandResults.results).forEach((projectName) => { if (!this.projects[projectName]) { delete this.commandResults.results[projectName]; } }); } }