Skip to content

Commit dae22a9

Browse files
committed
chore: add local eslint targets
1 parent ed01057 commit dae22a9

File tree

12 files changed

+352
-49
lines changed

12 files changed

+352
-49
lines changed

code-pushup.config.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,14 @@ import {
66
jsDocsCoreConfig,
77
jsPackagesCoreConfig,
88
lighthouseCoreConfig,
9+
loadEnv,
910
typescriptPluginConfig,
1011
} from './code-pushup.preset.js';
1112
import type { CoreConfig } from './packages/models/src/index.js';
1213
import { mergeConfigs } from './packages/utils/src/index.js';
1314

14-
// load upload configuration from environment
15-
const envSchema = z.object({
16-
CP_SERVER: z.string().url(),
17-
CP_API_KEY: z.string().min(1),
18-
CP_ORGANIZATION: z.string().min(1),
19-
CP_PROJECT: z.string().min(1),
20-
});
21-
const { data: env } = await envSchema.safeParseAsync(process.env);
22-
2315
const config: CoreConfig = {
24-
...(env && {
25-
upload: {
26-
server: env.CP_SERVER,
27-
apiKey: env.CP_API_KEY,
28-
organization: env.CP_ORGANIZATION,
29-
project: env.CP_PROJECT,
30-
},
31-
}),
32-
16+
...(await loadEnv()),
3317
plugins: [],
3418
};
3519

