-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(devkit): add aggregateLog util for executor to plugin migration (n…
…rwl#26523) <!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> ## Current Behavior <!-- This is the behavior we have today --> There is no way to aggregate logs and output at the end of execution for the executor to plugin migrations ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> There should be a way to aggregate logs and output them at the end of execution Usage: ```ts // Call with the executorName that is being migrated // Make sure the log itself does not contain dynamic values // Add the project root that is being migrated aggregateLog({executorName: '@nx/vite:build', project: projectRoot, log: 'Encountered X in project.json. Do Y to handle this manually.'}) // Then in GeneratorCallback run a task return () => { flushLogs() }; ``` Example Output ![image](https://github.com/nrwl/nx/assets/12140467/9a36c855-7377-4ad5-946c-c50202d9b50c) ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
- Loading branch information
Showing
2 changed files
with
155 additions
and
0 deletions.
There are no files selected for viewing
89 changes: 89 additions & 0 deletions
89
packages/devkit/src/generators/plugin-migrations/aggregate-log-util.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { logger } from 'nx/src/devkit-exports'; | ||
import { AggregatedLog } from './aggregate-log-util'; | ||
|
||
describe(`aggregateLog utils`, () => { | ||
it('should aggregate similar logs to single log listing the affected projects', () => { | ||
// ARRANGE | ||
let spyLog = ''; | ||
jest.spyOn(logger, 'warn').mockImplementation((log) => (spyLog = log)); | ||
const aggregatedLogs = new AggregatedLog(); | ||
aggregatedLogs.addLog({ | ||
executorName: '@nx/vite:serve', | ||
log: `Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file.`, | ||
project: 'app', | ||
}); | ||
aggregatedLogs.addLog({ | ||
executorName: '@nx/vite:serve', | ||
log: `Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file.`, | ||
project: 'myapp', | ||
}); | ||
aggregatedLogs.addLog({ | ||
executorName: '@nx/vite:serve', | ||
log: `Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file.`, | ||
project: 'shop-app', | ||
}); | ||
|
||
// ACT | ||
aggregatedLogs.flushLogs(); | ||
|
||
// ASSERT | ||
expect(logger.warn).toHaveBeenCalled(); | ||
expect(spyLog).toMatchInlineSnapshot(` | ||
"[1mEncountered the following while migrating '@nx/vite:serve':[22m | ||
[1m[22m • Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file. | ||
[1mAffected Projects[22m | ||
app | ||
myapp | ||
shop-app | ||
" | ||
`); | ||
}); | ||
|
||
it('should aggregate similar logs to single log and output different logs correctly', () => { | ||
// ARRANGE | ||
let spyLog = ''; | ||
jest.spyOn(logger, 'warn').mockImplementation((log) => (spyLog = log)); | ||
const aggregatedLogs = new AggregatedLog(); | ||
aggregatedLogs.addLog({ | ||
executorName: '@nx/vite:serve', | ||
log: `Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file.`, | ||
project: 'app', | ||
}); | ||
aggregatedLogs.addLog({ | ||
executorName: '@nx/vite:build', | ||
log: `Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file.`, | ||
project: 'myapp', | ||
}); | ||
aggregatedLogs.addLog({ | ||
executorName: '@nx/vite:serve', | ||
log: `Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file.`, | ||
project: 'shop-app', | ||
}); | ||
aggregatedLogs.addLog({ | ||
executorName: '@nx/vite:serve', | ||
log: `Encountered 'AnotherValue' in project.json. You will need to copy the contents of this file to the 'config.prop' property in your Vite config file.`, | ||
project: 'shop-app', | ||
}); | ||
|
||
// ACT | ||
aggregatedLogs.flushLogs(); | ||
|
||
// ASSERT | ||
expect(logger.warn).toHaveBeenCalled(); | ||
expect(spyLog).toMatchInlineSnapshot(` | ||
"[1mEncountered the following while migrating '@nx/vite:serve':[22m | ||
[1m[22m • Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file. | ||
[1mAffected Projects[22m | ||
app | ||
shop-app | ||
• Encountered 'AnotherValue' in project.json. You will need to copy the contents of this file to the 'config.prop' property in your Vite config file. | ||
[1mAffected Projects[22m | ||
shop-app | ||
[1mEncountered the following while migrating '@nx/vite:build':[22m | ||
[1m[22m • Encountered 'proxyConfig' in project.json. You will need to copy the contents of this file to the 'server.proxy' property in your Vite config file. | ||
[1mAffected Projects[22m | ||
myapp | ||
" | ||
`); | ||
}); | ||
}); |
66 changes: 66 additions & 0 deletions
66
packages/devkit/src/generators/plugin-migrations/aggregate-log-util.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { output, logger } from 'nx/src/devkit-exports'; | ||
|
||
interface AggregateLogOptions { | ||
project: string; | ||
log: string; | ||
executorName: string; | ||
} | ||
|
||
interface AggregateLogItem { | ||
log: string; | ||
projects: Set<string>; | ||
} | ||
|
||
/** | ||
* @example | ||
* // Instantiate a new object | ||
* const migrationLogs = new AggregatedLog(); | ||
* | ||
* // Add logs | ||
* migrationLogs.addLog({executorName: '@nx/vite:build', project: 'app1', log: 'Migrate X manually'}); | ||
* | ||
* // Flush all logs | ||
* migrationLogs.flushLogs() | ||
*/ | ||
export class AggregatedLog { | ||
logs: Map<string, Map<string, AggregateLogItem>> = new Map(); | ||
|
||
addLog({ project, log, executorName }: AggregateLogOptions): void { | ||
if (!this.logs.has(executorName)) { | ||
this.logs.set(executorName, new Map()); | ||
} | ||
|
||
const executorLogs = this.logs.get(executorName); | ||
if (!executorLogs.has(log)) { | ||
executorLogs.set(log, { log, projects: new Set([project]) }); | ||
} else { | ||
const logItem = executorLogs.get(log); | ||
logItem.projects.add(project); | ||
} | ||
} | ||
|
||
reset(): void { | ||
this.logs.clear(); | ||
} | ||
|
||
flushLogs(): void { | ||
let fullLog = ''; | ||
for (const executorName of this.logs.keys()) { | ||
fullLog = `${fullLog}${output.bold( | ||
`Encountered the following while migrating '${executorName}':\r\n` | ||
)}`; | ||
for (const logItem of this.logs.get(executorName).values()) { | ||
fullLog = `${fullLog} • ${logItem.log}\r\n`; | ||
fullLog = `${fullLog} ${output.bold(`Affected Projects`)}\r\n`; | ||
fullLog = `${fullLog} ${Array.from(logItem.projects.values()).join( | ||
`\r\n ` | ||
)}`; | ||
fullLog = `${fullLog}\r\n`; | ||
} | ||
} | ||
|
||
logger.warn(fullLog); | ||
|
||
this.reset(); | ||
} | ||
} |