Skip to content

Commit a3fc6d0

Browse files
authored
refactor: adjust prefix logic (#1189)
1 parent d1e8192 commit a3fc6d0

File tree

9 files changed

+201
-12
lines changed

9 files changed

+201
-12
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import type { Tree } from '@nx/devkit';
2+
import path from 'node:path';
3+
import { readProjectConfiguration } from 'nx/src/generators/utils/project-configuration';
4+
import { afterEach, expect } from 'vitest';
5+
import { generateCodePushupConfig } from '@code-pushup/nx-plugin';
6+
import {
7+
generateWorkspaceAndProject,
8+
materializeTree,
9+
nxShowProjectJson,
10+
nxTargetProject,
11+
registerPluginInWorkspace,
12+
} from '@code-pushup/test-nx-utils';
13+
import {
14+
E2E_ENVIRONMENTS_DIR,
15+
TEST_OUTPUT_DIR,
16+
teardownTestFolder,
17+
} from '@code-pushup/test-utils';
18+
import { INLINE_PLUGIN } from '../mocks/inline-plugin.js';
19+
20+
describe('nx-plugin pluginsConfig', () => {
21+
let tree: Tree;
22+
const project = 'my-lib';
23+
const testFileDir = path.join(
24+
E2E_ENVIRONMENTS_DIR,
25+
nxTargetProject(),
26+
TEST_OUTPUT_DIR,
27+
'plugin-plugins-config',
28+
);
29+
30+
beforeEach(async () => {
31+
tree = await generateWorkspaceAndProject(project);
32+
});
33+
34+
afterEach(async () => {
35+
await teardownTestFolder(testFileDir);
36+
});
37+
38+
it('should apply pluginsConfig options to executor target', async () => {
39+
const cwd = path.join(testFileDir, 'plugins-config-applied');
40+
const binPath = 'packages/cli/src/index.ts';
41+
const configPath = '{projectRoot}/code-pushup.config.ts';
42+
const projectPrefix = 'cli';
43+
44+
// Register plugin with options in the plugins array and pluginsConfig
45+
registerPluginInWorkspace(
46+
tree,
47+
{
48+
plugin: '@code-pushup/nx-plugin',
49+
options: {
50+
config: configPath,
51+
persist: {
52+
outputDir: '.code-pushup/{projectName}',
53+
},
54+
},
55+
},
56+
{
57+
projectPrefix,
58+
bin: binPath,
59+
env: {
60+
NODE_OPTIONS: '--import tsx',
61+
TSX_TSCONFIG_PATH: 'tsconfig.base.json',
62+
},
63+
},
64+
);
65+
66+
const { root } = readProjectConfiguration(tree, project);
67+
generateCodePushupConfig(tree, root, {
68+
plugins: [
69+
{
70+
fileImports: '',
71+
codeStrings: INLINE_PLUGIN,
72+
},
73+
],
74+
});
75+
76+
await materializeTree(tree, cwd);
77+
78+
const { code, projectJson } = await nxShowProjectJson(cwd, project);
79+
expect(code).toBe(0);
80+
81+
expect(projectJson).toStrictEqual(
82+
expect.objectContaining({
83+
targets: expect.objectContaining({
84+
'code-pushup': expect.objectContaining({
85+
executor: '@code-pushup/nx-plugin:cli',
86+
options: expect.objectContaining({
87+
projectPrefix,
88+
bin: binPath,
89+
env: {
90+
NODE_OPTIONS: '--import tsx',
91+
TSX_TSCONFIG_PATH: 'tsconfig.base.json',
92+
},
93+
}),
94+
}),
95+
}),
96+
}),
97+
);
98+
});
99+
});

packages/nx-plugin/src/executors/cli/executor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export default async function runCliExecutor(
2424
dryRun,
2525
env: executorEnv,
2626
bin,
27+
projectPrefix, // Do not forward to CLI, it is handled plugin logic only
2728
...restArgs
2829
} = parseCliExecutorOptions(terminalAndExecutorOptions, normalizedContext);
2930
// this sets `CP_VERBOSE=true` on process.env
@@ -48,7 +49,7 @@ export default async function runCliExecutor(
4849
logger.warn(`DryRun execution of: ${commandString}`);
4950
} else {
5051
try {
51-
logger.debug(`Run CLI with env vars: ${loggedEnvVars}`);
52+
logger.debug(`Run CLI with env vars: ${JSON.stringify(loggedEnvVars)}`);
5253
await executeProcess({
5354
command,
5455
args,

packages/nx-plugin/src/executors/internal/config.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,11 @@ export function uploadConfig(
5050

5151
const { projectPrefix, server, apiKey, organization, project, timeout } =
5252
options;
53-
const applyPrefix = workspaceRoot === '.';
54-
const prefix = projectPrefix ? `${projectPrefix}-` : '';
53+
const applyPrefix = workspaceRoot !== '.';
54+
const prefix = projectPrefix && applyPrefix ? `${projectPrefix}-` : '';
5555

5656
const derivedProject =
57-
projectName && !project
58-
? applyPrefix
59-
? `${prefix}${projectName}`
60-
: projectName
61-
: project;
57+
projectName && !project ? `${prefix}${projectName}` : project;
6258

6359
return {
6460
...parseEnv(process.env),

packages/nx-plugin/src/executors/internal/config.unit.test.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,39 @@ describe('uploadConfig', () => {
333333
},
334334
{ workspaceRoot: 'workspaceRoot', projectName: 'my-app' },
335335
),
336-
).toEqual(expect.objectContaining({ project: 'my-app2' }));
336+
).toStrictEqual(expect.objectContaining({ project: 'my-app2' }));
337+
});
338+
339+
it('should apply projectPrefix when workspaceRoot is not "."', () => {
340+
expect(
341+
uploadConfig(
342+
{
343+
...baseUploadConfig,
344+
projectPrefix: 'cli',
345+
},
346+
{ workspaceRoot: 'workspace-root', projectName: 'models' },
347+
),
348+
).toStrictEqual(expect.objectContaining({ project: 'cli-models' }));
349+
});
350+
351+
it('should NOT apply projectPrefix when workspaceRoot is "."', () => {
352+
expect(
353+
uploadConfig(
354+
{
355+
...baseUploadConfig,
356+
projectPrefix: 'cli',
357+
},
358+
{ workspaceRoot: '.', projectName: 'models' },
359+
),
360+
).toStrictEqual(expect.objectContaining({ project: 'models' }));
361+
});
362+
363+
it('should NOT apply projectPrefix when projectPrefix is not provided', () => {
364+
expect(
365+
uploadConfig(baseUploadConfig, {
366+
workspaceRoot: 'workspace-root',
367+
projectName: 'models',
368+
}),
369+
).toStrictEqual(expect.objectContaining({ project: 'models' }));
337370
});
338371
});

packages/nx-plugin/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import { PLUGIN_NAME } from './plugin/constants.js';
12
import { createNodes, createNodesV2 } from './plugin/index.js';
23

34
// default export for nx.json#plugins
45
const plugin = {
5-
name: '@code-pushup/nx-plugin',
6+
name: PLUGIN_NAME,
67
createNodesV2,
78
// Keep for backwards compatibility with Nx < 21
89
createNodes,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export const CP_TARGET_NAME = 'code-pushup';
2+
export const PLUGIN_NAME = '@code-pushup/nx-plugin';

packages/nx-plugin/src/plugin/plugin.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
CreateNodesV2,
88
} from '@nx/devkit';
99
import { PROJECT_JSON_FILE_NAME } from '../internal/constants.js';
10+
import { PLUGIN_NAME } from './constants.js';
1011
import { createTargets } from './target/targets.js';
1112
import type { CreateNodesOptions } from './types.js';
1213
import {
@@ -15,6 +16,9 @@ import {
1516
} from './utils.js';
1617

1718
// name has to be "createNodes" to get picked up by Nx <v20
19+
/**
20+
* @deprecated
21+
*/
1822
export const createNodes: CreateNodes = [
1923
`**/${PROJECT_JSON_FILE_NAME}`,
2024
async (
@@ -23,10 +27,14 @@ export const createNodes: CreateNodes = [
2327
context: CreateNodesContext,
2428
): Promise<CreateNodesResult> => {
2529
const parsedCreateNodesOptions = createNodesOptions as CreateNodesOptions;
30+
const pluginsConfig =
31+
context.nxJsonConfiguration.pluginsConfig?.[PLUGIN_NAME] ?? {};
32+
const mergedOptions = { ...pluginsConfig, ...parsedCreateNodesOptions };
33+
2634
const normalizedContext = await normalizedCreateNodesContext(
2735
context,
2836
projectConfigurationFile,
29-
parsedCreateNodesOptions,
37+
mergedOptions,
3038
);
3139

3240
return {
@@ -47,13 +55,16 @@ export const createNodesV2: CreateNodesV2<CreateNodesOptions> = [
4755
context: CreateNodesContextV2,
4856
): Promise<CreateNodesResultV2> => {
4957
const parsedCreateNodesOptions = createNodesOptions as CreateNodesOptions;
58+
const { pluginsConfig = {} } = context.nxJsonConfiguration;
59+
const pluginsConfigObj = pluginsConfig[PLUGIN_NAME] ?? {};
60+
const mergedOptions = { ...pluginsConfigObj, ...parsedCreateNodesOptions };
5061

5162
return await Promise.all(
5263
projectConfigurationFiles.map(async projectConfigurationFile => {
5364
const normalizedContext = await normalizedCreateNodesV2Context(
5465
context,
5566
projectConfigurationFile,
56-
parsedCreateNodesOptions,
67+
mergedOptions,
5768
);
5869

5970
const result: CreateNodesResult = {

testing/test-nx-utils/src/lib/utils/nx.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,29 @@ export async function generateWorkspaceAndProject(
6565
export function registerPluginInWorkspace(
6666
tree: Tree,
6767
configuration: PluginConfiguration,
68+
pluginConfig?: Record<string, unknown>,
6869
) {
6970
const normalizedPluginConfiguration =
7071
typeof configuration === 'string'
7172
? {
7273
plugin: configuration,
7374
}
7475
: configuration;
76+
77+
const pluginName =
78+
typeof configuration === 'string' ? configuration : configuration.plugin;
79+
7580
updateJson(tree, 'nx.json', (json: NxJsonConfiguration) => ({
7681
...json,
7782
plugins: [...(json.plugins ?? []), normalizedPluginConfiguration],
83+
...(pluginConfig
84+
? {
85+
pluginsConfig: {
86+
...json.pluginsConfig,
87+
[pluginName]: pluginConfig,
88+
},
89+
}
90+
: {}),
7891
}));
7992
}
8093

testing/test-nx-utils/src/lib/utils/nx.unit.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,38 @@ describe('registerPluginInWorkspace', () => {
9191
}),
9292
);
9393
});
94+
95+
it('should register pluginsConfig when provided', () => {
96+
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
97+
98+
registerPluginInWorkspace(
99+
tree,
100+
{
101+
plugin: '@code-pushup/nx-plugin',
102+
options: { targetName: 'code-pushup' },
103+
},
104+
{
105+
projectPrefix: 'cli',
106+
bin: 'packages/cli/src/index.ts',
107+
},
108+
);
109+
110+
const nxJson = JSON.parse(tree.read('nx.json')?.toString() ?? '{}');
111+
expect(nxJson).toStrictEqual(
112+
expect.objectContaining({
113+
plugins: [
114+
{
115+
plugin: '@code-pushup/nx-plugin',
116+
options: { targetName: 'code-pushup' },
117+
},
118+
],
119+
pluginsConfig: {
120+
'@code-pushup/nx-plugin': {
121+
projectPrefix: 'cli',
122+
bin: 'packages/cli/src/index.ts',
123+
},
124+
},
125+
}),
126+
);
127+
});
94128
});

0 commit comments

Comments
 (0)