code-pushup.preset.ts

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/* eslint-disable @nx/enforce-module-boundaries */
2+
import 'dotenv/config';
3+
import { z } from 'zod';
24
import type {
35
CategoryConfig,
46
CoreConfig,
@@ -29,6 +31,46 @@ import typescriptPlugin, {
2931
getCategories,
3032
} from './packages/plugin-typescript/src/index.js';
3133

34+
/**
35+
* Helper function to load and validate Code PushUp environment variables for upload configuration
36+
*/
37+
export async function loadEnv() {
38+
const envSchema = z.object({
39+
CP_SERVER: z.string().url(),
40+
CP_API_KEY: z.string().min(1),
41+
CP_ORGANIZATION: z.string().min(1),
42+
CP_PROJECT: z.string().min(1),
43+
});
44+
45+
const { data: env, success } = await envSchema.safeParseAsync(process.env);
46+
47+
if (!success || !env) {
48+
return {};
49+
}
50+
const uploadConfig = {
51+
server: env.CP_SERVER,
52+
apiKey: env.CP_API_KEY,
53+
organization: env.CP_ORGANIZATION,
54+
project: env.CP_PROJECT,
55+
};
56+
return (
57+
uploadConfig.apiKey && {
58+
upload: uploadConfig,
59+
}
60+
);
61+
}
62+
63+
/**
64+
* Common exclusion patterns for JSDoc coverage
65+
*/
66+
export const jsDocsExclusionPatterns = [
67+
'!packages/**/node_modules',
68+
'!packages/**/{mocks,mock}',
69+
'!**/*.{spec,test}.ts',
70+
'!**/implementation/**',
71+
'!**/internal/**',
72+
];
73+
3274
export const jsPackagesCategories: CategoryConfig[] = [
3375
{
3476
slug: 'security',
@@ -131,8 +173,12 @@ export const coverageCategories: CategoryConfig[] = [
131173
},
132174
];
133175

134-
export const jsPackagesCoreConfig = async (): Promise<CoreConfig> => ({
135-
plugins: [await jsPackagesPlugin()],
176+
export const jsPackagesCoreConfig = async (
177+
packageJsonPath?: string,
178+
): Promise<CoreConfig> => ({
179+
plugins: [
180+
await jsPackagesPlugin(packageJsonPath ? { packageJsonPath } : undefined),
181+
],
136182
categories: jsPackagesCategories,
137183
});
138184

@@ -177,12 +223,12 @@ export const typescriptPluginConfig = async (
177223
categories: getCategories(),
178224
});
179225

226+
/**
227+
* Generates coverage configuration for Nx projects. Supports both single projects and all projects.
228+
*/
180229
export const coverageCoreConfigNx = async (
181230
projectName?: string,
182231
): Promise<CoreConfig> => {
183-
if (projectName) {
184-
throw new Error('coverageCoreConfigNx for single projects not implemented');
185-
}
186232
const targetNames = ['unit-test', 'int-test'];
187233
const targetArgs = [
188234
'-t',
@@ -195,13 +241,14 @@ export const coverageCoreConfigNx = async (
195241
await coveragePlugin({
196242
coverageToolCommand: {
197243
command: 'npx',
198-
args: [
199-
'nx',
200-
projectName ? `run --project ${projectName}` : 'run-many',
201-
...targetArgs,
202-
],
244+
args: projectName
245+
? ['nx', 'run-many', '-p', projectName, ...targetArgs]
246+
: ['nx', 'run-many', ...targetArgs],
203247
},
204-
reports: await getNxCoveragePaths(targetNames),
248+
reports: await getNxCoveragePaths(
249+
targetNames,
250+
projectName ? [projectName] : undefined,
251+
),
205252
}),
206253
],
207254
categories: coverageCategories,

nx.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
{
22
"$schema": "./node_modules/nx/schemas/nx-schema.json",
33
"targetDefaults": {
4+
"code-pushup": {
5+
"executor": "nx:run-commands",
6+
"options": {
7+
"command": "node packages/cli/src/index.ts --no-progress --verbose",
8+
"cache": true,
9+
"options": {
10+
"config": "packages/{projectName}/code-pushup.config.ts",
11+
"persist": {
12+
"filename": "{projectName}-report",
13+
"outputDir": "packages/{projectName}/.code-pushup"
14+
},
15+
"upload": {
16+
"project": "{projectName}"
17+
}
18+
},
19+
"env": {
20+
"NODE_OPTIONS": "--import tsx",
21+
"TSX_TSCONFIG_PATH": "{workspaceRoot}/tsconfig.base.json"
22+
}
23+
}
24+
},
425
"build": {
526
"dependsOn": ["^build"],
627
"inputs": ["production", "^production"],

packages/cli/code-pushup.config.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import 'dotenv/config';
2+
import {
3+
coverageCoreConfigNx,
4+
eslintCoreConfigNx,
5+
jsDocsCoreConfig,
6+
jsDocsExclusionPatterns,
7+
jsPackagesCoreConfig,
8+
loadEnv,
9+
typescriptPluginConfig,
10+
} from '../../code-pushup.preset.js';
11+
import type { CoreConfig } from '../../packages/models/src/index.js';
12+
import { mergeConfigs } from '../../packages/utils/src/index.js';
13+
14+
const projectName = process.env.CP_PROJECT_NAME || 'cli';
15+
16+
const config: CoreConfig = {
17+
...(await loadEnv()),
18+
persist: {
19+
filename: `${projectName}-report`,
20+
outputDir: `packages/${projectName}/.code-pushup`,
21+
},
22+
plugins: [],
23+
};
24+
25+
export default mergeConfigs(
26+
config,
27+
await coverageCoreConfigNx(projectName),
28+
await jsPackagesCoreConfig('package.json'), // Use workspace root package.json
29+
await typescriptPluginConfig({
30+
tsconfig: `packages/${projectName}/tsconfig.lib.json`,
31+
}),
32+
await eslintCoreConfigNx(projectName),
33+
jsDocsCoreConfig([
34+
`packages/${projectName}/src/**/*.ts`,
35+
...jsDocsExclusionPatterns,
36+
]),
37+
);

packages/cli/project.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
"sourceRoot": "packages/cli/src",
55
"projectType": "library",
66
"targets": {
7+
"code-pushup": {
8+
"options": {
9+
"config": "packages/cli/code-pushup.config.ts"
10+
},
11+
"env": {
12+
"TSX_TSCONFIG_PATH": "../../tsconfig.base.json"
13+
}
14+
},
715
"build": {
816
"executor": "@nx/js:tsc",
917
"outputs": ["{options.outputPath}"],
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import 'dotenv/config';
2+
import {
3+
coverageCoreConfigNx,
4+
eslintCoreConfigNx,
5+
jsDocsCoreConfig,
6+
jsDocsExclusionPatterns,
7+
jsPackagesCoreConfig,
8+
loadEnv,
9+
typescriptPluginConfig,
10+
} from '../../code-pushup.preset.js';
11+
import type { CoreConfig } from '../../packages/models/src/index.js';
12+
import { mergeConfigs } from '../../packages/utils/src/index.js';
13+
14+
const projectName = process.env.CP_PROJECT_NAME || 'core';
15+
16+
const config: CoreConfig = {
17+
...(await loadEnv()),
18+
persist: {
19+
filename: `${projectName}-report`,
20+
outputDir: `packages/${projectName}/.code-pushup`,
21+
},
22+
plugins: [],
23+
};
24+
25+
export default mergeConfigs(
26+
config,
27+
await coverageCoreConfigNx(projectName),
28+
await jsPackagesCoreConfig('package.json'), // Use workspace root package.json
29+
await typescriptPluginConfig({
30+
tsconfig: `packages/${projectName}/tsconfig.lib.json`,
31+
}),
32+
await eslintCoreConfigNx(projectName),
33+
jsDocsCoreConfig([
34+
`packages/${projectName}/src/**/*.ts`,
35+
...jsDocsExclusionPatterns,
36+
]),
37+
);

packages/core/project.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
"sourceRoot": "packages/core/src",
55
"projectType": "library",
66
"targets": {
7+
"code-pushup": {
8+
"options": {
9+
"config": "packages/core/code-pushup.config.ts"
10+
},
11+
"env": {
12+
"TSX_TSCONFIG_PATH": "../../tsconfig.base.json"
13+
}
14+
},
715
"build": {
816
"executor": "@nx/js:tsc",
917
"outputs": ["{options.outputPath}"],
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import 'dotenv/config';
2+
import {
3+
coverageCoreConfigNx,
4+
eslintCoreConfigNx,
5+
jsDocsCoreConfig,
6+
jsDocsExclusionPatterns,
7+
jsPackagesCoreConfig,
8+
loadEnv,
9+
typescriptPluginConfig,
10+
} from '../../code-pushup.preset.js';
11+
import type { CoreConfig } from '../../packages/models/src/index.js';
12+
import { mergeConfigs } from '../../packages/utils/src/index.js';
13+
14+
const projectName = process.env.CP_PROJECT_NAME || 'models';
15+
16+
const config: CoreConfig = {
17+
...(await loadEnv()),
18+
persist: {
19+
filename: `${projectName}-report`,
20+
outputDir: `packages/${projectName}/.code-pushup`,
21+
},
22+
plugins: [],
23+
};
24+
25+
export default mergeConfigs(
26+
config,
27+
await coverageCoreConfigNx(projectName),
28+
await jsPackagesCoreConfig('package.json'), // Use workspace root package.json
29+
await typescriptPluginConfig({
30+
tsconfig: `packages/${projectName}/tsconfig.lib.json`,
31+
}),
32+
await eslintCoreConfigNx(projectName),
33+
jsDocsCoreConfig([
34+
`packages/${projectName}/src/**/*.ts`,
35+
...jsDocsExclusionPatterns,
36+
]),
37+
);

packages/models/project.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44
"sourceRoot": "packages/models/src",
55
"projectType": "library",
66
"targets": {
7+
"code-pushup": {
8+
"outputs": ["{options.outputPath}"],
9+
"cache": true,
10+
"options": {
11+
"config": "packages/models/code-pushup.config.ts",
12+
"outputPath": "packages/models/.code-pushup"
13+
},
14+
"env": {
15+
"TSX_TSCONFIG_PATH": "../../tsconfig.base.json"
16+
}
17+
},
718
"build": {
819
"dependsOn": [{ "projects": "models-transformers", "target": "build" }],
920
"executor": "@nx/js:tsc",

packages/plugin-coverage/src/lib/nx/coverage-paths.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ import { importModule, ui } from '@code-pushup/utils';
1212
import type { CoverageResult } from '../config.js';
1313

1414
/**
15+
* Gathers coverage paths from Nx projects. Filters by specific projects when provided.
1516
* @param targets nx targets to be used for measuring coverage, test by default
17+
* @param projects optional array of project names to filter results for specific projects
18+
* @param verbose optional verbose logging
1619
* @returns An array of coverage result information for the coverage plugin.
1720
*/
1821
export async function getNxCoveragePaths(
1922
targets: string[] = ['test'],
23+
projects?: string[],
2024
verbose?: boolean,
2125
): Promise<CoverageResult[]> {
2226
if (verbose) {
@@ -30,8 +34,10 @@ export async function getNxCoveragePaths(
3034

3135
const coverageResults = await Promise.all(
3236
targets.map(async target => {
33-
const relevantNodes = Object.values(nodes).filter(graph =>
34-
hasNxTarget(graph, target),
37+
const relevantNodes = Object.values(nodes).filter(
38+
graph =>
39+
hasNxTarget(graph, target) &&
40+
(projects ? projects.includes(graph.name) : true),
3541
);
3642

3743
return await Promise.all(
@@ -162,7 +168,7 @@ export async function getCoveragePathForJest(
162168
options: JestExecutorOptions,
163169
project: ProjectConfiguration,
164170
target: string,
165-
) {
171+
): Promise<CoverageResult> {
166172
const { jestConfig } = options;
167173

168174
const testConfig = await importModule<JestCoverageConfig>({
@@ -186,7 +192,13 @@ export async function getCoveragePathForJest(
186192
}
187193

188194
if (path.isAbsolute(coverageDirectory)) {
189-
return path.join(coverageDirectory, 'lcov.info');
195+
return {
196+
pathToProject: project.root,
197+
resultsPath: path.join(coverageDirectory, 'lcov.info'),
198+
};
190199
}
191-
return path.join(project.root, coverageDirectory, 'lcov.info');
200+
return {
201+
pathToProject: project.root,
202+
resultsPath: path.join(project.root, coverageDirectory, 'lcov.info'),
203+
};
192204
}

0 commit comments

Comments
 (0)