diff --git a/.github/workflows/code-pushup-fork.yml b/.github/workflows/code-pushup-fork.centralized.yml similarity index 79% rename from .github/workflows/code-pushup-fork.yml rename to .github/workflows/code-pushup-fork.centralized.yml index 27d9c04e0..7276391e3 100644 --- a/.github/workflows/code-pushup-fork.yml +++ b/.github/workflows/code-pushup-fork.centralized.yml @@ -1,4 +1,4 @@ -name: Code PushUp (fork) +name: Code PushUp - Standalone Mode (fork) # separated from code-pushup.yml for security reasons # => requires permissions to create PR comment @@ -20,19 +20,23 @@ permissions: jobs: code-pushup: runs-on: ubuntu-latest - name: Code PushUp + name: Run Code PushUp (fork) if: github.event.pull_request.head.repo.fork steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version-file: .nvmrc cache: npm + - name: Set base and head for Nx affected commands + uses: nrwl/nx-set-shas@v4 - name: Install dependencies run: npm ci - name: Run Code PushUp action uses: code-pushup/github-action@v0 with: - bin: npx nx code-pushup -- + bin: npx nx code-pushup --nx-bail -- diff --git a/.github/workflows/code-pushup-fork.monorepo.yml b/.github/workflows/code-pushup-fork.monorepo.yml new file mode 100644 index 000000000..13ecc69c2 --- /dev/null +++ b/.github/workflows/code-pushup-fork.monorepo.yml @@ -0,0 +1,44 @@ +name: Code PushUp - Monorepo/Cache (fork) + +# separated from code-pushup.yml for security reasons +# => requires permissions to create PR comment +# => for PRs from forks, needs to run on `pull_request_target`, not `pull_request` +# => `pull_request_target` is a security risk when secrets are being used +# => secrets needed for code-pushup upload +# => code-pushup for forks runs in separate workflow with no secrets access + +on: + pull_request_target: + branches: [main] + +env: + NX_NON_NATIVE_HASHER: true + +permissions: + pull-requests: write + +jobs: + code-pushup: + runs-on: ubuntu-latest + name: Run monorepo layout with caching + if: github.event.pull_request.head.repo.fork + steps: + - name: Checkout PR head + uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} + fetch-depth: 0 + - name: Derive Nx SHAs + uses: nrwl/nx-set-shas@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + cache: npm + - name: Install dependencies + run: npm ci + - name: Run Code PushUp action + uses: code-pushup/github-action@v0 + with: + bin: npx nx affected -t code-pushup -- diff --git a/.github/workflows/code-pushup.yml b/.github/workflows/code-pushup.centralized.yml similarity index 78% rename from .github/workflows/code-pushup.yml rename to .github/workflows/code-pushup.centralized.yml index aaa929329..21d7bce27 100644 --- a/.github/workflows/code-pushup.yml +++ b/.github/workflows/code-pushup.centralized.yml @@ -1,4 +1,4 @@ -name: Code PushUp +name: Code PushUp - Standalone Mode on: push: @@ -16,7 +16,7 @@ permissions: jobs: code-pushup: runs-on: ubuntu-latest - name: Code PushUp + name: Run Code PushUp # ignore PRs from forks, handled by code-pushup-fork.yml if: ${{ !github.event.pull_request.head.repo.fork }} env: @@ -27,14 +27,18 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version-file: .nvmrc cache: npm + - name: Set base and head for Nx affected commands + uses: nrwl/nx-set-shas@v4 - name: Install dependencies run: npm ci - name: Run Code PushUp action uses: code-pushup/github-action@v0 with: - bin: npx nx code-pushup -- + bin: npx nx code-pushup --nx-bail -- diff --git a/.github/workflows/code-pushup.monorepo.yml b/.github/workflows/code-pushup.monorepo.yml new file mode 100644 index 000000000..dc85ca3a4 --- /dev/null +++ b/.github/workflows/code-pushup.monorepo.yml @@ -0,0 +1,45 @@ +name: Code PushUp - Monorepo/Cache + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + NX_NON_NATIVE_HASHER: true + +permissions: + pull-requests: write + +jobs: + code-pushup: + runs-on: ubuntu-latest + name: Run monorepo layout with caching + # ignore PRs from forks, handled by code-pushup-fork.yml + if: ${{ !github.event.pull_request.head.repo.fork }} + env: + CP_SERVER: ${{ secrets.CP_SERVER }} + CP_API_KEY: ${{ secrets.CP_API_KEY }} + CP_ORGANIZATION: code-pushup + CP_PROJECT: cli + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Derive Nx SHAs + uses: nrwl/nx-set-shas@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + cache: npm + - name: Install dependencies + run: npm ci + - name: Run Code PushUp action + uses: code-pushup/github-action@v0 + with: + bin: npx nx affected -t code-pushup -- + monorepo: nx + parallel: 3 diff --git a/.prettierignore b/.prettierignore index 4ee7dc0ac..c2e007510 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,3 +3,6 @@ /coverage /.nx __snapshots__ + +/.nx/cache +/.nx/workspace-data \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e8c8e23a5..b0b9cc487 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,6 +69,41 @@ You can control the execution of long-running tests over the `INCLUDE_SLOW_TESTS To change this setup, open (or create) the `.env` file in the root folder. Edit or add the environment variable there as follows: `INCLUDE_SLOW_TESTS=true`. +### Testing with pkg-new + +You can test the CLI using published packages from pull requests via [pkg-new](https://pkg.pr.new/). This is useful for testing changes before they are merged. + +To test a specific PR (replace `` with the actual PR number): + +```bash +# Install required dependencies first +npm install \ + https://pkg.pr.new/code-pushup/cli/@code-pushup/utils@ \ + https://pkg.pr.new/code-pushup/cli/@code-pushup/models@ \ + https://pkg.pr.new/code-pushup/cli/@code-pushup/core@ \ + https://pkg.pr.new/code-pushup/cli/@code-pushup/cli@ +``` + +Update nx.json to use pkg-new: + +```jsonc +{ + "targetDefaults": { + "code-pushup": { + "executor": "nx:run-commands", + "options": { + "command": "npx https://pkg.pr.new/code-pushup/cli/@code-pushup/cli@", // instead of "command": "node packages/cli/src/index.ts" + "args": [ + // ... + ], + }, + }, + }, +} +``` + +**Note:** The `@code-pushup/portal-client` package may not be available via pkg-new, but it's an optional peer dependency and won't affect collect functionality. Only the upload command is not working. + ## Git Commit messages must follow [conventional commits](https://conventionalcommits.org/) format. diff --git a/code-pushup.central.config.ts b/code-pushup.central.config.ts new file mode 100644 index 000000000..955767acf --- /dev/null +++ b/code-pushup.central.config.ts @@ -0,0 +1,46 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsPackagesCoreConfig, + lighthouseCoreConfig, + loadEnv, + typescriptPluginConfig, +} from './code-pushup.preset.js'; +import type { CoreConfig } from './packages/models/src/index.js'; +import { mergeConfigs } from './packages/utils/src/index.js'; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +const merged = mergeConfigs( + config, + await coverageCoreConfigNx('cli'), + await jsPackagesCoreConfig(), + await lighthouseCoreConfig( + 'https://github.com/code-pushup/cli?tab=readme-ov-file#code-pushup-cli/', + ), + await typescriptPluginConfig({ + tsconfig: 'packages/cli/tsconfig.lib.json', + }), + + await eslintCoreConfigNx(), + jsDocsCoreConfig([ + 'packages/**/src/**/*.ts', + '!packages/**/node_modules', + '!packages/**/{mocks,mock}', + '!**/*.{spec,test}.ts', + '!**/implementation/**', + '!**/internal/**', + ]), +); + +export default { + ...merged, + categories: merged.categories?.filter( + c => c.slug !== 'bug-prevention' && c.slug !== 'code-style', + ), +} satisfies CoreConfig; diff --git a/code-pushup.config.ts b/code-pushup.config.ts index b9234bacd..70160b423 100644 --- a/code-pushup.config.ts +++ b/code-pushup.config.ts @@ -1,55 +1,29 @@ import 'dotenv/config'; -import { z } from 'zod'; import { - coverageCoreConfigNx, - eslintCoreConfigNx, - jsDocsCoreConfig, jsPackagesCoreConfig, lighthouseCoreConfig, - typescriptPluginConfig, } from './code-pushup.preset.js'; import type { CoreConfig } from './packages/models/src/index.js'; import { mergeConfigs } from './packages/utils/src/index.js'; -// load upload configuration from environment -const envSchema = z.object({ - CP_SERVER: z.string().url(), - CP_API_KEY: z.string().min(1), - CP_ORGANIZATION: z.string().min(1), - CP_PROJECT: z.string().min(1), -}); -const { data: env } = await envSchema.safeParseAsync(process.env); +const project = process.env['NX_TASK_TARGET_PROJECT'] || 'cli-workspace'; const config: CoreConfig = { - ...(env && { + ...(process.env['CP_API_KEY'] && { upload: { - server: env.CP_SERVER, - apiKey: env.CP_API_KEY, - organization: env.CP_ORGANIZATION, - project: 'cli-workspace', + project, + organization: 'code-pushup', + server: 'https://api.staging.code-pushup.dev/graphql', + apiKey: process.env['CP_API_KEY'], }, }), - plugins: [], }; export default mergeConfigs( config, - await coverageCoreConfigNx(), await jsPackagesCoreConfig(), await lighthouseCoreConfig( 'https://github.com/code-pushup/cli?tab=readme-ov-file#code-pushup-cli/', ), - await typescriptPluginConfig({ - tsconfig: 'packages/cli/tsconfig.lib.json', - }), - await eslintCoreConfigNx(), - jsDocsCoreConfig([ - 'packages/**/src/**/*.ts', - '!packages/**/node_modules', - '!packages/**/{mocks,mock}', - '!**/*.{spec,test}.ts', - '!**/implementation/**', - '!**/internal/**', - ]), ); diff --git a/code-pushup.preset.ts b/code-pushup.preset.ts index 0b033bcd8..40be0ac5f 100644 --- a/code-pushup.preset.ts +++ b/code-pushup.preset.ts @@ -1,13 +1,18 @@ /* eslint-disable @nx/enforce-module-boundaries */ +import 'dotenv/config'; +import { z } from 'zod'; import type { CategoryConfig, CoreConfig, + PersistConfig, + PluginConfig, + UploadConfig, } from './packages/models/src/index.js'; import coveragePlugin, { getNxCoveragePaths, } from './packages/plugin-coverage/src/index.js'; import eslintPlugin, { - eslintConfigFromNxProject, + eslintConfigFromAllNxProjects, } from './packages/plugin-eslint/src/index.js'; import type { ESLintTarget } from './packages/plugin-eslint/src/lib/config.js'; import { nxProjectsToConfig } from './packages/plugin-eslint/src/lib/nx/projects-to-config.js'; @@ -131,15 +136,21 @@ export const coverageCategories: CategoryConfig[] = [ }, ]; -export const jsPackagesCoreConfig = async (): Promise => ({ - plugins: [await jsPackagesPlugin()], +export const jsPackagesCoreConfig = async ( + packageJsonPath?: string, +): Promise => ({ + plugins: [ + await jsPackagesPlugin(packageJsonPath ? { packageJsonPath } : undefined), + ], categories: jsPackagesCategories, }); export const lighthouseCoreConfig = async ( urls: LighthouseUrls, ): Promise => { - const lhPlugin = await lighthousePlugin(urls); + const lhPlugin = await lighthousePlugin(urls, { + onlyAudits: ['largest-contentful-paint'], + }); return { plugins: [lhPlugin], categories: mergeLighthouseCategories(lhPlugin, lighthouseCategories), @@ -172,11 +183,12 @@ export const eslintCoreConfigNx = async ( projectName?: string, ): Promise => ({ plugins: [ - await eslintPlugin( - await (projectName - ? eslintConfigFromNxProject(projectName) - : eslintConfigFromPublishableNxProjects()), - ), + projectName + ? await eslintPlugin({ + eslintrc: `packages/${projectName}/eslint.config.js`, + patterns: ['.'], + }) + : await eslintPlugin(await eslintConfigFromAllNxProjects()), ], categories: eslintCategories, }); @@ -188,11 +200,27 @@ export const typescriptPluginConfig = async ( categories: getCategories(), }); +/** + * Generates coverage configuration for Nx projects. Supports both single projects and all projects. + */ export const coverageCoreConfigNx = async ( - projectName?: string, + projectArg?: + | string + | { + projectName?: string; + targetNames?: string | string[]; + }, ): Promise => { - const targetNames = ['unit-test', 'int-test']; - const targetArgs = ['-t', ...targetNames]; + const { projectName, targetNames } = + typeof projectArg === 'string' + ? { projectName: projectArg } + : (projectArg ?? {}); + const parsedTargetNames = Array.isArray(targetNames) + ? targetNames + : targetNames != null + ? [targetNames] + : ['unit-test', 'int-test']; + const targetArgs = ['-t', parsedTargetNames.join(',')]; return { plugins: [ await coveragePlugin({ @@ -215,3 +243,148 @@ export const coverageCoreConfigNx = async ( categories: coverageCategories, }; }; + +export function mergeConfigs( + config: CoreConfig, + ...configs: Partial[] +): CoreConfig { + return configs.reduce( + (acc, obj) => ({ + ...acc, + ...mergeCategories(acc.categories, obj.categories), + ...mergePlugins(acc.plugins, obj.plugins), + ...mergePersist(acc.persist, obj.persist), + ...mergeUpload(acc.upload, obj.upload), + }), + config, + ); +} + +function mergeCategories( + a: CategoryConfig[] | undefined, + b: CategoryConfig[] | undefined, +): Pick { + if (!a && !b) { + return {}; + } + + const mergedMap = new Map(); + + const addToMap = (categories: CategoryConfig[]) => { + categories.forEach(newObject => { + if (mergedMap.has(newObject.slug)) { + const existingObject: CategoryConfig | undefined = mergedMap.get( + newObject.slug, + ); + + mergedMap.set(newObject.slug, { + ...existingObject, + ...newObject, + + refs: mergeByUniqueCategoryRefCombination( + existingObject?.refs, + newObject.refs, + ), + }); + } else { + mergedMap.set(newObject.slug, newObject); + } + }); + }; + + if (a) { + addToMap(a); + } + if (b) { + addToMap(b); + } + + // Convert the map back to an array + return { categories: [...mergedMap.values()] }; +} + +function mergePlugins( + a: PluginConfig[] | undefined, + b: PluginConfig[] | undefined, +): Pick { + if (!a && !b) { + return { plugins: [] }; + } + + const mergedMap = new Map(); + + const addToMap = (plugins: PluginConfig[]) => { + plugins.forEach(newObject => { + mergedMap.set(newObject.slug, newObject); + }); + }; + + if (a) { + addToMap(a); + } + if (b) { + addToMap(b); + } + + return { plugins: [...mergedMap.values()] }; +} + +function mergePersist( + a: PersistConfig | undefined, + b: PersistConfig | undefined, +): Pick { + if (!a && !b) { + return {}; + } + + if (a) { + return b ? { persist: { ...a, ...b } } : { persist: a }; + } else { + return { persist: b }; + } +} + +function mergeByUniqueCategoryRefCombination< + T extends { slug: string; type: string; plugin: string }, +>(a: T[] | undefined, b: T[] | undefined) { + const map = new Map(); + + const addToMap = (refs: T[]) => { + refs.forEach(ref => { + const uniqueIdentification = `${ref.type}:${ref.plugin}:${ref.slug}`; + if (map.has(uniqueIdentification)) { + map.set(uniqueIdentification, { + ...map.get(uniqueIdentification), + ...ref, + }); + } else { + map.set(uniqueIdentification, ref); + } + }); + }; + + // Add objects from both arrays to the map + if (a) { + addToMap(a); + } + if (b) { + addToMap(b); + } + + return [...map.values()]; +} + +function mergeUpload( + a: UploadConfig | undefined, + b: UploadConfig | undefined, +): Pick { + if (!a && !b) { + return {}; + } + + if (a) { + return b ? { upload: { ...a, ...b } } : { upload: a }; + } else { + return { upload: b }; + } +} diff --git a/e2e/create-cli-e2e/project.json b/e2e/create-cli-e2e/project.json index bf0b88071..b09bdce91 100644 --- a/e2e/create-cli-e2e/project.json +++ b/e2e/create-cli-e2e/project.json @@ -1,7 +1,7 @@ { "name": "create-cli-e2e", "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "examples/create-cli-e2e/src", + "sourceRoot": "e2e/create-cli-e2e/src", "projectType": "application", "targets": { "lint": {}, diff --git a/eslint.config.js b/eslint.config.js index 5830ca0f7..456cfea4f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -27,6 +27,8 @@ export default tseslint.config( String.raw`^.*/eslint(\.base)?\.config\.[cm]?js$`, String.raw`^.*/code-pushup\.(config|preset)(\.m?[jt]s)?$`, '^[./]+/tools/.*$', + '^@code-pushup/test-utils(|/.*)$', + '^@code-pushup/test-nx-utils(|/.*)$', ], depConstraints: [ { diff --git a/examples/plugins/project.json b/examples/plugins/project.json index 1370e0782..10c75f0ba 100644 --- a/examples/plugins/project.json +++ b/examples/plugins/project.json @@ -1,6 +1,6 @@ { "name": "examples-plugins", - "$schema": "../../node_modules/nx/schemas/project-schema.json", + "$schema": "../node_modules/nx/schemas/project-schema.json", "sourceRoot": "examples/plugins/src", "projectType": "library", "targets": { diff --git a/examples/plugins/tsconfig.lib.json b/examples/plugins/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/examples/plugins/tsconfig.lib.json +++ b/examples/plugins/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/nx.json b/nx.json index a472f35ed..46234ce0a 100644 --- a/nx.json +++ b/nx.json @@ -1,6 +1,222 @@ { "$schema": "./node_modules/nx/schemas/nx-schema.json", + "namedInputs": { + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "production": [ + "default", + "!{projectRoot}/README.md", + "!{projectRoot}/CHANGELOG.md", + "!{projectRoot}/perf/**/*", + "!{projectRoot}/tools/**/*", + "!{projectRoot}/zod2md.config.ts", + "!{projectRoot}/eslint.config.?(c)js", + "!{workspaceRoot}/**/.code-pushup/**/*", + "!{projectRoot}/code-pushup.config.?(*.).?(m)[jt]s", + "!{projectRoot}/@(test|mocks|mock)/**/*", + "!{projectRoot}/**/?(*.)test.[jt]s?(x)?(.snap)", + "!{projectRoot}/**/?(*.)mocks.[jt]s?(x)", + "!{projectRoot}/**/?(*.)mock.[jt]s?(x)", + "!{projectRoot}/vitest.@(unit|int|e2e).config.[jt]s", + "!{projectRoot}/dist/**/*", + "!{projectRoot}/tsconfig.@(test|tools).json", + "!{workspaceRoot}/**/(*.)coverage/**/*" + ], + "test-vitest-inputs": [ + "default", + { + "externalDependencies": ["vitest"] + } + ], + "lint-eslint-inputs": [ + "default", + { + "externalDependencies": ["eslint"] + } + ], + "typecheck-typescript-inputs": [ + "default", + { + "externalDependencies": ["typescript"] + } + ], + "code-pushup-inputs": [ + "default", + { + "env": "NODE_OPTIONS" + }, + { + "env": "TSX_TSCONFIG_PATH" + } + ], + "sharedGlobals": [ + { + "runtime": "npm --version" + }, + { + "runtime": "node --version" + } + ] + }, "targetDefaults": { + "code-pushup": { + "cache": true, + "outputs": [ + "{projectRoot}/.code-pushup/report.md", + "{projectRoot}/.code-pushup/report.json" + ], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.read", + "--persist.outputDir={projectRoot}/.code-pushup", + "--upload.project=cli-{projectName}" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-coverage": { + "cache": true, + "outputs": ["{projectRoot}/.code-pushup/coverage"], + "executor": "nx:run-commands", + "dependsOn": ["unit-test", "int-test"], + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=coverage", + "--persist.skipReports=true", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-eslint": { + "cache": true, + "inputs": ["default", "^default", "{projectRoot}/eslint.config.?(c)js"], + "outputs": ["{projectRoot}/.code-pushup/eslint"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=eslint", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-js-packages": { + "cache": false, + "inputs": [ + "default", + "^default", + "{projectRoot}/package.json", + { "runtime": "echo $(($(date +%s) / 6))" } + ], + "outputs": ["{projectRoot}/.code-pushup/js-packages"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=js-packages", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-lighthouse": { + "cache": true, + "outputs": ["{projectRoot}/.code-pushup/lighthouse"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=lighthouse", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-jsdocs": { + "cache": true, + "inputs": ["default", "^default", "{projectRoot}/tsconfig.lib.json"], + "outputs": ["{projectRoot}/.code-pushup/jsdocs"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=jsdocs", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-typescript": { + "cache": true, + "inputs": ["default", "^default", "{projectRoot}/tsconfig.lib.json"], + "outputs": ["{projectRoot}/.code-pushup/typescript"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=typescript", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, "build": { "dependsOn": ["^build"], "inputs": ["production", "^production"], @@ -22,7 +238,6 @@ "executor": "@nx/vite:test", "options": { "configFile": "{projectRoot}/vitest.unit.config.ts", - "passWithNoTests": true, "coverage": { "enabled": true } @@ -34,13 +249,16 @@ "executor": "@nx/vite:test", "options": { "configFile": "{projectRoot}/vitest.int.config.ts", - "passWithNoTests": true, "coverage": { "enabled": true } } }, - "e2e": { "dependsOn": ["^build"] }, + "e2e": { + "dependsOn": ["^build"], + "inputs": ["default"], + "cache": true + }, "lint": { "inputs": ["default", "{workspaceRoot}/eslint.config.?(c)js"], "executor": "@nx/eslint:lint", @@ -76,12 +294,170 @@ }, "@nx/vite:test": { "cache": true, - "inputs": ["default", "^production"], + "inputs": ["test-vitest-inputs"], "options": { "passWithNoTests": true, "watch": false } }, + "code-pushup": { + "cache": false, + "outputs": [ + "{projectRoot}/.code-pushup/report.md", + "{projectRoot}/.code-pushup/report.json" + ], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.read", + "--persist.outputDir={projectRoot}/.code-pushup", + "--upload.project=cli-{projectName}" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-coverage": { + "cache": true, + "inputs": ["code-pushup-inputs", "test-vitest-inputs"], + "outputs": ["{projectRoot}/.code-pushup/coverage/runner-output.json"], + "executor": "nx:run-commands", + "dependsOn": ["*-test"], + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=coverage", + "--persist.skipReports=true", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-eslint": { + "cache": true, + "inputs": ["code-pushup-inputs", "lint-eslint-inputs"], + "outputs": ["{projectRoot}/.code-pushup/eslint/runner-output.json"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=eslint", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-js-packages": { + "cache": false, + "inputs": [ + { + "runtime": "date +%Y-%m-%d" + } + ], + "outputs": ["{projectRoot}/.code-pushup/js-packages/runner-output.json"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--onlyPlugins=js-packages", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-lighthouse": { + "cache": true, + "inputs": ["code-pushup-inputs", "production", "^production"], + "outputs": ["{projectRoot}/.code-pushup/lighthouse/runner-output.json"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=lighthouse", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-jsdocs": { + "cache": true, + "inputs": ["code-pushup-inputs", "typecheck-typescript-inputs"], + "outputs": ["{projectRoot}/.code-pushup/jsdocs/runner-output.json"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=jsdocs", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, + "code-pushup-typescript": { + "cache": true, + "inputs": ["code-pushup-inputs", "typecheck-typescript-inputs"], + "outputs": ["{projectRoot}/.code-pushup/typescript/runner-output.json"], + "executor": "nx:run-commands", + "options": { + "command": "node packages/cli/src/index.ts collect", + "args": [ + "--no-progress", + "--verbose", + "--config={projectRoot}/code-pushup.config.ts", + "--cache.write", + "--onlyPlugins=typescript", + "--persist.skipReports", + "--persist.outputDir={projectRoot}/.code-pushup" + ], + "env": { + "NODE_OPTIONS": "--import tsx", + "TSX_TSCONFIG_PATH": "tsconfig.base.json" + } + } + }, "nx-release-publish": { "dependsOn": ["build"], "executor": "@nx/js:release-publish", diff --git a/package.json b/package.json index e1f97c332..986ea3a26 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,9 @@ "node": ">=22.14" }, "dependencies": { + "@code-pushup/models": "https://pkg.pr.new/code-pushup/cli/@code-pushup/models@1059", "@code-pushup/portal-client": "^0.15.0", + "@code-pushup/utils": "https://pkg.pr.new/code-pushup/cli/@code-pushup/utils@1059", "@isaacs/cliui": "^8.0.2", "@nx/devkit": "21.4.1", "@poppinss/cliui": "6.4.1", diff --git a/packages/ci/code-pushup.config.ts b/packages/ci/code-pushup.config.ts new file mode 100644 index 000000000..9bf27088f --- /dev/null +++ b/packages/ci/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; +import { mergeConfigs } from '../../packages/utils/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/ci/project.json b/packages/ci/project.json index b6bdeab2c..e6b01da4a 100644 --- a/packages/ci/project.json +++ b/packages/ci/project.json @@ -8,7 +8,19 @@ "lint": {}, "lint-report": {}, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:tooling", "type:feature", "publishable"] } diff --git a/packages/ci/tsconfig.lib.json b/packages/ci/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/ci/tsconfig.lib.json +++ b/packages/ci/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/ci/tsconfig.tools.json b/packages/ci/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/ci/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/cli/code-pushup.config.ts b/packages/cli/code-pushup.config.ts new file mode 100644 index 000000000..25e6a399d --- /dev/null +++ b/packages/cli/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/cli/project.json b/packages/cli/project.json index 733186813..3ebc5e201 100644 --- a/packages/cli/project.json +++ b/packages/cli/project.json @@ -26,7 +26,19 @@ "cwd": "examples/react-todos-app" }, "dependsOn": ["build"] - } + }, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:core", "type:app", "publishable"] } diff --git a/packages/cli/tsconfig.lib.json b/packages/cli/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/cli/tsconfig.lib.json +++ b/packages/cli/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/cli/tsconfig.tools.json b/packages/cli/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/cli/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/core/code-pushup.config.ts b/packages/core/code-pushup.config.ts new file mode 100644 index 000000000..25e6a399d --- /dev/null +++ b/packages/core/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/core/project.json b/packages/core/project.json index 75fc9f380..bd60c5f54 100644 --- a/packages/core/project.json +++ b/packages/core/project.json @@ -8,7 +8,19 @@ "lint": {}, "lint-report": {}, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:core", "type:feature", "publishable"] } diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 893f9a925..042f549ac 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -18,6 +18,9 @@ }, { "path": "./tsconfig.test.json" + }, + { + "path": "./tsconfig.tools.json" } ] } diff --git a/packages/core/tsconfig.lib.json b/packages/core/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/core/tsconfig.lib.json +++ b/packages/core/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/core/tsconfig.tools.json b/packages/core/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/core/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/create-cli/code-pushup.config.ts b/packages/create-cli/code-pushup.config.ts new file mode 100644 index 000000000..c661594be --- /dev/null +++ b/packages/create-cli/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; +import { mergeConfigs } from '../../packages/utils/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx({ projectName, targetNames: ['unit-test'] }), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/create-cli/project.json b/packages/create-cli/project.json index 813f42b91..98501e26c 100644 --- a/packages/create-cli/project.json +++ b/packages/create-cli/project.json @@ -8,16 +8,20 @@ "lint": {}, "lint-report": {}, "unit-test": {}, - "exec-node": { - "dependsOn": ["build"], - "command": "node ./dist/packages/create-cli/src/index.js", - "options": {} + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] }, - "exec-npm": { - "dependsOn": ["^build"], - "command": "npm exec ./dist/packages/create-cli", - "options": {} - } + "code-pushup-eslint": {}, + "code-pushup-coverage": { + "dependsOn": ["unit-test"] + }, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, - "tags": ["scope:tooling", "type:app", "publishable"] + "tags": ["scope:shared", "type:util", "publishable"] } diff --git a/packages/create-cli/tsconfig.lib.json b/packages/create-cli/tsconfig.lib.json index d96298230..c38419f5e 100644 --- a/packages/create-cli/tsconfig.lib.json +++ b/packages/create-cli/tsconfig.lib.json @@ -10,6 +10,7 @@ "vitest.unit.config.ts", "vitest.int.config.ts", "src/**/*.test.ts", - "test/**/*.ts" + "test/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/create-cli/tsconfig.tools.json b/packages/create-cli/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/create-cli/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/models/code-pushup.config.ts b/packages/models/code-pushup.config.ts new file mode 100644 index 000000000..cc85175a6 --- /dev/null +++ b/packages/models/code-pushup.config.ts @@ -0,0 +1,32 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +// This part should use mergeConfig in a normal setup, but here we are manually merging to avoid circular dependencies +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx({ projectName, targetNames: ['unit-test'] }), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/models/project.json b/packages/models/project.json index 58a71cd27..83dfa4de8 100644 --- a/packages/models/project.json +++ b/packages/models/project.json @@ -4,6 +4,20 @@ "sourceRoot": "packages/models/src", "projectType": "library", "targets": { + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-jsdocs": {}, + "code-pushup-coverage": { + "dependsOn": ["unit-test"] + }, + "code-pushup-typescript": {}, "generate-docs": { "command": "npx zod2md --config packages/models/zod2md.config.ts", "cache": true, @@ -14,7 +28,10 @@ "dependsOn": [ "^build", "generate-docs", - { "projects": "models-transformers", "target": "build" } + { + "projects": "models-transformers", + "target": "build" + } ] }, "lint": {}, diff --git a/packages/models/transformers/package.json b/packages/models/transformers/package.json index 4d245947f..e5d33d01b 100644 --- a/packages/models/transformers/package.json +++ b/packages/models/transformers/package.json @@ -7,5 +7,8 @@ "dependencies": { "typescript": "^5.5.4", "ts-patch": "^3.3.0" - } + }, + "files": [ + "src" + ] } diff --git a/packages/models/transformers/project.json b/packages/models/transformers/project.json index fdd783682..b377da537 100644 --- a/packages/models/transformers/project.json +++ b/packages/models/transformers/project.json @@ -7,9 +7,13 @@ "build": { "executor": "@nx/js:tsc", "outputs": ["{options.outputPath}"], - "dependsOn": [{ "target": "pre-build" }], + "dependsOn": [ + { + "target": "pre-build" + } + ], "options": { - "outputPath": "dist/packages/models-transformers", + "outputPath": "packages/models/transformers/dist", "main": "packages/models/transformers/src/index.ts", "tsConfig": "packages/models/transformers/tsconfig.lib.json" } diff --git a/packages/models/transformers/tsconfig.lib.json b/packages/models/transformers/tsconfig.lib.json index fa583ace0..48174f134 100644 --- a/packages/models/transformers/tsconfig.lib.json +++ b/packages/models/transformers/tsconfig.lib.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "outDir": "../../../dist/packages/models-transformers", + "outDir": "./dist", "rootDir": "./", "module": "commonjs", "types": ["node"] diff --git a/packages/models/tsconfig.lib.json b/packages/models/tsconfig.lib.json index b741c8920..2c92983e0 100644 --- a/packages/models/tsconfig.lib.json +++ b/packages/models/tsconfig.lib.json @@ -6,7 +6,7 @@ "types": ["node"], "plugins": [ { - "transform": "./dist/packages/models-transformers", + "transform": "./packages/models/transformers/dist", "afterDeclarations": true } ] diff --git a/packages/models/tsconfig.test.json b/packages/models/tsconfig.test.json index 67645f7d5..477efb329 100644 --- a/packages/models/tsconfig.test.json +++ b/packages/models/tsconfig.test.json @@ -4,7 +4,7 @@ "outDir": "../../dist/out-tsc", "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"] }, - "exclude": ["**/code-pushup.config.ts"], + "exclude": ["code-pushup.config.ts"], "include": [ "vitest.unit.config.ts", "vitest.int.config.ts", diff --git a/packages/models/tsconfig.tools.json b/packages/models/tsconfig.tools.json index 18f62770b..4a9dfeae3 100644 --- a/packages/models/tsconfig.tools.json +++ b/packages/models/tsconfig.tools.json @@ -4,5 +4,5 @@ "outDir": "../../dist/out-tsc", "types": ["nodenext"] }, - "include": ["zod2md.config.ts"] + "include": ["zod2md.config.ts", "code-pushup.config.ts"] } diff --git a/packages/nx-plugin/code-pushup.config.ts b/packages/nx-plugin/code-pushup.config.ts new file mode 100644 index 000000000..9bf27088f --- /dev/null +++ b/packages/nx-plugin/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; +import { mergeConfigs } from '../../packages/utils/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/nx-plugin/project.json b/packages/nx-plugin/project.json index 63e15c1d4..bd5db64fa 100644 --- a/packages/nx-plugin/project.json +++ b/packages/nx-plugin/project.json @@ -3,7 +3,6 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "packages/nx-plugin/src", "projectType": "library", - "implicitDependencies": ["cli"], "targets": { "build": { "options": { @@ -51,7 +50,19 @@ } }, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:tooling", "type:feature", "publishable"] } diff --git a/packages/nx-plugin/tsconfig.lib.json b/packages/nx-plugin/tsconfig.lib.json index 71aabc78b..20ece2831 100644 --- a/packages/nx-plugin/tsconfig.lib.json +++ b/packages/nx-plugin/tsconfig.lib.json @@ -12,6 +12,7 @@ "src/**/__snapshots__/*.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "test/**/*.ts" + "test/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/nx-plugin/tsconfig.tools.json b/packages/nx-plugin/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/nx-plugin/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/plugin-coverage/code-pushup.config.ts b/packages/plugin-coverage/code-pushup.config.ts new file mode 100644 index 000000000..25e6a399d --- /dev/null +++ b/packages/plugin-coverage/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/plugin-coverage/project.json b/packages/plugin-coverage/project.json index 031d65697..42e5da8d6 100644 --- a/packages/plugin-coverage/project.json +++ b/packages/plugin-coverage/project.json @@ -8,7 +8,19 @@ "lint": {}, "lint-report": {}, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:plugin", "type:feature", "publishable"] } diff --git a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts index b5140bbbf..52c20cdbe 100644 --- a/packages/plugin-coverage/src/lib/nx/coverage-paths.ts +++ b/packages/plugin-coverage/src/lib/nx/coverage-paths.ts @@ -12,26 +12,51 @@ import { importModule, ui } from '@code-pushup/utils'; import type { CoverageResult } from '../config.js'; /** + * Resolves the cached project graph for the current Nx workspace. + * First tries to read cache and if not possible, go for the async creation. + */ +async function resolveCachedProjectGraph() { + const { readCachedProjectGraph, createProjectGraphAsync } = await import( + '@nx/devkit' + ); + try { + return readCachedProjectGraph(); + } catch (error) { + ui().logger.info( + `Could not read cached project graph, falling back to async creation. + ${stringifyError(error)}`, + ); + return await createProjectGraphAsync({ exitOnError: false }); + } +} + +/** + * Gathers coverage paths from Nx projects. Filters by specific projects when provided. * @param targets nx targets to be used for measuring coverage, test by default + * @param projects optional array of project names to filter results for specific projects + * @param verbose optional verbose logging * @returns An array of coverage result information for the coverage plugin. */ -export async function getNxCoveragePaths( - targets: string[] = ['test'], - verbose?: boolean, -): Promise { +export async function getNxCoveragePaths(options: { + targets?: string[]; + projects?: string[]; + verbose?: boolean; +}): Promise { + const { targets = ['test'], verbose, projects } = options; if (verbose) { ui().logger.info( bold('💡 Gathering coverage from the following nx projects:'), ); } - const { createProjectGraphAsync } = await import('@nx/devkit'); - const { nodes } = await createProjectGraphAsync({ exitOnError: false }); + const { nodes } = await resolveCachedProjectGraph(); const coverageResults = await Promise.all( targets.map(async target => { - const relevantNodes = Object.values(nodes).filter(graph => - hasNxTarget(graph, target), + const relevantNodes = Object.values(nodes).filter( + graph => + hasNxTarget(graph, target) && + (projects ? projects.includes(graph.name) : true), ); return await Promise.all( @@ -160,7 +185,7 @@ export async function getCoveragePathForJest( options: JestExecutorOptions, project: ProjectConfiguration, target: string, -) { +): Promise { const { jestConfig } = options; const testConfig = await importModule({ diff --git a/packages/plugin-coverage/tsconfig.lib.json b/packages/plugin-coverage/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/plugin-coverage/tsconfig.lib.json +++ b/packages/plugin-coverage/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/plugin-coverage/tsconfig.tools.json b/packages/plugin-coverage/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/plugin-coverage/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/plugin-eslint/code-pushup.config.ts b/packages/plugin-eslint/code-pushup.config.ts new file mode 100644 index 000000000..25e6a399d --- /dev/null +++ b/packages/plugin-eslint/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/plugin-eslint/project.json b/packages/plugin-eslint/project.json index eeae19055..83ccee8f2 100644 --- a/packages/plugin-eslint/project.json +++ b/packages/plugin-eslint/project.json @@ -8,7 +8,19 @@ "lint": {}, "lint-report": {}, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:plugin", "type:feature", "publishable"] } diff --git a/packages/plugin-eslint/src/lib/nx/find-all-projects.ts b/packages/plugin-eslint/src/lib/nx/find-all-projects.ts index 11ecfb284..10306f83e 100644 --- a/packages/plugin-eslint/src/lib/nx/find-all-projects.ts +++ b/packages/plugin-eslint/src/lib/nx/find-all-projects.ts @@ -1,7 +1,27 @@ +import { stringifyError, ui } from '@code-pushup/utils'; import type { ESLintTarget } from '../config.js'; import { filterProjectGraph } from './filter-project-graph.js'; import { nxProjectsToConfig } from './projects-to-config.js'; +/** + * Resolves the cached project graph for the current Nx workspace. + * First tries to read cache and if not possible, go for the async creation. + */ +async function resolveCachedProjectGraph() { + const { readCachedProjectGraph, createProjectGraphAsync } = await import( + '@nx/devkit' + ); + try { + return readCachedProjectGraph(); + } catch (error) { + ui().logger.info( + `Could not read cached project graph, falling back to async creation. + ${stringifyError(error)}`, + ); + return await createProjectGraphAsync({ exitOnError: false }); + } +} + /** * Finds all Nx projects in workspace and converts their lint configurations to Code PushUp ESLint plugin parameters. * @@ -31,8 +51,7 @@ import { nxProjectsToConfig } from './projects-to-config.js'; export async function eslintConfigFromAllNxProjects( options: { exclude?: string[] } = {}, ): Promise { - const { createProjectGraphAsync } = await import('@nx/devkit'); - const projectGraph = await createProjectGraphAsync({ exitOnError: false }); + const projectGraph = await resolveCachedProjectGraph(); const filteredProjectGraph = filterProjectGraph( projectGraph, options.exclude, diff --git a/packages/plugin-eslint/tsconfig.lib.json b/packages/plugin-eslint/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/plugin-eslint/tsconfig.lib.json +++ b/packages/plugin-eslint/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/plugin-eslint/tsconfig.tools.json b/packages/plugin-eslint/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/plugin-eslint/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/plugin-js-packages/code-pushup.config.ts b/packages/plugin-js-packages/code-pushup.config.ts new file mode 100644 index 000000000..25e6a399d --- /dev/null +++ b/packages/plugin-js-packages/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/plugin-js-packages/project.json b/packages/plugin-js-packages/project.json index 63782308a..9916ef55f 100644 --- a/packages/plugin-js-packages/project.json +++ b/packages/plugin-js-packages/project.json @@ -8,7 +8,19 @@ "lint": {}, "lint-report": {}, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:plugin", "type:feature", "publishable"], "description": "A plugin for JavaScript packages." diff --git a/packages/plugin-js-packages/tsconfig.lib.json b/packages/plugin-js-packages/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/plugin-js-packages/tsconfig.lib.json +++ b/packages/plugin-js-packages/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/plugin-js-packages/tsconfig.tools.json b/packages/plugin-js-packages/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/plugin-js-packages/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/plugin-jsdocs/code-pushup.config.ts b/packages/plugin-jsdocs/code-pushup.config.ts new file mode 100644 index 000000000..9bf27088f --- /dev/null +++ b/packages/plugin-jsdocs/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; +import { mergeConfigs } from '../../packages/utils/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/plugin-jsdocs/project.json b/packages/plugin-jsdocs/project.json index 9f07a4761..8500553be 100644 --- a/packages/plugin-jsdocs/project.json +++ b/packages/plugin-jsdocs/project.json @@ -3,12 +3,24 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "packages/plugin-jsdocs/src", "projectType": "library", - "tags": ["scope:plugin", "type:feature", "publishable"], "targets": { "build": {}, "lint": {}, "lint-report": {}, "unit-test": {}, - "int-test": {} - } + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} + }, + "tags": ["scope:plugin", "type:feature", "publishable"] } diff --git a/packages/plugin-jsdocs/tsconfig.lib.json b/packages/plugin-jsdocs/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/plugin-jsdocs/tsconfig.lib.json +++ b/packages/plugin-jsdocs/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/plugin-jsdocs/tsconfig.tools.json b/packages/plugin-jsdocs/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/plugin-jsdocs/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/plugin-lighthouse/code-pushup.config.ts b/packages/plugin-lighthouse/code-pushup.config.ts new file mode 100644 index 000000000..6588febce --- /dev/null +++ b/packages/plugin-lighthouse/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx({ projectName, targetNames: ['unit-test'] }), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/plugin-lighthouse/project.json b/packages/plugin-lighthouse/project.json index 468165a9c..c20901486 100644 --- a/packages/plugin-lighthouse/project.json +++ b/packages/plugin-lighthouse/project.json @@ -7,7 +7,21 @@ "build": {}, "lint": {}, "lint-report": {}, - "unit-test": {} + "unit-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": { + "dependsOn": ["unit-test"] + }, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:plugin", "type:feature", "publishable"] } diff --git a/packages/plugin-lighthouse/tsconfig.lib.json b/packages/plugin-lighthouse/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/plugin-lighthouse/tsconfig.lib.json +++ b/packages/plugin-lighthouse/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/plugin-lighthouse/tsconfig.tools.json b/packages/plugin-lighthouse/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/plugin-lighthouse/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/plugin-typescript/code-pushup.config.ts b/packages/plugin-typescript/code-pushup.config.ts new file mode 100644 index 000000000..25e6a399d --- /dev/null +++ b/packages/plugin-typescript/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/plugin-typescript/project.json b/packages/plugin-typescript/project.json index de10ea00e..4ff592eee 100644 --- a/packages/plugin-typescript/project.json +++ b/packages/plugin-typescript/project.json @@ -8,7 +8,19 @@ "lint": {}, "lint-report": {}, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-coverage": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {} }, "tags": ["scope:plugin", "type:feature", "publishable"] } diff --git a/packages/plugin-typescript/tsconfig.lib.json b/packages/plugin-typescript/tsconfig.lib.json index 76a3dbec1..8f9e8a92a 100644 --- a/packages/plugin-typescript/tsconfig.lib.json +++ b/packages/plugin-typescript/tsconfig.lib.json @@ -11,6 +11,7 @@ "vitest.int.config.ts", "src/**/*.test.ts", "src/**/*.mock.ts", - "mocks/**/*.ts" + "mocks/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/plugin-typescript/tsconfig.tools.json b/packages/plugin-typescript/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/plugin-typescript/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/packages/utils/code-pushup.config.ts b/packages/utils/code-pushup.config.ts new file mode 100644 index 000000000..25e6a399d --- /dev/null +++ b/packages/utils/code-pushup.config.ts @@ -0,0 +1,31 @@ +import 'dotenv/config'; +import { + coverageCoreConfigNx, + eslintCoreConfigNx, + jsDocsCoreConfig, + jsDocsExclusionPatterns, + loadEnv, + mergeConfigs, + typescriptPluginConfig, +} from '../../code-pushup.preset.js'; +import type { CoreConfig } from '../../packages/models/src/index.js'; + +const projectName = process.env['NX_TASK_TARGET_PROJECT']; + +const config: CoreConfig = { + ...(await loadEnv()), + plugins: [], +}; + +export default mergeConfigs( + config, + await eslintCoreConfigNx(projectName), + await coverageCoreConfigNx(projectName), + await typescriptPluginConfig({ + tsconfig: `packages/${projectName}/tsconfig.lib.json`, + }), + jsDocsCoreConfig([ + `packages/${projectName}/src/**/*.ts`, + ...jsDocsExclusionPatterns, + ]), +); diff --git a/packages/utils/project.json b/packages/utils/project.json index 2953464ca..03f0bc3ee 100644 --- a/packages/utils/project.json +++ b/packages/utils/project.json @@ -20,7 +20,20 @@ } }, "unit-test": {}, - "int-test": {} + "int-test": {}, + "code-pushup": { + "dependsOn": [ + "code-pushup-coverage", + "code-pushup-jsdocs", + "code-pushup-typescript", + "code-pushup-eslint" + ] + }, + "code-pushup-eslint": {}, + "code-pushup-jsdocs": {}, + "code-pushup-coverage": { + "dependsOn": ["unit-test", "int-test"] + } }, "tags": ["scope:shared", "type:util", "publishable"] } diff --git a/packages/utils/tsconfig.lib.json b/packages/utils/tsconfig.lib.json index 17dadcedf..0ac87fe0b 100644 --- a/packages/utils/tsconfig.lib.json +++ b/packages/utils/tsconfig.lib.json @@ -12,6 +12,7 @@ "src/**/*.test.ts", "src/**/*.mock.ts", "mocks/**/*.ts", - "perf/**/*.ts" + "perf/**/*.ts", + "code-pushup.config.ts" ] } diff --git a/packages/utils/tsconfig.tools.json b/packages/utils/tsconfig.tools.json new file mode 100644 index 000000000..8fd1f320d --- /dev/null +++ b/packages/utils/tsconfig.tools.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc-tools", + "types": ["node"] + }, + "include": ["code-pushup.config.ts"] +} diff --git a/project.json b/project.json index 1f19a828e..ac255666e 100644 --- a/project.json +++ b/project.json @@ -2,14 +2,25 @@ "name": "cli-workspace", "$schema": "node_modules/nx/schemas/project-schema.json", "targets": { + "code-pushup-js-packages": {}, + "code-pushup-lighthouse": {}, + "code-pushup-coverage": { + "dependsOn": ["^*-test"] + }, + "code-pushup-eslint": {}, + "code-pushup-jsdocs": {}, + "code-pushup-typescript": {}, "code-pushup": { + "dependsOn": ["code-pushup-*"], "executor": "nx:run-commands", "options": { - "command": "node packages/cli/src/index.ts --no-progress --verbose", - "env": { - "NODE_OPTIONS": "--import tsx", - "TSX_TSCONFIG_PATH": "tsconfig.base.json" - } + "args": [ + "--no-progress", + "--verbose", + "--cache.read", + "--persist.outputDir={projectRoot}/.code-pushup", + "--upload.project={projectName}" + ] } } } diff --git a/testing/test-nx-utils/tsconfig.json b/testing/test-nx-utils/tsconfig.json index c370491f9..aab1b622a 100644 --- a/testing/test-nx-utils/tsconfig.json +++ b/testing/test-nx-utils/tsconfig.json @@ -8,7 +8,8 @@ "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, - "types": ["vitest"] + "types": ["vitest"], + "rootDir": ".." }, "files": [], "include": [], @@ -18,6 +19,9 @@ }, { "path": "./tsconfig.test.json" + }, + { + "path": "../test-utils/tsconfig.lib.json" } ] } diff --git a/testing/test-nx-utils/tsconfig.lib.json b/testing/test-nx-utils/tsconfig.lib.json index 09cc715cc..3750702ca 100644 --- a/testing/test-nx-utils/tsconfig.lib.json +++ b/testing/test-nx-utils/tsconfig.lib.json @@ -2,6 +2,7 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../dist/out-tsc", + "rootDir": "../../", "declaration": true, "types": ["node"] }, diff --git a/testing/test-setup/tsconfig.json b/testing/test-setup/tsconfig.json index 465306e46..1a2fbb2f5 100644 --- a/testing/test-setup/tsconfig.json +++ b/testing/test-setup/tsconfig.json @@ -7,7 +7,8 @@ "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "rootDir": ".." }, "files": [], "include": [], @@ -17,6 +18,9 @@ }, { "path": "./tsconfig.test.json" + }, + { + "path": "../test-utils/tsconfig.lib.json" } ] } diff --git a/testing/test-setup/tsconfig.lib.json b/testing/test-setup/tsconfig.lib.json index 3cc313086..fec0e233c 100644 --- a/testing/test-setup/tsconfig.lib.json +++ b/testing/test-setup/tsconfig.lib.json @@ -2,6 +2,7 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../dist/out-tsc", + "rootDir": "../../", "declaration": true, "types": ["node"] }, diff --git a/testing/test-utils/tsconfig.lib.json b/testing/test-utils/tsconfig.lib.json index 3975fe4ed..eeb3208f4 100644 --- a/testing/test-utils/tsconfig.lib.json +++ b/testing/test-utils/tsconfig.lib.json @@ -3,6 +3,7 @@ "compilerOptions": { "outDir": "../dist/out-tsc", "declaration": true, + "composite": true, "types": ["node"] }, "include": ["src/**/*.ts"],