From 1d9022933d7a123434988a5d7af580d52a63b56d Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 14 Aug 2024 16:21:06 +0200 Subject: [PATCH 01/32] feat(nx-plugin): refactor autorun executor to general command executor --- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 173 ++++++++++++++++++ packages/nx-plugin/package.json | 3 +- .../src/executors/autorun/executor.ts | 20 +- .../executors/autorun/executor.unit.test.ts | 3 +- .../src/executors/autorun/schema.json | 5 +- .../nx-plugin/src/executors/internal/types.ts | 1 + 6 files changed, 191 insertions(+), 14 deletions(-) create mode 100644 e2e/nx-plugin-e2e/tests/executor.e2e.test.ts diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts new file mode 100644 index 000000000..d770bb79b --- /dev/null +++ b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts @@ -0,0 +1,173 @@ +import {Tree, updateProjectConfiguration} from '@nx/devkit'; +import {rm} from 'node:fs/promises'; +import {join, relative} from 'node:path'; +import {readProjectConfiguration} from 'nx/src/generators/utils/project-configuration'; +import {afterEach, expect} from 'vitest'; +import {generateCodePushupConfig} from '@code-pushup/nx-plugin'; +import { + generateWorkspaceAndProject, + materializeTree, +} from '@code-pushup/test-nx-utils'; +import {removeColorCodes} from '@code-pushup/test-utils'; +import {executeProcess, readJsonFile} from '@code-pushup/utils'; + +// @TODO replace with default bin after https://github.com/code-pushup/cli/issues/643 +function relativePathToCwd(testDir: string): string { + return relative(join(process.cwd(), testDir), process.cwd()); +} + +async function addTargetToWorkspace( + tree: Tree, + options: { cwd: string; project: string }, +) { + const {cwd, project} = options; + const pathRelativeToPackage = relative(join(cwd, 'libs', project), cwd); + const projectCfg = readProjectConfiguration(tree, project); + updateProjectConfiguration(tree, project, { + ...projectCfg, + targets: { + ...projectCfg.targets, + ['code-pushup']: { + executor: `${join( + relativePathToCwd(cwd), + 'dist/packages/nx-plugin', + )}:autorun`, + }, + }, + }); + const {root} = projectCfg; + generateCodePushupConfig(tree, root, { + fileImports: `import type {CoreConfig} from "${join( + relativePathToCwd(cwd), + pathRelativeToPackage, + 'dist/packages/models', + )}";`, + plugins: [ + { + fileImports: `import {customPlugin} from "${join( + relativePathToCwd(cwd), + pathRelativeToPackage, + 'dist/testing/test-utils', + )}";`, + codeStrings: 'customPlugin()', + }, + ], + }); + await materializeTree(tree, cwd); +} + +describe('CLI executor', () => { + let tree: Tree; + const project = 'my-lib'; + const baseDir = 'tmp/nx-plugin-e2e/executor'; + + beforeEach(async () => { + tree = await generateWorkspaceAndProject(project); + }); + + afterEach(async () => { + await rm(baseDir, {recursive: true, force: true}); + }); + + it('should execute autorun executor by default', async () => { + const cwd = join(baseDir, 'execute-default-executor'); + await addTargetToWorkspace(tree, {cwd, project}); + + const {stdout, code} = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, '--dryRun'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup'); + + }); + + it('should execute print-config executor', async () => { + const cwd = join(baseDir, 'execute-print-config-executor'); + await addTargetToWorkspace(tree, {cwd, project}); + + const {stdout, code} = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'print-config'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup print-config'); + + await expect(() => readJsonFile( + join(cwd, '.code-pushup', project, 'report.json'), + )).rejects.toThrow(''); + }); + + it('should execute collect executor', async () => { + const cwd = join(baseDir, 'execute-collect-executor'); + await addTargetToWorkspace(tree, {cwd, project}); + + const {stdout, code} = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'collect'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup collect'); + + const report = await readJsonFile( + join(cwd, '.code-pushup', project, 'report.json'), + ); + expect(report).toStrictEqual( + expect.objectContaining({ + plugins: [ + expect.objectContaining({ + slug: 'good-feels', + audits: [ + expect.objectContaining({ + displayValue: '✅ Perfect! 👌', + slug: 'always-perfect', + }), + ], + }), + ], + }), + ); + }); + + it('should execute upload executor to throw if no report is present', async () => { + const cwd = join(baseDir, 'execute-upload-executor'); + await addTargetToWorkspace(tree, {cwd, project}); + + const {stdout, code} = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'upload', '--dryRun'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup upload') + + }); + + it('should execute autorun executor', async () => { + const cwd = join(baseDir, 'execute-autorun-executor'); + await addTargetToWorkspace(tree, {cwd, project}); + + const {stdout, code} = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'autorun', '--dryRun'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup autorun'); + + }); +}); + diff --git a/packages/nx-plugin/package.json b/packages/nx-plugin/package.json index fe0805057..b002438ad 100644 --- a/packages/nx-plugin/package.json +++ b/packages/nx-plugin/package.json @@ -9,7 +9,8 @@ "nx": "^17.1.3", "@code-pushup/models": "*", "zod": "^3.22.4", - "@code-pushup/utils": "*" + "@code-pushup/utils": "*", + "ansis": "^3.3.0" }, "type": "commonjs", "main": "./src/index.js", diff --git a/packages/nx-plugin/src/executors/autorun/executor.ts b/packages/nx-plugin/src/executors/autorun/executor.ts index 4df28ba50..0c6ffd984 100644 --- a/packages/nx-plugin/src/executors/autorun/executor.ts +++ b/packages/nx-plugin/src/executors/autorun/executor.ts @@ -6,6 +6,7 @@ import { normalizeContext } from '../internal/context'; import { AUTORUN_COMMAND } from './constants'; import { AutorunCommandExecutorOptions } from './schema'; import { parseAutorunExecutorOptions } from './utils'; +import {bold} from "ansis"; export type ExecutorOutput = { success: boolean; @@ -22,25 +23,26 @@ export default function runAutorunExecutor( terminalAndExecutorOptions, normalizedContext, ); - const { dryRun, verbose } = terminalAndExecutorOptions; - const command = createCliCommand(AUTORUN_COMMAND, cliArgumentObject); - const commandOptions = context.cwd ? { cwd: context.cwd } : {}; + const { dryRun, verbose, command = AUTORUN_COMMAND } = terminalAndExecutorOptions; + + const commandString = createCliCommand(command, cliArgumentObject); + const commandStringOptions = context.cwd ? { cwd: context.cwd } : {}; if (verbose) { - logger.info(`Run ${AUTORUN_COMMAND} executor`); - logger.info(`Command: ${command}`); + logger.info(`Run CLI executor with commandString: ${bold(command)}`); + logger.info(`Command: ${commandString}`); } if (dryRun) { - logger.warn(`DryRun execution of: ${command}`); + logger.warn(`DryRun execution of: ${commandString}`); } else { try { // @TODO use executeProcess instead of execSync -> non blocking, logs #761 // eslint-disable-next-line n/no-sync - execSync(command, commandOptions); + execSync(commandString, commandStringOptions); } catch (error) { logger.error(error); return Promise.resolve({ success: false, - command, + commandString, error, }); } @@ -48,6 +50,6 @@ export default function runAutorunExecutor( return Promise.resolve({ success: true, - command, + command: commandString, } satisfies ExecutorOutput); } diff --git a/packages/nx-plugin/src/executors/autorun/executor.unit.test.ts b/packages/nx-plugin/src/executors/autorun/executor.unit.test.ts index 56b21a4a4..580bab156 100644 --- a/packages/nx-plugin/src/executors/autorun/executor.unit.test.ts +++ b/packages/nx-plugin/src/executors/autorun/executor.unit.test.ts @@ -4,6 +4,7 @@ import { execSync } from 'node:child_process'; import { afterEach, beforeEach, expect, vi } from 'vitest'; import { executorContext } from '@code-pushup/test-nx-utils'; import runAutorunExecutor from './executor'; +import {bold} from "ansis"; vi.mock('node:child_process', async () => { const actual = await vi.importActual('node:child_process'); @@ -94,7 +95,7 @@ describe('runAutorunExecutor', () => { expect(loggerWarnSpy).toHaveBeenCalledTimes(0); expect(loggerInfoSpy).toHaveBeenCalledTimes(2); expect(loggerInfoSpy).toHaveBeenCalledWith( - expect.stringContaining('Run autorun executor'), + expect.stringContaining(`Run CLI executor with commandString: ${bold('autorun')}`), ); expect(loggerInfoSpy).toHaveBeenCalledWith( expect.stringContaining('Command: npx @code-pushup/cli autorun'), diff --git a/packages/nx-plugin/src/executors/autorun/schema.json b/packages/nx-plugin/src/executors/autorun/schema.json index 288c2591e..743f64c66 100644 --- a/packages/nx-plugin/src/executors/autorun/schema.json +++ b/packages/nx-plugin/src/executors/autorun/schema.json @@ -5,11 +5,10 @@ "description": "Executes the @code-pushup/cli autorun command See: https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#autorun-command", "type": "object", "properties": { - "project": { + "command": { "type": "string", - "description": "The name of the project.", + "description": "The command to run.", "x-prompt": "Which project should configure Code Pushup?", - "x-dropdown": "projects", "$default": { "$source": "argv", "index": 0 diff --git a/packages/nx-plugin/src/executors/internal/types.ts b/packages/nx-plugin/src/executors/internal/types.ts index f642b6ef1..a7995d991 100644 --- a/packages/nx-plugin/src/executors/internal/types.ts +++ b/packages/nx-plugin/src/executors/internal/types.ts @@ -20,6 +20,7 @@ export type ProjectExecutorOnlyOptions = { * CLI types that apply globally for all commands. */ export type GlobalExecutorOptions = { + command?: 'collect' | 'upload' | 'autorun' | 'print-config' | 'compare' | 'history'; bin?: string; verbose?: boolean; progress?: boolean; From 446f9d128cd3dd4d7cb0b98efba2a6dea96a6f83 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 14 Aug 2024 20:31:40 +0200 Subject: [PATCH 02/32] refactor(nx-plugin): refactor autorun command to general --- .../__snapshots__/nx-plugin.e2e.test.ts.snap | 4 +- .../tests/configuration.e2e.test.ts | 8 +- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 58 +++++----- e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts | 8 +- nx.json | 11 +- packages/nx-plugin/README.md | 49 +++++++- ...nx-plugin-dynamic-target-configuration.png | Bin 0 -> 48819 bytes packages/nx-plugin/executors.json | 8 +- packages/nx-plugin/package.json | 3 +- .../src/executors/autorun/constants.ts | 1 - .../executors/{autorun => command}/README.md | 26 ++++- .../executor.integration.test.ts | 0 .../{autorun => command}/executor.ts | 16 ++- .../executor.unit.test.ts | 13 +-- .../{autorun => command}/schema.json | 0 .../executors/{autorun => command}/schema.ts | 0 .../utils.integration.test.ts | 0 .../executors/{autorun => command}/utils.ts | 0 .../{autorun => command}/utils.unit.test.ts | 0 .../nx-plugin/src/executors/internal/cli.ts | 22 ++-- .../src/executors/internal/cli.unit.test.ts | 9 +- .../nx-plugin/src/executors/internal/types.ts | 8 +- .../src/generators/configuration/README.md | 15 ++- .../generator.integration.test.ts | 6 +- .../src/generators/configuration/generator.ts | 2 +- .../nx-plugin/src/generators/init/README.md | 10 +- packages/nx-plugin/src/plugin/README.md | 107 ++++++++++++++++++ .../src/plugin/target/executor-target.ts | 2 +- .../target/executor.target.unit.test.ts | 4 +- .../src/plugin/target/targets.unit.test.ts | 6 +- testing/test-utils/src/index.ts | 1 + .../src/lib/fixtures/configs/custom-plugin.ts | 7 +- 32 files changed, 302 insertions(+), 102 deletions(-) create mode 100644 packages/nx-plugin/docs/images/nx-plugin-dynamic-target-configuration.png delete mode 100644 packages/nx-plugin/src/executors/autorun/constants.ts rename packages/nx-plugin/src/executors/{autorun => command}/README.md (78%) rename packages/nx-plugin/src/executors/{autorun => command}/executor.integration.test.ts (100%) rename packages/nx-plugin/src/executors/{autorun => command}/executor.ts (78%) rename packages/nx-plugin/src/executors/{autorun => command}/executor.unit.test.ts (87%) rename packages/nx-plugin/src/executors/{autorun => command}/schema.json (100%) rename packages/nx-plugin/src/executors/{autorun => command}/schema.ts (100%) rename packages/nx-plugin/src/executors/{autorun => command}/utils.integration.test.ts (100%) rename packages/nx-plugin/src/executors/{autorun => command}/utils.ts (100%) rename packages/nx-plugin/src/executors/{autorun => command}/utils.unit.test.ts (100%) create mode 100644 packages/nx-plugin/src/plugin/README.md diff --git a/e2e/nx-plugin-e2e/tests/__snapshots__/nx-plugin.e2e.test.ts.snap b/e2e/nx-plugin-e2e/tests/__snapshots__/nx-plugin.e2e.test.ts.snap index 0315a42f6..96205b158 100644 --- a/e2e/nx-plugin-e2e/tests/__snapshots__/nx-plugin.e2e.test.ts.snap +++ b/e2e/nx-plugin-e2e/tests/__snapshots__/nx-plugin.e2e.test.ts.snap @@ -14,7 +14,7 @@ exports[`nx-plugin > should NOT add config targets dynamically if the project is "targets": { "code-pushup": { "configurations": {}, - "executor": "@code-pushup/nx-plugin:autorun", + "executor": "@code-pushup/nx-plugin:command", "options": {}, }, }, @@ -73,7 +73,7 @@ exports[`nx-plugin > should add executor target dynamically if the project is co "targets": { "code-pushup": { "configurations": {}, - "executor": "@code-pushup/nx-plugin:autorun", + "executor": "@code-pushup/nx-plugin:command", "options": {}, }, }, diff --git a/e2e/nx-plugin-e2e/tests/configuration.e2e.test.ts b/e2e/nx-plugin-e2e/tests/configuration.e2e.test.ts index 0142578c5..5e7ef538e 100644 --- a/e2e/nx-plugin-e2e/tests/configuration.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/configuration.e2e.test.ts @@ -72,7 +72,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', }, }), }), @@ -115,7 +115,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', }, }), }), @@ -156,7 +156,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', }, }), }), @@ -200,7 +200,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.not.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', }, }), }), diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts index d770bb79b..b1d3627f3 100644 --- a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts @@ -1,15 +1,15 @@ -import {Tree, updateProjectConfiguration} from '@nx/devkit'; -import {rm} from 'node:fs/promises'; -import {join, relative} from 'node:path'; -import {readProjectConfiguration} from 'nx/src/generators/utils/project-configuration'; -import {afterEach, expect} from 'vitest'; -import {generateCodePushupConfig} from '@code-pushup/nx-plugin'; +import { Tree, updateProjectConfiguration } from '@nx/devkit'; +import { rm } from 'node:fs/promises'; +import { join, relative } from 'node:path'; +import { readProjectConfiguration } from 'nx/src/generators/utils/project-configuration'; +import { afterEach, expect } from 'vitest'; +import { generateCodePushupConfig } from '@code-pushup/nx-plugin'; import { generateWorkspaceAndProject, materializeTree, } from '@code-pushup/test-nx-utils'; -import {removeColorCodes} from '@code-pushup/test-utils'; -import {executeProcess, readJsonFile} from '@code-pushup/utils'; +import { removeColorCodes } from '@code-pushup/test-utils'; +import { executeProcess, readJsonFile } from '@code-pushup/utils'; // @TODO replace with default bin after https://github.com/code-pushup/cli/issues/643 function relativePathToCwd(testDir: string): string { @@ -20,7 +20,7 @@ async function addTargetToWorkspace( tree: Tree, options: { cwd: string; project: string }, ) { - const {cwd, project} = options; + const { cwd, project } = options; const pathRelativeToPackage = relative(join(cwd, 'libs', project), cwd); const projectCfg = readProjectConfiguration(tree, project); updateProjectConfiguration(tree, project, { @@ -31,11 +31,11 @@ async function addTargetToWorkspace( executor: `${join( relativePathToCwd(cwd), 'dist/packages/nx-plugin', - )}:autorun`, + )}:command`, }, }, }); - const {root} = projectCfg; + const { root } = projectCfg; generateCodePushupConfig(tree, root, { fileImports: `import type {CoreConfig} from "${join( relativePathToCwd(cwd), @@ -66,14 +66,14 @@ describe('CLI executor', () => { }); afterEach(async () => { - await rm(baseDir, {recursive: true, force: true}); + await rm(baseDir, { recursive: true, force: true }); }); - it('should execute autorun executor by default', async () => { + it('should execute no command by default', async () => { const cwd = join(baseDir, 'execute-default-executor'); - await addTargetToWorkspace(tree, {cwd, project}); + await addTargetToWorkspace(tree, { cwd, project }); - const {stdout, code} = await executeProcess({ + const { stdout, code } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, '--dryRun'], cwd, @@ -82,14 +82,13 @@ describe('CLI executor', () => { expect(code).toBe(0); const cleanStdout = removeColorCodes(stdout); expect(cleanStdout).toContain('nx run my-lib:code-pushup'); - }); it('should execute print-config executor', async () => { const cwd = join(baseDir, 'execute-print-config-executor'); - await addTargetToWorkspace(tree, {cwd, project}); + await addTargetToWorkspace(tree, { cwd, project }); - const {stdout, code} = await executeProcess({ + const { stdout, code } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, 'print-config'], cwd, @@ -99,16 +98,16 @@ describe('CLI executor', () => { const cleanStdout = removeColorCodes(stdout); expect(cleanStdout).toContain('nx run my-lib:code-pushup print-config'); - await expect(() => readJsonFile( - join(cwd, '.code-pushup', project, 'report.json'), - )).rejects.toThrow(''); + await expect(() => + readJsonFile(join(cwd, '.code-pushup', project, 'report.json')), + ).rejects.toThrow(''); }); it('should execute collect executor', async () => { const cwd = join(baseDir, 'execute-collect-executor'); - await addTargetToWorkspace(tree, {cwd, project}); + await addTargetToWorkspace(tree, { cwd, project }); - const {stdout, code} = await executeProcess({ + const { stdout, code } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, 'collect'], cwd, @@ -140,9 +139,9 @@ describe('CLI executor', () => { it('should execute upload executor to throw if no report is present', async () => { const cwd = join(baseDir, 'execute-upload-executor'); - await addTargetToWorkspace(tree, {cwd, project}); + await addTargetToWorkspace(tree, { cwd, project }); - const {stdout, code} = await executeProcess({ + const { stdout, code } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, 'upload', '--dryRun'], cwd, @@ -150,15 +149,14 @@ describe('CLI executor', () => { expect(code).toBe(0); const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup upload') - + expect(cleanStdout).toContain('nx run my-lib:code-pushup upload'); }); it('should execute autorun executor', async () => { const cwd = join(baseDir, 'execute-autorun-executor'); - await addTargetToWorkspace(tree, {cwd, project}); + await addTargetToWorkspace(tree, { cwd, project }); - const {stdout, code} = await executeProcess({ + const { stdout, code } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, 'autorun', '--dryRun'], cwd, @@ -167,7 +165,5 @@ describe('CLI executor', () => { expect(code).toBe(0); const cleanStdout = removeColorCodes(stdout); expect(cleanStdout).toContain('nx run my-lib:code-pushup autorun'); - }); }); - diff --git a/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts b/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts index dd02aa1d5..898dd73b0 100644 --- a/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts @@ -163,7 +163,7 @@ describe('nx-plugin', () => { expect(projectJson.targets).toStrictEqual({ ['code-pushup']: { configurations: {}, - executor: `@code-pushup/nx-plugin:autorun`, + executor: `@code-pushup/nx-plugin:command`, options: {}, }, }); @@ -209,9 +209,7 @@ describe('nx-plugin', () => { const cleanStderr = removeColorCodes(stderr); // @TODO create test environment for working plugin. This here misses package-lock.json to execute correctly - expect(cleanStderr).toContain( - 'DryRun execution of: npx @code-pushup/cli autorun', - ); + expect(cleanStderr).toContain('DryRun execution of: npx @code-pushup/cli'); const cleanStdout = removeColorCodes(stdout); expect(cleanStdout).toContain( @@ -237,7 +235,7 @@ describe('nx-plugin', () => { expect(projectJson.targets).toStrictEqual({ ['code-pushup']: expect.objectContaining({ - executor: 'XYZ:autorun', + executor: 'XYZ:command', }), }); }); diff --git a/nx.json b/nx.json index 54c295ad7..d6947d770 100644 --- a/nx.json +++ b/nx.json @@ -109,5 +109,14 @@ } }, "releaseTagPattern": "v{version}" - } + }, + "plugins": [ + { + "plugin": "@code-pushup/nx-plugin", + "options": { + "targetName": "cp", + "projectPrefix": "cli" + } + } + ] } diff --git a/packages/nx-plugin/README.md b/packages/nx-plugin/README.md index 3999f5d8a..c1bb289fb 100644 --- a/packages/nx-plugin/README.md +++ b/packages/nx-plugin/README.md @@ -1,11 +1,30 @@ # @code-pushup/nx-plugin +### Plugin + +Register this plugin in your `nx.json` to leverage a set of generators and executors to integrate Code PushUp into a Nx workspace. + +#### Registration + +```jsonc +// nx.json +{ + //... + "plugins": ["@code-pushup/nx-plugin"] +} +``` + +Resulting targets: + +- `nx run :code-pushup--configuration` (no config file present) +- `nx run :code-pushup` (`code-pushup.config.{ts,mjs,js}` is present) + ### Generators #### Init Install JS packages and register plugin. -See [init docs](./src/generators/init/README.md) for details +See [init generator docs](./src/generators/init/README.md) for details Examples: @@ -15,9 +34,35 @@ Examples: #### Configuration Adds a `code-pushup` target to your `project.json`. -See [configuration docs](./src/generators/configuration/README.md) for details +See [configuration generator docs](./src/generators/configuration/README.md) for details Examples: - `nx g @code-pushup/nx-plugin:configuration --project=` - `nx g @code-pushup/nx-plugin:configuration --project= --targetName=cp` + +### Executor + +#### Command + +Install JS packages configure a target in your project json. +See [command executor docs](./src/executor/command/README.md) for details + +Examples: + +```json +{ + "name": "my-project", + "targets": { + "code-pushup": { + "executor": "@code-pushup/nx-plugin:command", + "options": { + "projectPrefix": "workspace-name" + } + } + } +} +``` + +- `nx run :code-pushup` +- `nx run :code-pushup print-config --persist.filename=custom-report` diff --git a/packages/nx-plugin/docs/images/nx-plugin-dynamic-target-configuration.png b/packages/nx-plugin/docs/images/nx-plugin-dynamic-target-configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..6184f2e39cd47a6b546202d25ffc83164bc8faee GIT binary patch literal 48819 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%0AX8a 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/project.json { "name": "my-project", "targets": { "code-pushup": { - "executor": "@code-pushup/nx-plugin:autorun" + "executor": "@code-pushup/nx-plugin:command" } } } ``` +Run +`nx run :code-pushup` + +```text +Root/ +├── .code-pushup/ +│ ├── report.json 👈 generated +│ └── report.md 👈 generated +├── project-name/ +│ ├── project.json +│ ├── code-pushup.config.ts 👈 executed +│ └── ... +└── ... +``` + By default, the Nx plugin will derive the options from the executor config. The following things happen: diff --git a/packages/nx-plugin/src/executors/autorun/executor.integration.test.ts b/packages/nx-plugin/src/executors/command/executor.integration.test.ts similarity index 100% rename from packages/nx-plugin/src/executors/autorun/executor.integration.test.ts rename to packages/nx-plugin/src/executors/command/executor.integration.test.ts diff --git a/packages/nx-plugin/src/executors/autorun/executor.ts b/packages/nx-plugin/src/executors/command/executor.ts similarity index 78% rename from packages/nx-plugin/src/executors/autorun/executor.ts rename to packages/nx-plugin/src/executors/command/executor.ts index 0c6ffd984..f22314c95 100644 --- a/packages/nx-plugin/src/executors/autorun/executor.ts +++ b/packages/nx-plugin/src/executors/command/executor.ts @@ -3,10 +3,8 @@ import { ExecutorContext, logger } from '@nx/devkit'; import { execSync } from 'node:child_process'; import { createCliCommand } from '../internal/cli'; import { normalizeContext } from '../internal/context'; -import { AUTORUN_COMMAND } from './constants'; import { AutorunCommandExecutorOptions } from './schema'; import { parseAutorunExecutorOptions } from './utils'; -import {bold} from "ansis"; export type ExecutorOutput = { success: boolean; @@ -17,18 +15,18 @@ export type ExecutorOutput = { export default function runAutorunExecutor( terminalAndExecutorOptions: AutorunCommandExecutorOptions, context: ExecutorContext, -) { +): Promise { const normalizedContext = normalizeContext(context); const cliArgumentObject = parseAutorunExecutorOptions( terminalAndExecutorOptions, normalizedContext, ); - const { dryRun, verbose, command = AUTORUN_COMMAND } = terminalAndExecutorOptions; + const { dryRun, verbose, command } = terminalAndExecutorOptions; - const commandString = createCliCommand(command, cliArgumentObject); + const commandString = createCliCommand({ command, args: cliArgumentObject }); const commandStringOptions = context.cwd ? { cwd: context.cwd } : {}; if (verbose) { - logger.info(`Run CLI executor with commandString: ${bold(command)}`); + logger.info(`Run CLI executor ${command ?? ''}`); logger.info(`Command: ${commandString}`); } if (dryRun) { @@ -42,8 +40,8 @@ export default function runAutorunExecutor( logger.error(error); return Promise.resolve({ success: false, - commandString, - error, + command: commandString, + error: error as Error, }); } } @@ -51,5 +49,5 @@ export default function runAutorunExecutor( return Promise.resolve({ success: true, command: commandString, - } satisfies ExecutorOutput); + }); } diff --git a/packages/nx-plugin/src/executors/autorun/executor.unit.test.ts b/packages/nx-plugin/src/executors/command/executor.unit.test.ts similarity index 87% rename from packages/nx-plugin/src/executors/autorun/executor.unit.test.ts rename to packages/nx-plugin/src/executors/command/executor.unit.test.ts index 580bab156..f19386933 100644 --- a/packages/nx-plugin/src/executors/autorun/executor.unit.test.ts +++ b/packages/nx-plugin/src/executors/command/executor.unit.test.ts @@ -4,7 +4,6 @@ import { execSync } from 'node:child_process'; import { afterEach, beforeEach, expect, vi } from 'vitest'; import { executorContext } from '@code-pushup/test-nx-utils'; import runAutorunExecutor from './executor'; -import {bold} from "ansis"; vi.mock('node:child_process', async () => { const actual = await vi.importActual('node:child_process'); @@ -34,13 +33,13 @@ describe('runAutorunExecutor', () => { envSpy.mockReset().mockReturnValue({}); }); - it('should call execSync with autorun command and return result', async () => { + it('should call execSync with return result', async () => { const output = await runAutorunExecutor({}, executorContext('utils')); expect(output.success).toBe(true); - expect(output.command).toMatch('npx @code-pushup/cli autorun'); + expect(output.command).toMatch('npx @code-pushup/cli'); // eslint-disable-next-line n/no-sync expect(execSync).toHaveBeenCalledWith( - expect.stringContaining('npx @code-pushup/cli autorun'), + expect.stringContaining('npx @code-pushup/cli'), { cwd: '/test' }, ); }); @@ -95,10 +94,10 @@ describe('runAutorunExecutor', () => { expect(loggerWarnSpy).toHaveBeenCalledTimes(0); expect(loggerInfoSpy).toHaveBeenCalledTimes(2); expect(loggerInfoSpy).toHaveBeenCalledWith( - expect.stringContaining(`Run CLI executor with commandString: ${bold('autorun')}`), + expect.stringContaining(`Run CLI executor`), ); expect(loggerInfoSpy).toHaveBeenCalledWith( - expect.stringContaining('Command: npx @code-pushup/cli autorun'), + expect.stringContaining('Command: npx @code-pushup/cli'), ); }); @@ -109,7 +108,7 @@ describe('runAutorunExecutor', () => { expect(loggerWarnSpy).toHaveBeenCalledTimes(1); expect(loggerWarnSpy).toHaveBeenCalledWith( expect.stringContaining( - 'DryRun execution of: npx @code-pushup/cli autorun --dryRun', + 'DryRun execution of: npx @code-pushup/cli --dryRun', ), ); }); diff --git a/packages/nx-plugin/src/executors/autorun/schema.json b/packages/nx-plugin/src/executors/command/schema.json similarity index 100% rename from packages/nx-plugin/src/executors/autorun/schema.json rename to packages/nx-plugin/src/executors/command/schema.json diff --git a/packages/nx-plugin/src/executors/autorun/schema.ts b/packages/nx-plugin/src/executors/command/schema.ts similarity index 100% rename from packages/nx-plugin/src/executors/autorun/schema.ts rename to packages/nx-plugin/src/executors/command/schema.ts diff --git a/packages/nx-plugin/src/executors/autorun/utils.integration.test.ts b/packages/nx-plugin/src/executors/command/utils.integration.test.ts similarity index 100% rename from packages/nx-plugin/src/executors/autorun/utils.integration.test.ts rename to packages/nx-plugin/src/executors/command/utils.integration.test.ts diff --git a/packages/nx-plugin/src/executors/autorun/utils.ts b/packages/nx-plugin/src/executors/command/utils.ts similarity index 100% rename from packages/nx-plugin/src/executors/autorun/utils.ts rename to packages/nx-plugin/src/executors/command/utils.ts diff --git a/packages/nx-plugin/src/executors/autorun/utils.unit.test.ts b/packages/nx-plugin/src/executors/command/utils.unit.test.ts similarity index 100% rename from packages/nx-plugin/src/executors/autorun/utils.unit.test.ts rename to packages/nx-plugin/src/executors/command/utils.unit.test.ts diff --git a/packages/nx-plugin/src/executors/internal/cli.ts b/packages/nx-plugin/src/executors/internal/cli.ts index 1783a052b..82e3153d5 100644 --- a/packages/nx-plugin/src/executors/internal/cli.ts +++ b/packages/nx-plugin/src/executors/internal/cli.ts @@ -1,12 +1,12 @@ -export function createCliCommand( - command: string, - args: Record, - options?: { - bin: string; - }, -): string { - const { bin = '@code-pushup/cli' } = options ?? {}; - return `npx ${bin} ${command} ${objectToCliArgs(args).join(' ')}`; +export function createCliCommand(options?: { + args?: Record; + command?: string; + bin?: string; +}): string { + const { bin = '@code-pushup/cli', command, args } = options ?? {}; + return `npx ${bin} ${objectToCliArgs({ _: command ?? [], ...args }).join( + ' ', + )}`; } type ArgumentValue = number | string | boolean | string[]; @@ -29,7 +29,9 @@ export function objectToCliArgs< // process/file/script if (key === '_') { // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return Array.isArray(value) ? value : [`${value}`]; + return (Array.isArray(value) ? value : [`${value}`]).filter( + v => v != null, + ); } const prefix = key.length === 1 ? '-' : '--'; diff --git a/packages/nx-plugin/src/executors/internal/cli.unit.test.ts b/packages/nx-plugin/src/executors/internal/cli.unit.test.ts index 41892097b..ab39b876b 100644 --- a/packages/nx-plugin/src/executors/internal/cli.unit.test.ts +++ b/packages/nx-plugin/src/executors/internal/cli.unit.test.ts @@ -87,8 +87,13 @@ describe('objectToCliArgs', () => { }); describe('createCliCommand', () => { - it('should create command out of command name and an object for arguments', () => { - const result = createCliCommand('autorun', { verbose: true }); + it('should create command out of object for arguments', () => { + const result = createCliCommand({ args: { verbose: true } }); + expect(result).toBe('npx @code-pushup/cli --verbose'); + }); + + it('should create command out of object for arguments with positional', () => { + const result = createCliCommand({ args: { _: 'autorun', verbose: true } }); expect(result).toBe('npx @code-pushup/cli autorun --verbose'); }); }); diff --git a/packages/nx-plugin/src/executors/internal/types.ts b/packages/nx-plugin/src/executors/internal/types.ts index a7995d991..efb256e8c 100644 --- a/packages/nx-plugin/src/executors/internal/types.ts +++ b/packages/nx-plugin/src/executors/internal/types.ts @@ -20,7 +20,13 @@ export type ProjectExecutorOnlyOptions = { * CLI types that apply globally for all commands. */ export type GlobalExecutorOptions = { - command?: 'collect' | 'upload' | 'autorun' | 'print-config' | 'compare' | 'history'; + command?: + | 'collect' + | 'upload' + | 'autorun' + | 'print-config' + | 'compare' + | 'history'; bin?: string; verbose?: boolean; progress?: boolean; diff --git a/packages/nx-plugin/src/generators/configuration/README.md b/packages/nx-plugin/src/generators/configuration/README.md index 12615bdda..79ab3ec39 100644 --- a/packages/nx-plugin/src/generators/configuration/README.md +++ b/packages/nx-plugin/src/generators/configuration/README.md @@ -4,13 +4,22 @@ ## Usage -`nx generate configuration ...` +`nx generate @code-pushup/nx-plugin:configuration` By default, the Nx plugin will search for existing configuration files. If they are not present it creates a `code-pushup.config.ts` and adds a target to your `project.json` file. -You can specify the collection explicitly as follows: +You can specify the project explicitly as follows: -`nx g @code-pushup/nx-plugin:configuration ...` +`nx g @code-pushup/nx-plugin:configuration ` + +```text +Root/ +├── project-name/ +│ ├── project.json 👈 updated +│ ├── code-pushup.config.ts 👈 generated +│ └── ... +└── ... +``` Show what will be generated without writing to disk: diff --git a/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts b/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts index d2e3f3928..75683ce7b 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts @@ -45,7 +45,7 @@ describe('addTargetToProject', () => { ); expect(projectConfiguration.targets?.[DEFAULT_TARGET_NAME]).toEqual({ - executor: `${PACKAGE_NAME}:autorun`, + executor: `${PACKAGE_NAME}:command`, }); }); @@ -70,7 +70,7 @@ describe('addTargetToProject', () => { ); expect(projectConfiguration.targets?.['cp']).toEqual({ - executor: `${PACKAGE_NAME}:autorun`, + executor: `${PACKAGE_NAME}:command`, }); }); }); @@ -102,7 +102,7 @@ describe('configurationGenerator', () => { ); expect(projectConfiguration.targets?.[DEFAULT_TARGET_NAME]).toEqual({ - executor: `${PACKAGE_NAME}:autorun`, + executor: `${PACKAGE_NAME}:command`, }); }); diff --git a/packages/nx-plugin/src/generators/configuration/generator.ts b/packages/nx-plugin/src/generators/configuration/generator.ts index 604a61aa0..0cb5f28f0 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.ts @@ -46,7 +46,7 @@ export function addTargetToProject( const { targetName, project } = options; const codePushupTargetConfig = { - executor: `${PACKAGE_NAME}:autorun`, + executor: `${PACKAGE_NAME}:command`, }; updateProjectConfiguration(tree, project, { diff --git a/packages/nx-plugin/src/generators/init/README.md b/packages/nx-plugin/src/generators/init/README.md index 53e36abf2..08887e347 100644 --- a/packages/nx-plugin/src/generators/init/README.md +++ b/packages/nx-plugin/src/generators/init/README.md @@ -4,7 +4,7 @@ ## Usage -`nx generate configuration ...` +`nx generate @code-pushup/nx-plugin:init` By default, the Nx plugin will update your `package.json` with needed dependencies and register the plugin in your `nx.json` configuration. @@ -12,6 +12,14 @@ You can specify the collection explicitly as follows: `nx g @code-pushup/nx-plugin:init` +```text +Root/ +├── ... +├── nx.json 👈 updated +├── package.json 👈 updated +└── ... +``` + Show what will be generated without writing to disk: `nx g @code-pushup/nx-plugin:init --dry-run` diff --git a/packages/nx-plugin/src/plugin/README.md b/packages/nx-plugin/src/plugin/README.md new file mode 100644 index 000000000..1ff22e522 --- /dev/null +++ b/packages/nx-plugin/src/plugin/README.md @@ -0,0 +1,107 @@ +# @code-pushup/nx-plugin + +The Nx Plugin for CodePushup, an open source code quality and conformance tool. + +Why should you use this plugin? + +- Zero setup cost. Just run the `init` generator and you're good to go. +- Smoother CI integration +- Minimal configuration +- Automated setup, migration and maintenance + +## Usage + +```jsonc +// nx.json +{ + //... + "plugins": ["@code-pushup/nx-plugin"] +} +``` + +or with options: + +```jsonc +// nx.json +{ + //... + "plugins": [ + { + "plugin": "@code-pushup/nx-plugin", + "options": { + "projectPrefix": "cli" + } + } + ] +} +``` + +Now every project will have `code-pushup--configuration` target if no `code-pushup.{ts,mjs,js}` is present. + +- `nx run :code-pushup--configuration` +- `nx run :code-pushup--configuration --skipFormat` + +Run it and the project will get automatically configured. + +```text +Root/ +├── project-name/ +│ ├── code-pushup.config.ts 👈 generated +│ └── ... +└── ... +``` + +For details visit the [configuration generator docs](../../src/generators/configuration/README.md). + +With the configuration from above a `code-pushup` target is now present. + +- `nx run :code-pushup` + +Run it and the project will get automatically collect the report. + +```text +Root/ +├── .code-pushup/ +│ └── project-name +│ ├── report.md 👈 generated +│ └── report.json 👈 generated +├── project-name/ +│ ├── code-pushup.config.ts +│ └── ... +└── ... +``` + +Pass positional arguments to execute a specific command, use named arguments to overwrite defaults. + +- `nx run :code-pushup --onlyPlugins=eslint` +- `nx run :code-pushup collect` +- `nx run :code-pushup upload --upload.server=https://staging.code-pushup.dev` + +For a full list of command visit the [CodePushup CLI documentation](../../../cli/README.md#commands). + +## Options + +| Name | type | description | +| ----------------- | -------------------------------- | ------------------------------------------------------ | +| **projectPrefix** | `string` | prefix for upload.project on non root projects | +| **targetName** | `string` (DEFAULT 'code-pushup') | The id used to identify a target in your project.json. | +| **bin** | `string` | Path to Code PushUp CLI | + +All options are optional and provided in the `nx.json` file. + +```jsonc +// nx.json +{ + //... + "plugins": [ + { + "plugin": "@code-pushup/nx-plugin", + "options": { + "projectPrefix": "cli" + "targetName": "cp" + "bin": "dist/package/code-pushup-custom-build" + } + } + ] +} +``` diff --git a/packages/nx-plugin/src/plugin/target/executor-target.ts b/packages/nx-plugin/src/plugin/target/executor-target.ts index 14eaaff07..3ba0d3eed 100644 --- a/packages/nx-plugin/src/plugin/target/executor-target.ts +++ b/packages/nx-plugin/src/plugin/target/executor-target.ts @@ -7,6 +7,6 @@ export function createExecutorTarget(options?: { }): TargetConfiguration { const { bin = PACKAGE_NAME } = options ?? {}; return { - executor: `${bin}:autorun`, + executor: `${bin}:command`, }; } diff --git a/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts b/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts index 245fc4c66..4c132bf0a 100644 --- a/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts +++ b/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts @@ -4,13 +4,13 @@ import { createExecutorTarget } from './executor-target'; describe('createExecutorTarget', () => { it('should return executor target without project name', () => { expect(createExecutorTarget()).toStrictEqual({ - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', }); }); it('should use bin if provides', () => { expect(createExecutorTarget({ bin: 'xyz' })).toStrictEqual({ - executor: 'xyz:autorun', + executor: 'xyz:command', }); }); }); diff --git a/packages/nx-plugin/src/plugin/target/targets.unit.test.ts b/packages/nx-plugin/src/plugin/target/targets.unit.test.ts index fcb6fc0f4..b829e57fa 100644 --- a/packages/nx-plugin/src/plugin/target/targets.unit.test.ts +++ b/packages/nx-plugin/src/plugin/target/targets.unit.test.ts @@ -108,7 +108,7 @@ describe('createTargets', () => { ).resolves.toStrictEqual( expect.objectContaining({ [targetName]: { - executor: `${PACKAGE_NAME}:autorun`, + executor: `${PACKAGE_NAME}:command`, }, }), ); @@ -132,7 +132,7 @@ describe('createTargets', () => { } as NormalizedCreateNodesContext), ).resolves.toStrictEqual({ [DEFAULT_TARGET_NAME]: { - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', }, }); }); @@ -157,7 +157,7 @@ describe('createTargets', () => { } as NormalizedCreateNodesContext), ).resolves.toStrictEqual({ cp: { - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', }, }); }); diff --git a/testing/test-utils/src/index.ts b/testing/test-utils/src/index.ts index 19e1fa5ac..a2de808ca 100644 --- a/testing/test-utils/src/index.ts +++ b/testing/test-utils/src/index.ts @@ -12,6 +12,7 @@ export * from './lib/utils/commit.mock'; export * from './lib/utils/core-config.mock'; export * from './lib/utils/minimal-config.mock'; export * from './lib/utils/report.mock'; +export * from './lib/fixtures/configs/custom-plugin'; // dynamic mocks export * from './lib/utils/dynamic-mocks/categories.mock'; diff --git a/testing/test-utils/src/lib/fixtures/configs/custom-plugin.ts b/testing/test-utils/src/lib/fixtures/configs/custom-plugin.ts index d385c066a..6afe6bc80 100644 --- a/testing/test-utils/src/lib/fixtures/configs/custom-plugin.ts +++ b/testing/test-utils/src/lib/fixtures/configs/custom-plugin.ts @@ -1,4 +1,4 @@ -const customPlugin = { +const customPluginConfig = { slug: 'good-feels', title: 'Good feels', icon: 'javascript', @@ -18,4 +18,7 @@ const customPlugin = { ], }; -export default customPlugin; +export function customPlugin() { + return customPluginConfig; +} +export default customPluginConfig; From 942039bf7575468748048eb3e7bcfecb665eed2e Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 14 Aug 2024 20:45:51 +0200 Subject: [PATCH 03/32] add upload defaults --- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts index b1d3627f3..0b3683529 100644 --- a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts @@ -52,6 +52,11 @@ async function addTargetToWorkspace( codeStrings: 'customPlugin()', }, ], + upload: { + server: 'http://staging.code-pushup.dev', + organization: 'code-pushup', + apiKey: '12345678', + }, }); await materializeTree(tree, cwd); } @@ -72,7 +77,6 @@ describe('CLI executor', () => { it('should execute no command by default', async () => { const cwd = join(baseDir, 'execute-default-executor'); await addTargetToWorkspace(tree, { cwd, project }); - const { stdout, code } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, '--dryRun'], From a51ffd75b8f2a1853350b565ed104f63a0e2f9b2 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 14 Aug 2024 21:16:20 +0200 Subject: [PATCH 04/32] remove warning --- package-lock.json | 431 ++++++++++++++++++++++++++++++++++++++++------ package.json | 3 +- 2 files changed, 380 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf14d59f0..92c30bbb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,8 +47,9 @@ "@nx/react": "17.3.2", "@nx/vite": "17.3.2", "@nx/workspace": "17.3.2", + "@swc-node/register": "^1.10.9", "@swc/cli": "~0.1.62", - "@swc/core": "1.3.99", + "@swc/core": "^1.3.99", "@testing-library/jest-dom": "^6.4.2", "@testing-library/react": "^14.0.0", "@trivago/prettier-plugin-sort-imports": "^4.2.0", @@ -2909,6 +2910,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/@emnapi/core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", + "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", + "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@ericcornelissen/bash-parser": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@ericcornelissen/bash-parser/-/bash-parser-0.5.2.tgz", @@ -4269,6 +4301,18 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-3.0.0.tgz", @@ -5659,6 +5703,152 @@ "node": ">=8" } }, + "node_modules/@oxc-resolver/binding-darwin-arm64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.10.2.tgz", + "integrity": "sha512-aOCZYXqmFL+2sXlaVkYbAOtICGGeTFtmdul8OimQfOXHJods6YHJ2nR6+rEeBcJzaXyXPP18ne1IsEc4AYL1IA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-darwin-x64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-1.10.2.tgz", + "integrity": "sha512-6WD7lHGkoduFZfUgnC2suKOlqttQRKxWsiVXiiGPu3mfXvQAhMd/gekuH1t8vOhFlPJduaww15n5UB0bSjCK+w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-freebsd-x64": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-1.10.2.tgz", + "integrity": "sha512-nEqHWx/Ot5p7Mafj8qH6vFlLSvHjECxAcZwhnAMqRuQu1NgXC/QM3emkdhVGy7QJgsxZbHpPaF6TERNf5/NL9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.10.2.tgz", + "integrity": "sha512-+AlZI0fPnpfArh8aC5k2295lmQrxa2p8gBLxC3buvCkz0ZpbVLxyyAXz3J2jGwJnmc5MUPLEqPYw6ZlAGH4XHA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.10.2.tgz", + "integrity": "sha512-8fZ8NszFaUZaoA8eUwkF2lHjgUs76aFiewWgG/cjcZmwKp+ErZQLW8eOvIWZ4SohHQ+ScvhVsSaU2PU38c88gw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-musl": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.10.2.tgz", + "integrity": "sha512-oPrLICrw96Ym9n04FWXWGkbkpF6qJtZ57JSnqI3oQ24xHTt4iWyjHKHQO46NbJAK9sFb3Qce4BzV8faDI5Rifg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-gnu": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.10.2.tgz", + "integrity": "sha512-eli74jTAUiIfqi8IPFqiPxQS69Alcr6w/IFRyf3XxrkxeFGgcgxJkRIxWNTKJ6T3EXxjuma+49LdZn6l9rEj7A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-musl": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-1.10.2.tgz", + "integrity": "sha512-HH9zmjNSQo3rkbqJH5nIjGrtjC+QPrUy0KGGMR/oRCSLuD0cNFJ/Uly1XAugwSm4oEw0+rv6PmeclXmVTKsxhw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-wasm32-wasi": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-1.10.2.tgz", + "integrity": "sha512-3ItX23q33sfVBtMMdMhVDSe0NX5zBHxHfmFiXhSJuwNaVIwGpLFU7WU2nmq9oNdnmTOvjL8vlhOqiGvumBLlRA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.10.2.tgz", + "integrity": "sha512-aVoj2V+jmQ1N+lVy9AhaLmzssJM0lcKt8D0UL83aNLZJ5lSN7hgBuUXTVmL+VF268f167khjo38z+fbELDVm8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxc-resolver/binding-win32-x64-msvc": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.10.2.tgz", + "integrity": "sha512-l8BDQWyP0Piw8hlmYPUqTRKLsq+ceG9h+9p6ZrjNzwW9AmJX7T7T2hgoVVHqS6f4WNA/CFkb3RyZP9QTzNkyyA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@paulirish/trace_engine": { "version": "0.0.19", "resolved": "https://registry.npmjs.org/@paulirish/trace_engine/-/trace_engine-0.0.19.tgz", @@ -6629,6 +6819,92 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@swc-node/core": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", + "integrity": "sha512-OGsvXIid2Go21kiNqeTIn79jcaX4l0G93X2rAnas4LFoDyA9wAwVK7xZdm+QsKoMn5Mus2yFLCc4OtX2dD/PWA==", + "devOptional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@swc/core": ">= 1.4.13", + "@swc/types": ">= 0.1" + } + }, + "node_modules/@swc-node/register": { + "version": "1.10.9", + "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.10.9.tgz", + "integrity": "sha512-iXy2sjP0phPEpK2yivjRC3PAgoLaT4sjSk0LDWCTdcTBJmR4waEog0E6eJbvoOkLkOtWw37SB8vCkl/bbh4+8A==", + "devOptional": true, + "dependencies": { + "@swc-node/core": "^1.13.3", + "@swc-node/sourcemap-support": "^0.5.1", + "colorette": "^2.0.20", + "debug": "^4.3.5", + "oxc-resolver": "^1.10.2", + "pirates": "^4.0.6", + "tslib": "^2.6.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@swc/core": ">= 1.4.13", + "typescript": ">= 4.3" + } + }, + "node_modules/@swc-node/register/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "devOptional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@swc-node/sourcemap-support": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz", + "integrity": "sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg==", + "devOptional": true, + "dependencies": { + "source-map-support": "^0.5.21", + "tslib": "^2.6.3" + } + }, + "node_modules/@swc-node/sourcemap-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@swc-node/sourcemap-support/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/@swc/cli": { "version": "0.1.65", "resolved": "https://registry.npmjs.org/@swc/cli/-/cli-0.1.65.tgz", @@ -6662,14 +6938,14 @@ } }, "node_modules/@swc/core": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.99.tgz", - "integrity": "sha512-8O996RfuPC4ieb4zbYMfbyCU9k4gSOpyCNnr7qBQ+o7IEmh8JCV6B8wwu+fT/Om/6Lp34KJe1IpJ/24axKS6TQ==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.11.tgz", + "integrity": "sha512-AB+qc45UrJrDfbhPKcUXk+9z/NmFfYYwJT6G7/iur0fCse9kXjx45gi40+u/O2zgarG/30/zV6E3ps8fUvjh7g==", "devOptional": true, "hasInstallScript": true, "dependencies": { - "@swc/counter": "^0.1.1", - "@swc/types": "^0.1.5" + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" }, "engines": { "node": ">=10" @@ -6679,18 +6955,19 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.99", - "@swc/core-darwin-x64": "1.3.99", - "@swc/core-linux-arm64-gnu": "1.3.99", - "@swc/core-linux-arm64-musl": "1.3.99", - "@swc/core-linux-x64-gnu": "1.3.99", - "@swc/core-linux-x64-musl": "1.3.99", - "@swc/core-win32-arm64-msvc": "1.3.99", - "@swc/core-win32-ia32-msvc": "1.3.99", - "@swc/core-win32-x64-msvc": "1.3.99" + "@swc/core-darwin-arm64": "1.7.11", + "@swc/core-darwin-x64": "1.7.11", + "@swc/core-linux-arm-gnueabihf": "1.7.11", + "@swc/core-linux-arm64-gnu": "1.7.11", + "@swc/core-linux-arm64-musl": "1.7.11", + "@swc/core-linux-x64-gnu": "1.7.11", + "@swc/core-linux-x64-musl": "1.7.11", + "@swc/core-win32-arm64-msvc": "1.7.11", + "@swc/core-win32-ia32-msvc": "1.7.11", + "@swc/core-win32-x64-msvc": "1.7.11" }, "peerDependencies": { - "@swc/helpers": "^0.5.0" + "@swc/helpers": "*" }, "peerDependenciesMeta": { "@swc/helpers": { @@ -6699,9 +6976,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.99.tgz", - "integrity": "sha512-Qj7Jct68q3ZKeuJrjPx7k8SxzWN6PqLh+VFxzA+KwLDpQDPzOlKRZwkIMzuFjLhITO4RHgSnXoDk/Syz0ZeN+Q==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.11.tgz", + "integrity": "sha512-HRQv4qIeMBPThZ6Y/4yYW52rGsS6yrpusvuxLGyoFo45Y0y12/V2yXkOIA/0HIQyrqoUAxn1k4zQXpPaPNCmnw==", "cpu": [ "arm64" ], @@ -6715,9 +6992,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.99.tgz", - "integrity": "sha512-wR7m9QVJjgiBu1PSOHy7s66uJPa45Kf9bZExXUL+JAa9OQxt5y+XVzr+n+F045VXQOwdGWplgPnWjgbUUHEVyw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.11.tgz", + "integrity": "sha512-vtMQj0F3oYwDu5yhO7SKDRg1XekRSi6/TbzHAbBXv+dBhlGGvcZZynT1H90EVFTv+7w7Sh+lOFvRv5Z4ZTcxow==", "cpu": [ "x64" ], @@ -6730,10 +7007,26 @@ "node": ">=10" } }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.11.tgz", + "integrity": "sha512-mHtzWKxhtyreI4CSxs+3+ENv8t/Qo35WFoYG66qHEgJz/Z2Lh6jv1E+MYgHdYwnpQHgHbdvAco7HsBu/Dt6xXw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.99.tgz", - "integrity": "sha512-gcGv1l5t0DScEONmw5OhdVmEI/o49HCe9Ik38zzH0NtDkc+PDYaCcXU5rvfZP2qJFaAAr8cua8iJcOunOSLmnA==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.11.tgz", + "integrity": "sha512-FRwe/x0GfXSQjGP2lIk+NO0pUFS/lI/RorCLBPiK808EVE9JTbh9DKCc/4Bbb4jgScAjNkrFCUVObQYl3YKmpA==", "cpu": [ "arm64" ], @@ -6747,9 +7040,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.99.tgz", - "integrity": "sha512-XL1/eUsTO8BiKsWq9i3iWh7H99iPO61+9HYiWVKhSavknfj4Plbn+XyajDpxsauln5o8t+BRGitymtnAWJM4UQ==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.11.tgz", + "integrity": "sha512-GY/rs0+GUq14Gbnza90KOrQd/9yHd5qQMii5jcSWcUCT5A8QTa8kiicsM2NxZeTJ69xlKmT7sLod5l99lki/2A==", "cpu": [ "arm64" ], @@ -6763,9 +7056,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.99.tgz", - "integrity": "sha512-fGrXYE6DbTfGNIGQmBefYxSk3rp/1lgbD0nVg4rl4mfFRQPi7CgGhrrqSuqZ/ezXInUIgoCyvYGWFSwjLXt/Qg==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.11.tgz", + "integrity": "sha512-QDkGRwSPmp2RBOlSs503IUXlWYlny8DyznTT0QuK0ML2RpDFlXWU94K/EZhS0RBEUkMY/W51OacM8P8aS/dkCg==", "cpu": [ "x64" ], @@ -6779,9 +7072,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.99.tgz", - "integrity": "sha512-kvgZp/mqf3IJ806gUOL6gN6VU15+DfzM1Zv4Udn8GqgXiUAvbQehrtruid4Snn5pZTLj4PEpSCBbxgxK1jbssA==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.11.tgz", + "integrity": "sha512-SBEfKrXy6zQ6ksnyxw1FaCftrIH4fLfA81xNnKb7x/6iblv7Ko6H0aK3P5C86jyqF/82+ONl9C7ImGkUFQADig==", "cpu": [ "x64" ], @@ -6795,9 +7088,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.99.tgz", - "integrity": "sha512-yt8RtZ4W/QgFF+JUemOUQAkVW58cCST7mbfKFZ1v16w3pl3NcWd9OrtppFIXpbjU1rrUX2zp2R7HZZzZ2Zk/aQ==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.11.tgz", + "integrity": "sha512-a2Y4xxEsLLYHJN7sMnw9+YQJDi3M1BxEr9hklfopPuGGnYLFNnx5CypH1l9ReijEfWjIAHNi7pq3m023lzW1Hg==", "cpu": [ "arm64" ], @@ -6811,9 +7104,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.99.tgz", - "integrity": "sha512-62p5fWnOJR/rlbmbUIpQEVRconICy5KDScWVuJg1v3GPLBrmacjphyHiJC1mp6dYvvoEWCk/77c/jcQwlXrDXw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.11.tgz", + "integrity": "sha512-ZbZFMwZO+j8ulhegJ7EhJ/QVZPoQ5qc30ylJQSxizizTJaen71Q7/13lXWc6ksuCKvg6dUKrp/TPgoxOOtSrFA==", "cpu": [ "ia32" ], @@ -6827,9 +7120,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.99", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.99.tgz", - "integrity": "sha512-PdppWhkoS45VGdMBxvClVgF1hVjqamtvYd82Gab1i4IV45OSym2KinoDCKE1b6j3LwBLOn2J9fvChGSgGfDCHQ==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.11.tgz", + "integrity": "sha512-IUohZedSJyDu/ReEBG/mqX6uG29uA7zZ9z6dIAF+p6eFxjXmh9MuHryyM+H8ebUyoq/Ad3rL+rUCksnuYNnI0w==", "cpu": [ "x64" ], @@ -6857,9 +7150,9 @@ } }, "node_modules/@swc/types": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", - "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", "devOptional": true, "dependencies": { "@swc/counter": "^0.1.3" @@ -7235,6 +7528,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", @@ -10179,7 +10482,7 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/build-md": { @@ -10907,7 +11210,7 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "devOptional": true }, "node_modules/columnify": { "version": "1.6.0", @@ -20932,6 +21235,28 @@ "node": ">=0.10.0" } }, + "node_modules/oxc-resolver": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-1.10.2.tgz", + "integrity": "sha512-NIbwVqoU8Bhl7PVtItHCg+VFFokIDwBgIgFUwFG2Y8ePhxftFh5xG+KLar5PLWXlCP4WunPIuXD3jr3v6/MfRw==", + "devOptional": true, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-resolver/binding-darwin-arm64": "1.10.2", + "@oxc-resolver/binding-darwin-x64": "1.10.2", + "@oxc-resolver/binding-freebsd-x64": "1.10.2", + "@oxc-resolver/binding-linux-arm-gnueabihf": "1.10.2", + "@oxc-resolver/binding-linux-arm64-gnu": "1.10.2", + "@oxc-resolver/binding-linux-arm64-musl": "1.10.2", + "@oxc-resolver/binding-linux-x64-gnu": "1.10.2", + "@oxc-resolver/binding-linux-x64-musl": "1.10.2", + "@oxc-resolver/binding-wasm32-wasi": "1.10.2", + "@oxc-resolver/binding-win32-arm64-msvc": "1.10.2", + "@oxc-resolver/binding-win32-x64-msvc": "1.10.2" + } + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -21496,7 +21821,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 6" } @@ -24319,9 +24644,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -24534,7 +24859,7 @@ "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index a36668097..82d990d4f 100644 --- a/package.json +++ b/package.json @@ -59,8 +59,9 @@ "@nx/react": "17.3.2", "@nx/vite": "17.3.2", "@nx/workspace": "17.3.2", + "@swc-node/register": "^1.10.9", "@swc/cli": "~0.1.62", - "@swc/core": "1.3.99", + "@swc/core": "^1.3.99", "@testing-library/jest-dom": "^6.4.2", "@testing-library/react": "^14.0.0", "@trivago/prettier-plugin-sort-imports": "^4.2.0", From a94feeb1d05dbf2901f21f2f711cc8d9be1b4b7c Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 14 Aug 2024 21:22:30 +0200 Subject: [PATCH 05/32] set default upload options --- e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts b/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts index 898dd73b0..00bb62d67 100644 --- a/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/nx-plugin.e2e.test.ts @@ -198,6 +198,11 @@ describe('nx-plugin', () => { codeStrings: 'await jsPackagesPlugin({packageManager: `npm`})', }, ], + upload: { + server: 'http://staging.code-pushup.dev', + organization: 'code-pushup', + apiKey: '12345678', + }, }); await materializeTree(tree, cwd); From 0ae3a4e549a196d4b898800325a11e32b241ddd0 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 14 Aug 2024 21:49:46 +0200 Subject: [PATCH 06/32] wip --- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 10 +++++----- packages/nx-plugin/package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts index 0b3683529..90a34de77 100644 --- a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts @@ -75,7 +75,7 @@ describe('CLI executor', () => { }); it('should execute no command by default', async () => { - const cwd = join(baseDir, 'execute-default-executor'); + const cwd = join(baseDir, 'execute-default-command'); await addTargetToWorkspace(tree, { cwd, project }); const { stdout, code } = await executeProcess({ command: 'npx', @@ -89,7 +89,7 @@ describe('CLI executor', () => { }); it('should execute print-config executor', async () => { - const cwd = join(baseDir, 'execute-print-config-executor'); + const cwd = join(baseDir, 'execute-print-config-command'); await addTargetToWorkspace(tree, { cwd, project }); const { stdout, code } = await executeProcess({ @@ -108,7 +108,7 @@ describe('CLI executor', () => { }); it('should execute collect executor', async () => { - const cwd = join(baseDir, 'execute-collect-executor'); + const cwd = join(baseDir, 'execute-collect-command'); await addTargetToWorkspace(tree, { cwd, project }); const { stdout, code } = await executeProcess({ @@ -142,7 +142,7 @@ describe('CLI executor', () => { }); it('should execute upload executor to throw if no report is present', async () => { - const cwd = join(baseDir, 'execute-upload-executor'); + const cwd = join(baseDir, 'execute-upload-command'); await addTargetToWorkspace(tree, { cwd, project }); const { stdout, code } = await executeProcess({ @@ -157,7 +157,7 @@ describe('CLI executor', () => { }); it('should execute autorun executor', async () => { - const cwd = join(baseDir, 'execute-autorun-executor'); + const cwd = join(baseDir, 'execute-autorun-command'); await addTargetToWorkspace(tree, { cwd, project }); const { stdout, code } = await executeProcess({ diff --git a/packages/nx-plugin/package.json b/packages/nx-plugin/package.json index fe0805057..13a9d200a 100644 --- a/packages/nx-plugin/package.json +++ b/packages/nx-plugin/package.json @@ -5,7 +5,7 @@ "description": "Nx plugin to integrate the Code PushUp CLI into your workspace 🛠️", "dependencies": { "@nx/devkit": "^17.1.3", - "tslib": "2.6.2", + "tslib": "2.6.3", "nx": "^17.1.3", "@code-pushup/models": "*", "zod": "^3.22.4", From 97bbbe79eaa840535d4dee538670d83d800877de Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 19 Aug 2024 22:22:55 +0200 Subject: [PATCH 07/32] wip --- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts index 90a34de77..0f2945127 100644 --- a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts @@ -53,6 +53,7 @@ async function addTargetToWorkspace( }, ], upload: { + project: 'my-lib', server: 'http://staging.code-pushup.dev', organization: 'code-pushup', apiKey: '12345678', From c47d04b18997d5c648ed6c23e50a8a1de3044999 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 25 Aug 2024 16:06:26 +0200 Subject: [PATCH 08/32] fix tests --- e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts | 4 ++-- e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts | 6 +++--- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 2 +- packages/nx-plugin/src/plugin/plugin.unit.test.ts | 4 ++-- .../src/plugin/target/executor.target.unit.test.ts | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts b/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts index d19872958..700956d10 100644 --- a/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts @@ -206,7 +206,7 @@ describe('nx-plugin', () => { await materializeTree(tree, cwd); - const { stdout } = await executeProcess({ + const { stdout, stderr } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, '--dryRun'], cwd, @@ -263,7 +263,7 @@ describe('nx-plugin', () => { expect(projectJson.targets).toStrictEqual({ ['code-pushup']: expect.objectContaining({ - executor: `@code-pushup/nx-plugin:autorun`, + executor: `@code-pushup/nx-plugin:command`, options: { projectPrefix: 'cli', }, diff --git a/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts index c265949bc..3efe65575 100644 --- a/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts @@ -30,7 +30,7 @@ async function addTargetToWorkspace( executor: `${join( relativePathToCwd(cwd), 'dist/packages/nx-plugin', - )}:autorun`, + )}:command`, }, }, }); @@ -55,7 +55,7 @@ async function addTargetToWorkspace( await materializeTree(tree, cwd); } -describe('executor autorun', () => { +describe('executor command', () => { let tree: Tree; const project = 'my-lib'; const baseDir = 'tmp/nx-plugin-e2e/executor'; @@ -68,7 +68,7 @@ describe('executor autorun', () => { await rm(baseDir, { recursive: true, force: true }); }); - it('should execute autorun executor', async () => { + it('should execute command executor', async () => { const cwd = join(baseDir, 'execute-dynamic-executor'); await addTargetToWorkspace(tree, { cwd, project }); diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts index 0f2945127..88c07b856 100644 --- a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts @@ -158,7 +158,7 @@ describe('CLI executor', () => { }); it('should execute autorun executor', async () => { - const cwd = join(baseDir, 'execute-autorun-command'); + const cwd = join(baseDir, 'execute-command-command'); await addTargetToWorkspace(tree, { cwd, project }); const { stdout, code } = await executeProcess({ diff --git a/packages/nx-plugin/src/plugin/plugin.unit.test.ts b/packages/nx-plugin/src/plugin/plugin.unit.test.ts index 56854b225..5dd988650 100644 --- a/packages/nx-plugin/src/plugin/plugin.unit.test.ts +++ b/packages/nx-plugin/src/plugin/plugin.unit.test.ts @@ -94,7 +94,7 @@ describe('@code-pushup/nx-plugin/plugin', () => { [projectRoot]: { targets: { [CP_TARGET_NAME]: { - executor: `${PACKAGE_NAME}:autorun`, + executor: `${PACKAGE_NAME}:command`, options: { projectPrefix: 'cli', }, @@ -126,7 +126,7 @@ describe('@code-pushup/nx-plugin/plugin', () => { [projectRoot]: { targets: { [CP_TARGET_NAME]: { - executor: `${PACKAGE_NAME}:autorun`, + executor: `${PACKAGE_NAME}:command`, options: { projectPrefix: 'cli', }, diff --git a/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts b/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts index c5edea928..40d3bb7ba 100644 --- a/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts +++ b/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts @@ -16,7 +16,7 @@ describe('createExecutorTarget', () => { it('should use projectPrefix if provided', () => { expect(createExecutorTarget({ projectPrefix: 'cli' })).toStrictEqual({ - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:command', options: { projectPrefix: 'cli', }, From 87f3dec96d080fc8d2179d2687f15e13d364283d Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 25 Aug 2024 16:27:16 +0200 Subject: [PATCH 09/32] reduce code in registry configuration --- tools/scripts/utils.ts | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/tools/scripts/utils.ts b/tools/scripts/utils.ts index 231df343f..745934749 100644 --- a/tools/scripts/utils.ts +++ b/tools/scripts/utils.ts @@ -6,28 +6,9 @@ export function configureRegistry({ registry, registryNoProtocol, }: RegistryData) { - /** - * Sets environment variables for NPM and Yarn registries, and optionally configures - * Yarn's unsafe HTTP whitelist. - * - * @param {string} registry - The registry URL to set for NPM and Yarn. - * @param {string} host - The hostname to whitelist for Yarn (optional). - * - * Variables Set: - * - `npm_config_registry`: NPM registry. - * - `YARN_REGISTRY`: Yarn v1 registry. - * - `YARN_NPM_REGISTRY_SERVER`: Yarn v2 registry. - * - `YARN_UNSAFE_HTTP_WHITELIST`: Yarn HTTP whitelist. - */ - process.env.npm_config_registry = registry; - process.env.YARN_REGISTRY = registry; - process.env.YARN_NPM_REGISTRY_SERVER = registry; - console.info(`Set NPM and yarn registry process.env`); + console.info(`Set NPM registry under location user to ${registry}`); + execSync(`npm config set registry "${registry}"`); - /** - * Optional: Set Yarn HTTP whitelist for non-HTTPS registries. - */ - process.env.YARN_UNSAFE_HTTP_WHITELIST = host; console.info(`Set yarn whitelíst process.env`); /** @@ -44,6 +25,7 @@ export function configureRegistry({ export function unconfigureRegistry({ registryNoProtocol, }: Pick) { + execSync('npm config delete registry'); execSync(`npm config delete ${registryNoProtocol}/:_authToken`); console.info('delete npm authToken: ' + registryNoProtocol); } From 3b9540d5e577a43fe88f795cdcd91a2d844c12dd Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 27 Aug 2024 00:32:50 +0200 Subject: [PATCH 10/32] rename executor from command to cli --- .../__snapshots__/create-nodes-plugin.e2e.test.ts.snap | 4 ++-- e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts | 6 +++--- e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts | 2 +- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 2 +- .../tests/generator-configuration.e2e.test.ts | 8 ++++---- packages/nx-plugin/README.md | 6 +++--- packages/nx-plugin/executors.json | 8 ++++---- .../nx-plugin/src/executors/{command => cli}/README.md | 4 ++-- .../{command => cli}/executor.integration.test.ts | 0 .../nx-plugin/src/executors/{command => cli}/executor.ts | 0 .../src/executors/{command => cli}/executor.unit.test.ts | 0 .../nx-plugin/src/executors/{command => cli}/schema.json | 0 .../nx-plugin/src/executors/{command => cli}/schema.ts | 0 .../executors/{command => cli}/utils.integration.test.ts | 0 .../nx-plugin/src/executors/{command => cli}/utils.ts | 0 .../src/executors/{command => cli}/utils.unit.test.ts | 0 .../configuration/generator.integration.test.ts | 6 +++--- .../nx-plugin/src/generators/configuration/generator.ts | 2 +- packages/nx-plugin/src/plugin/plugin.unit.test.ts | 4 ++-- packages/nx-plugin/src/plugin/target/executor-target.ts | 2 +- .../src/plugin/target/executor.target.unit.test.ts | 6 +++--- packages/nx-plugin/src/plugin/target/targets.unit.test.ts | 6 +++--- 22 files changed, 33 insertions(+), 33 deletions(-) rename packages/nx-plugin/src/executors/{command => cli}/README.md (96%) rename packages/nx-plugin/src/executors/{command => cli}/executor.integration.test.ts (100%) rename packages/nx-plugin/src/executors/{command => cli}/executor.ts (100%) rename packages/nx-plugin/src/executors/{command => cli}/executor.unit.test.ts (100%) rename packages/nx-plugin/src/executors/{command => cli}/schema.json (100%) rename packages/nx-plugin/src/executors/{command => cli}/schema.ts (100%) rename packages/nx-plugin/src/executors/{command => cli}/utils.integration.test.ts (100%) rename packages/nx-plugin/src/executors/{command => cli}/utils.ts (100%) rename packages/nx-plugin/src/executors/{command => cli}/utils.unit.test.ts (100%) diff --git a/e2e/nx-plugin-e2e/tests/__snapshots__/create-nodes-plugin.e2e.test.ts.snap b/e2e/nx-plugin-e2e/tests/__snapshots__/create-nodes-plugin.e2e.test.ts.snap index ac560ebc9..f3df74338 100644 --- a/e2e/nx-plugin-e2e/tests/__snapshots__/create-nodes-plugin.e2e.test.ts.snap +++ b/e2e/nx-plugin-e2e/tests/__snapshots__/create-nodes-plugin.e2e.test.ts.snap @@ -14,7 +14,7 @@ exports[`nx-plugin > should NOT add config targets dynamically if the project is "targets": { "code-pushup": { "configurations": {}, - "executor": "@code-pushup/nx-plugin:command", + "executor": "@code-pushup/nx-plugin:cli", "options": {}, }, }, @@ -58,7 +58,7 @@ exports[`nx-plugin > should add executor target dynamically if the project is co "targets": { "code-pushup": { "configurations": {}, - "executor": "@code-pushup/nx-plugin:command", + "executor": "@code-pushup/nx-plugin:cli", "options": {}, }, }, diff --git a/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts b/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts index 700956d10..6fa2bc6b6 100644 --- a/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/create-nodes-plugin.e2e.test.ts @@ -163,7 +163,7 @@ describe('nx-plugin', () => { expect(projectJson.targets).toStrictEqual({ ['code-pushup']: { configurations: {}, - executor: `@code-pushup/nx-plugin:command`, + executor: `@code-pushup/nx-plugin:cli`, options: {}, }, }); @@ -240,7 +240,7 @@ describe('nx-plugin', () => { expect(projectJson.targets).toStrictEqual({ ['code-pushup']: expect.objectContaining({ - executor: 'XYZ:command', + executor: 'XYZ:cli', }), }); }); @@ -263,7 +263,7 @@ describe('nx-plugin', () => { expect(projectJson.targets).toStrictEqual({ ['code-pushup']: expect.objectContaining({ - executor: `@code-pushup/nx-plugin:command`, + executor: `@code-pushup/nx-plugin:cli`, options: { projectPrefix: 'cli', }, diff --git a/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts index 3efe65575..42d3254d8 100644 --- a/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-autorun.e2e.test.ts @@ -30,7 +30,7 @@ async function addTargetToWorkspace( executor: `${join( relativePathToCwd(cwd), 'dist/packages/nx-plugin', - )}:command`, + )}:cli`, }, }, }); diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts index 88c07b856..da8272a2f 100644 --- a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts @@ -31,7 +31,7 @@ async function addTargetToWorkspace( executor: `${join( relativePathToCwd(cwd), 'dist/packages/nx-plugin', - )}:command`, + )}:cli`, }, }, }); diff --git a/e2e/nx-plugin-e2e/tests/generator-configuration.e2e.test.ts b/e2e/nx-plugin-e2e/tests/generator-configuration.e2e.test.ts index 5e7ef538e..52ebe31c9 100644 --- a/e2e/nx-plugin-e2e/tests/generator-configuration.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/generator-configuration.e2e.test.ts @@ -72,7 +72,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', }, }), }), @@ -115,7 +115,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', }, }), }), @@ -156,7 +156,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', }, }), }), @@ -200,7 +200,7 @@ describe('nx-plugin g configuration', () => { expect.objectContaining({ targets: expect.not.objectContaining({ 'code-pushup': { - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', }, }), }), diff --git a/packages/nx-plugin/README.md b/packages/nx-plugin/README.md index c1bb289fb..89e8c306e 100644 --- a/packages/nx-plugin/README.md +++ b/packages/nx-plugin/README.md @@ -43,10 +43,10 @@ Examples: ### Executor -#### Command +#### CLI Install JS packages configure a target in your project json. -See [command executor docs](./src/executor/command/README.md) for details +See [CLI executor docs](./src/executor/cli/README.md) for details Examples: @@ -55,7 +55,7 @@ Examples: "name": "my-project", "targets": { "code-pushup": { - "executor": "@code-pushup/nx-plugin:command", + "executor": "@code-pushup/nx-plugin:cli", "options": { "projectPrefix": "workspace-name" } diff --git a/packages/nx-plugin/executors.json b/packages/nx-plugin/executors.json index f2dcf9800..7ec8bbcdc 100644 --- a/packages/nx-plugin/executors.json +++ b/packages/nx-plugin/executors.json @@ -1,9 +1,9 @@ { "executors": { - "command": { - "implementation": "./src/executors/command/executor", - "schema": "./src/executors/command/schema.json", - "description": "CodePushup CLI command executor. Executes the @code-pushup/cli command's See: https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#commands" + "cli": { + "implementation": "./src/executors/cli/executor", + "schema": "./src/executors/cli/schema.json", + "description": "CodePushup CLI executor. Executes the @code-pushup/cli command's See: https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#commands" } } } diff --git a/packages/nx-plugin/src/executors/command/README.md b/packages/nx-plugin/src/executors/cli/README.md similarity index 96% rename from packages/nx-plugin/src/executors/command/README.md rename to packages/nx-plugin/src/executors/cli/README.md index 33737cd6c..6ea426ab9 100644 --- a/packages/nx-plugin/src/executors/command/README.md +++ b/packages/nx-plugin/src/executors/cli/README.md @@ -3,7 +3,7 @@ This executor is used to run the code-pushup CLI autorun command in a Nx workspace. For details on the CLI command read the [CLI autorun documentation](https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#autorun-command). -#### @code-pushup/nx-plugin:command +#### @code-pushup/nx-plugin:cli ## Usage @@ -15,7 +15,7 @@ Configure a target in your project json. "name": "my-project", "targets": { "code-pushup": { - "executor": "@code-pushup/nx-plugin:command" + "executor": "@code-pushup/nx-plugin:cli" } } } diff --git a/packages/nx-plugin/src/executors/command/executor.integration.test.ts b/packages/nx-plugin/src/executors/cli/executor.integration.test.ts similarity index 100% rename from packages/nx-plugin/src/executors/command/executor.integration.test.ts rename to packages/nx-plugin/src/executors/cli/executor.integration.test.ts diff --git a/packages/nx-plugin/src/executors/command/executor.ts b/packages/nx-plugin/src/executors/cli/executor.ts similarity index 100% rename from packages/nx-plugin/src/executors/command/executor.ts rename to packages/nx-plugin/src/executors/cli/executor.ts diff --git a/packages/nx-plugin/src/executors/command/executor.unit.test.ts b/packages/nx-plugin/src/executors/cli/executor.unit.test.ts similarity index 100% rename from packages/nx-plugin/src/executors/command/executor.unit.test.ts rename to packages/nx-plugin/src/executors/cli/executor.unit.test.ts diff --git a/packages/nx-plugin/src/executors/command/schema.json b/packages/nx-plugin/src/executors/cli/schema.json similarity index 100% rename from packages/nx-plugin/src/executors/command/schema.json rename to packages/nx-plugin/src/executors/cli/schema.json diff --git a/packages/nx-plugin/src/executors/command/schema.ts b/packages/nx-plugin/src/executors/cli/schema.ts similarity index 100% rename from packages/nx-plugin/src/executors/command/schema.ts rename to packages/nx-plugin/src/executors/cli/schema.ts diff --git a/packages/nx-plugin/src/executors/command/utils.integration.test.ts b/packages/nx-plugin/src/executors/cli/utils.integration.test.ts similarity index 100% rename from packages/nx-plugin/src/executors/command/utils.integration.test.ts rename to packages/nx-plugin/src/executors/cli/utils.integration.test.ts diff --git a/packages/nx-plugin/src/executors/command/utils.ts b/packages/nx-plugin/src/executors/cli/utils.ts similarity index 100% rename from packages/nx-plugin/src/executors/command/utils.ts rename to packages/nx-plugin/src/executors/cli/utils.ts diff --git a/packages/nx-plugin/src/executors/command/utils.unit.test.ts b/packages/nx-plugin/src/executors/cli/utils.unit.test.ts similarity index 100% rename from packages/nx-plugin/src/executors/command/utils.unit.test.ts rename to packages/nx-plugin/src/executors/cli/utils.unit.test.ts diff --git a/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts b/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts index 75683ce7b..2916664c0 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.integration.test.ts @@ -45,7 +45,7 @@ describe('addTargetToProject', () => { ); expect(projectConfiguration.targets?.[DEFAULT_TARGET_NAME]).toEqual({ - executor: `${PACKAGE_NAME}:command`, + executor: `${PACKAGE_NAME}:cli`, }); }); @@ -70,7 +70,7 @@ describe('addTargetToProject', () => { ); expect(projectConfiguration.targets?.['cp']).toEqual({ - executor: `${PACKAGE_NAME}:command`, + executor: `${PACKAGE_NAME}:cli`, }); }); }); @@ -102,7 +102,7 @@ describe('configurationGenerator', () => { ); expect(projectConfiguration.targets?.[DEFAULT_TARGET_NAME]).toEqual({ - executor: `${PACKAGE_NAME}:command`, + executor: `${PACKAGE_NAME}:cli`, }); }); diff --git a/packages/nx-plugin/src/generators/configuration/generator.ts b/packages/nx-plugin/src/generators/configuration/generator.ts index 0cb5f28f0..cb9493839 100644 --- a/packages/nx-plugin/src/generators/configuration/generator.ts +++ b/packages/nx-plugin/src/generators/configuration/generator.ts @@ -46,7 +46,7 @@ export function addTargetToProject( const { targetName, project } = options; const codePushupTargetConfig = { - executor: `${PACKAGE_NAME}:command`, + executor: `${PACKAGE_NAME}:cli`, }; updateProjectConfiguration(tree, project, { diff --git a/packages/nx-plugin/src/plugin/plugin.unit.test.ts b/packages/nx-plugin/src/plugin/plugin.unit.test.ts index 5dd988650..54c389778 100644 --- a/packages/nx-plugin/src/plugin/plugin.unit.test.ts +++ b/packages/nx-plugin/src/plugin/plugin.unit.test.ts @@ -94,7 +94,7 @@ describe('@code-pushup/nx-plugin/plugin', () => { [projectRoot]: { targets: { [CP_TARGET_NAME]: { - executor: `${PACKAGE_NAME}:command`, + executor: `${PACKAGE_NAME}:cli`, options: { projectPrefix: 'cli', }, @@ -126,7 +126,7 @@ describe('@code-pushup/nx-plugin/plugin', () => { [projectRoot]: { targets: { [CP_TARGET_NAME]: { - executor: `${PACKAGE_NAME}:command`, + executor: `${PACKAGE_NAME}:cli`, options: { projectPrefix: 'cli', }, diff --git a/packages/nx-plugin/src/plugin/target/executor-target.ts b/packages/nx-plugin/src/plugin/target/executor-target.ts index 64075c618..6d60fc829 100644 --- a/packages/nx-plugin/src/plugin/target/executor-target.ts +++ b/packages/nx-plugin/src/plugin/target/executor-target.ts @@ -8,7 +8,7 @@ export function createExecutorTarget(options?: { }): TargetConfiguration { const { bin = PACKAGE_NAME, projectPrefix } = options ?? {}; return { - executor: `${bin}:command`, + executor: `${bin}:cli`, ...(projectPrefix ? { options: { diff --git a/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts b/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts index 40d3bb7ba..8ea0799a7 100644 --- a/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts +++ b/packages/nx-plugin/src/plugin/target/executor.target.unit.test.ts @@ -4,19 +4,19 @@ import { createExecutorTarget } from './executor-target'; describe('createExecutorTarget', () => { it('should return executor target without project name', () => { expect(createExecutorTarget()).toStrictEqual({ - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', }); }); it('should use bin if provides', () => { expect(createExecutorTarget({ bin: 'xyz' })).toStrictEqual({ - executor: 'xyz:command', + executor: 'xyz:cli', }); }); it('should use projectPrefix if provided', () => { expect(createExecutorTarget({ projectPrefix: 'cli' })).toStrictEqual({ - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', options: { projectPrefix: 'cli', }, diff --git a/packages/nx-plugin/src/plugin/target/targets.unit.test.ts b/packages/nx-plugin/src/plugin/target/targets.unit.test.ts index 01af09de1..2eb5ffb0b 100644 --- a/packages/nx-plugin/src/plugin/target/targets.unit.test.ts +++ b/packages/nx-plugin/src/plugin/target/targets.unit.test.ts @@ -108,7 +108,7 @@ describe('createTargets', () => { ).resolves.toStrictEqual( expect.objectContaining({ [targetName]: { - executor: `${PACKAGE_NAME}:command`, + executor: `${PACKAGE_NAME}:cli`, }, }), ); @@ -132,7 +132,7 @@ describe('createTargets', () => { } as NormalizedCreateNodesContext), ).resolves.toStrictEqual({ [DEFAULT_TARGET_NAME]: { - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', }, }); }); @@ -157,7 +157,7 @@ describe('createTargets', () => { } as NormalizedCreateNodesContext), ).resolves.toStrictEqual({ cp: { - executor: '@code-pushup/nx-plugin:command', + executor: '@code-pushup/nx-plugin:cli', }, }); }); From 89639f9108710606029366d528cbdcbd4b5c1ed2 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 28 Aug 2024 18:37:48 +0200 Subject: [PATCH 11/32] merge main --- .../create-nodes-plugin.e2e.test.ts.snap | 0 .../plugin-create-nodes.e2e.test.ts.snap | 4 +- .../tests/executor-cli.e2e.test.ts | 116 +++++++++++- e2e/nx-plugin-e2e/tests/executor.e2e.test.ts | 174 ------------------ package-lock.json | 166 ++++++++++++++--- package.json | 8 + 6 files changed, 259 insertions(+), 209 deletions(-) delete mode 100644 e2e/nx-plugin-e2e/tests/__snapshots__/create-nodes-plugin.e2e.test.ts.snap delete mode 100644 e2e/nx-plugin-e2e/tests/executor.e2e.test.ts diff --git a/e2e/nx-plugin-e2e/tests/__snapshots__/create-nodes-plugin.e2e.test.ts.snap b/e2e/nx-plugin-e2e/tests/__snapshots__/create-nodes-plugin.e2e.test.ts.snap deleted file mode 100644 index e69de29bb..000000000 diff --git a/e2e/nx-plugin-e2e/tests/__snapshots__/plugin-create-nodes.e2e.test.ts.snap b/e2e/nx-plugin-e2e/tests/__snapshots__/plugin-create-nodes.e2e.test.ts.snap index 158dc132d..d1599c84c 100644 --- a/e2e/nx-plugin-e2e/tests/__snapshots__/plugin-create-nodes.e2e.test.ts.snap +++ b/e2e/nx-plugin-e2e/tests/__snapshots__/plugin-create-nodes.e2e.test.ts.snap @@ -4,7 +4,7 @@ exports[`nx-plugin > should NOT add config targets dynamically if the project is { "code-pushup": { "configurations": {}, - "executor": "@code-pushup/nx-plugin:autorun", + "executor": "@code-pushup/nx-plugin:cli", "options": {}, }, } @@ -26,7 +26,7 @@ exports[`nx-plugin > should add executor target dynamically if the project is co { "code-pushup": { "configurations": {}, - "executor": "@code-pushup/nx-plugin:autorun", + "executor": "@code-pushup/nx-plugin:cli", "options": {}, }, } diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 212f732d9..97ebab90f 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -9,7 +9,7 @@ import { materializeTree, } from '@code-pushup/test-nx-utils'; import { removeColorCodes } from '@code-pushup/test-utils'; -import { executeProcess } from '@code-pushup/utils'; +import { executeProcess, readJsonFile } from '@code-pushup/utils'; function relativePathToCwd(testDir: string): string { return relative(join(process.cwd(), testDir), process.cwd()); @@ -27,7 +27,7 @@ async function addTargetToWorkspace( targets: { ...projectCfg.targets, ['code-pushup']: { - executor: '@code-pushup/nx-plugin:autorun', + executor: '@code-pushup/nx-plugin:cli', }, }, }); @@ -59,13 +59,12 @@ describe('executor command', () => { }); afterEach(async () => { - await rm(baseDir, { recursive: true, force: true }); + // await rm(baseDir, { recursive: true, force: true }); }); - it('should execute command executor', async () => { - const cwd = join(baseDir, 'execute-dynamic-executor'); + it('should execute no specific command by default', async () => { + const cwd = join(baseDir, 'execute-default-command'); await addTargetToWorkspace(tree, { cwd, project }); - const { stdout, code } = await executeProcess({ command: 'npx', args: ['nx', 'run', `${project}:code-pushup`, '--dryRun'], @@ -74,6 +73,109 @@ describe('executor command', () => { expect(code).toBe(0); const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup --dryRun'); + expect(cleanStdout).toContain('nx run my-lib:code-pushup'); + }); + + it('should execute print-config executor', async () => { + const cwd = join(baseDir, 'execute-print-config-command'); + await addTargetToWorkspace(tree, { cwd, project }); + + const { stdout, code } = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'print-config'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup print-config'); + + await expect(() => + readJsonFile(join(cwd, '.code-pushup', project, 'report.json')), + ).rejects.toThrow(''); + }); + + it('should execute collect executor', async () => { + const cwd = join(baseDir, 'execute-collect-command'); + await addTargetToWorkspace(tree, { cwd, project }); + + const { stdout, code } = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'collect'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup collect'); + + const report = await readJsonFile( + join(cwd, '.code-pushup', project, 'report.json'), + ); + expect(report).toStrictEqual( + expect.objectContaining({ + plugins: [ + expect.objectContaining({ + slug: 'good-feels', + audits: [ + expect.objectContaining({ + displayValue: '✅ Perfect! 👌', + slug: 'always-perfect', + }), + ], + }), + ], + }), + ); + }); + + it('should execute upload executor to throw if no report is present', async () => { + const cwd = join(baseDir, 'execute-upload-command'); + await addTargetToWorkspace(tree, { cwd, project }); + + await expect( + executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'upload'], + cwd, + }), + ).rejects.toThrow(/report.json/); + }); + + it('should execute autorun executor', async () => { + const cwd = join(baseDir, 'execute-autorun-command'); + await addTargetToWorkspace(tree, { cwd, project }); + + const { stdout, code } = await executeProcess({ + command: 'npx', + args: ['nx', 'run', `${project}:code-pushup`, 'autorun'], + cwd, + }); + + expect(code).toBe(0); + const cleanStdout = removeColorCodes(stdout); + expect(cleanStdout).toContain('nx run my-lib:code-pushup autorun'); + expect(cleanStdout).toContain( + '> NX Successfully ran target code-pushup for project my-lib', + ); + + const report = await readJsonFile( + join(cwd, '.code-pushup', project, 'report.json'), + ); + expect(report).toStrictEqual( + expect.objectContaining({ + plugins: [ + expect.objectContaining({ + slug: 'good-feels', + audits: [ + expect.objectContaining({ + displayValue: '✅ Perfect! 👌', + slug: 'always-perfect', + }), + ], + }), + ], + }), + ); }); }); diff --git a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts deleted file mode 100644 index da8272a2f..000000000 --- a/e2e/nx-plugin-e2e/tests/executor.e2e.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { Tree, updateProjectConfiguration } from '@nx/devkit'; -import { rm } from 'node:fs/promises'; -import { join, relative } from 'node:path'; -import { readProjectConfiguration } from 'nx/src/generators/utils/project-configuration'; -import { afterEach, expect } from 'vitest'; -import { generateCodePushupConfig } from '@code-pushup/nx-plugin'; -import { - generateWorkspaceAndProject, - materializeTree, -} from '@code-pushup/test-nx-utils'; -import { removeColorCodes } from '@code-pushup/test-utils'; -import { executeProcess, readJsonFile } from '@code-pushup/utils'; - -// @TODO replace with default bin after https://github.com/code-pushup/cli/issues/643 -function relativePathToCwd(testDir: string): string { - return relative(join(process.cwd(), testDir), process.cwd()); -} - -async function addTargetToWorkspace( - tree: Tree, - options: { cwd: string; project: string }, -) { - const { cwd, project } = options; - const pathRelativeToPackage = relative(join(cwd, 'libs', project), cwd); - const projectCfg = readProjectConfiguration(tree, project); - updateProjectConfiguration(tree, project, { - ...projectCfg, - targets: { - ...projectCfg.targets, - ['code-pushup']: { - executor: `${join( - relativePathToCwd(cwd), - 'dist/packages/nx-plugin', - )}:cli`, - }, - }, - }); - const { root } = projectCfg; - generateCodePushupConfig(tree, root, { - fileImports: `import type {CoreConfig} from "${join( - relativePathToCwd(cwd), - pathRelativeToPackage, - 'dist/packages/models', - )}";`, - plugins: [ - { - fileImports: `import {customPlugin} from "${join( - relativePathToCwd(cwd), - pathRelativeToPackage, - 'dist/testing/test-utils', - )}";`, - codeStrings: 'customPlugin()', - }, - ], - upload: { - project: 'my-lib', - server: 'http://staging.code-pushup.dev', - organization: 'code-pushup', - apiKey: '12345678', - }, - }); - await materializeTree(tree, cwd); -} - -describe('CLI executor', () => { - let tree: Tree; - const project = 'my-lib'; - const baseDir = 'tmp/nx-plugin-e2e/executor'; - - beforeEach(async () => { - tree = await generateWorkspaceAndProject(project); - }); - - afterEach(async () => { - await rm(baseDir, { recursive: true, force: true }); - }); - - it('should execute no command by default', async () => { - const cwd = join(baseDir, 'execute-default-command'); - await addTargetToWorkspace(tree, { cwd, project }); - const { stdout, code } = await executeProcess({ - command: 'npx', - args: ['nx', 'run', `${project}:code-pushup`, '--dryRun'], - cwd, - }); - - expect(code).toBe(0); - const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup'); - }); - - it('should execute print-config executor', async () => { - const cwd = join(baseDir, 'execute-print-config-command'); - await addTargetToWorkspace(tree, { cwd, project }); - - const { stdout, code } = await executeProcess({ - command: 'npx', - args: ['nx', 'run', `${project}:code-pushup`, 'print-config'], - cwd, - }); - - expect(code).toBe(0); - const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup print-config'); - - await expect(() => - readJsonFile(join(cwd, '.code-pushup', project, 'report.json')), - ).rejects.toThrow(''); - }); - - it('should execute collect executor', async () => { - const cwd = join(baseDir, 'execute-collect-command'); - await addTargetToWorkspace(tree, { cwd, project }); - - const { stdout, code } = await executeProcess({ - command: 'npx', - args: ['nx', 'run', `${project}:code-pushup`, 'collect'], - cwd, - }); - - expect(code).toBe(0); - const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup collect'); - - const report = await readJsonFile( - join(cwd, '.code-pushup', project, 'report.json'), - ); - expect(report).toStrictEqual( - expect.objectContaining({ - plugins: [ - expect.objectContaining({ - slug: 'good-feels', - audits: [ - expect.objectContaining({ - displayValue: '✅ Perfect! 👌', - slug: 'always-perfect', - }), - ], - }), - ], - }), - ); - }); - - it('should execute upload executor to throw if no report is present', async () => { - const cwd = join(baseDir, 'execute-upload-command'); - await addTargetToWorkspace(tree, { cwd, project }); - - const { stdout, code } = await executeProcess({ - command: 'npx', - args: ['nx', 'run', `${project}:code-pushup`, 'upload', '--dryRun'], - cwd, - }); - - expect(code).toBe(0); - const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup upload'); - }); - - it('should execute autorun executor', async () => { - const cwd = join(baseDir, 'execute-command-command'); - await addTargetToWorkspace(tree, { cwd, project }); - - const { stdout, code } = await executeProcess({ - command: 'npx', - args: ['nx', 'run', `${project}:code-pushup`, 'autorun', '--dryRun'], - cwd, - }); - - expect(code).toBe(0); - const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup autorun'); - }); -}); diff --git a/package-lock.json b/package-lock.json index 662c5ae60..f840b3719 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,15 @@ }, "devDependencies": { "@beaussan/nx-knip": "0.0.5-13", + "@code-pushup/cli": "^0.49.0", + "@code-pushup/core": "^0.49.0", + "@code-pushup/coverage-plugin": "^0.49.0", "@code-pushup/eslint-config": "^0.2.1", + "@code-pushup/eslint-plugin": "^0.49.0", + "@code-pushup/js-packages-plugin": "^0.49.0", + "@code-pushup/lighthouse-plugin": "^0.49.0", + "@code-pushup/models": "^0.49.0", + "@code-pushup/utils": "^0.49.0", "@commitlint/cli": "^17.7.1", "@commitlint/config-conventional": "^17.7.0", "@commitlint/config-nx-scopes": "^18.4.3", @@ -2056,6 +2064,64 @@ "knip": "5" } }, + "node_modules/@code-pushup/cli": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/cli/-/cli-0.49.0.tgz", + "integrity": "sha512-f7tt7EFoW42Ev2rkcwi3e8cWW7r1bR7GAMHJoNmJvHJfR1/N6AHBt0kl3d8VwSZkltJx1POivj7KIHjNb4xHMw==", + "dev": true, + "dependencies": { + "@code-pushup/core": "0.49.0", + "@code-pushup/models": "0.49.0", + "@code-pushup/utils": "0.49.0", + "ansis": "^3.3.0", + "simple-git": "^3.20.0", + "yargs": "^17.7.2" + }, + "bin": { + "code-pushup": "index.js" + } + }, + "node_modules/@code-pushup/core": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/core/-/core-0.49.0.tgz", + "integrity": "sha512-zJxbkfbQxeEQc9zNw8bT0nz7d/pO5g2DICI551yj4lQ/Eep85V7IhzTYP+RmfFTStfYy4ppjkcBKDVnZPlMFsw==", + "dev": true, + "dependencies": { + "@code-pushup/models": "0.49.0", + "@code-pushup/portal-client": "^0.9.0", + "@code-pushup/utils": "0.49.0", + "ansis": "^3.3.0" + } + }, + "node_modules/@code-pushup/coverage-plugin": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/coverage-plugin/-/coverage-plugin-0.49.0.tgz", + "integrity": "sha512-gSyn7TeRBNsyxANyh/s3VthvsPlLVoG5f4maGoNNuuf1FYs1iSliySUNrguhatcCD4nQMmS+Ht6RcVUcGKZo2w==", + "dev": true, + "dependencies": { + "@code-pushup/models": "0.49.0", + "@code-pushup/utils": "0.49.0", + "ansis": "^3.3.0", + "parse-lcov": "^1.0.4", + "zod": "^3.22.4" + }, + "peerDependencies": { + "@nx/devkit": "^17.0.0 || ^18.0.0 || ^19.0.0", + "@nx/jest": "^17.0.0 || ^18.0.0 || ^19.0.0", + "@nx/vite": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@nx/devkit": { + "optional": true + }, + "@nx/jest": { + "optional": true + }, + "@nx/vite": { + "optional": true + } + } + }, "node_modules/@code-pushup/eslint-config": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@code-pushup/eslint-config/-/eslint-config-0.2.1.tgz", @@ -2126,6 +2192,62 @@ } } }, + "node_modules/@code-pushup/eslint-plugin": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/eslint-plugin/-/eslint-plugin-0.49.0.tgz", + "integrity": "sha512-0sqX2zQuISUKpPbPLVWFYSyZOej7tB5ttezS7ubuWMtcnrG6Q+cl5tQUVpNOr8aaVQASsVdyppYzkR3doC4t7g==", + "dev": true, + "dependencies": { + "@code-pushup/models": "0.49.0", + "@code-pushup/utils": "0.49.0", + "eslint": "^8.46.0", + "zod": "^3.22.4" + }, + "peerDependencies": { + "@nx/devkit": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@nx/devkit": { + "optional": true + } + } + }, + "node_modules/@code-pushup/js-packages-plugin": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/js-packages-plugin/-/js-packages-plugin-0.49.0.tgz", + "integrity": "sha512-TsDRuAStPEnn8cIneRsOAicrX+fapkp9PLfntXMcCbgU+HD448e/C0fL9xDERQptnajNd3k3x2z68WF8NVyYGQ==", + "dev": true, + "dependencies": { + "@code-pushup/models": "0.49.0", + "@code-pushup/utils": "0.49.0", + "build-md": "^0.4.1", + "semver": "^7.6.0", + "zod": "^3.22.4" + } + }, + "node_modules/@code-pushup/lighthouse-plugin": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/lighthouse-plugin/-/lighthouse-plugin-0.49.0.tgz", + "integrity": "sha512-Mj5mxJRSIAX1Ku4azIFyIrnI5ZOMKdOyRKeBGn3pOKB7lMTJdSPofFpfG3LiOJS5IB9Sy6O27c+Nft3Xm+YHXw==", + "dev": true, + "dependencies": { + "@code-pushup/models": "0.49.0", + "@code-pushup/utils": "0.49.0", + "ansis": "^3.3.0", + "lighthouse": "^12.0.0", + "lighthouse-logger": "2.0.1" + } + }, + "node_modules/@code-pushup/models": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/models/-/models-0.49.0.tgz", + "integrity": "sha512-GIu5EkclSoDxGJuN5CxsBLIGNuSZ6xqHK/9QNfLJPtsNr8/faVXvoJLcMlPgRrMsj1BGYO4RhU/PEvrQFvA4eQ==", + "dev": true, + "dependencies": { + "vscode-material-icons": "^0.1.0", + "zod": "^3.22.1" + } + }, "node_modules/@code-pushup/portal-client": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@code-pushup/portal-client/-/portal-client-0.9.0.tgz", @@ -2137,6 +2259,24 @@ "vscode-material-icons": "^0.1.0" } }, + "node_modules/@code-pushup/utils": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@code-pushup/utils/-/utils-0.49.0.tgz", + "integrity": "sha512-guIRo23AHlBDnae7Q+wEz2rIfWNWQ3YG8S7QHE/0gwZP7QswDQV1i4xmwgfSKuzHjr/X3SjYRjWt8dLSUHLEPg==", + "dev": true, + "dependencies": { + "@code-pushup/models": "0.49.0", + "@isaacs/cliui": "^8.0.2", + "@poppinss/cliui": "^6.4.0", + "ansis": "^3.3.0", + "build-md": "^0.4.1", + "bundle-require": "^4.0.1", + "esbuild": "^0.19.2", + "multi-progress-bars": "^5.0.3", + "semver": "^7.6.0", + "simple-git": "^3.20.0" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "license": "MIT", @@ -2915,7 +3055,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", - "dev": true, "optional": true, "dependencies": { "@emnapi/wasi-threads": "1.0.1", @@ -2926,7 +3065,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", - "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -2936,7 +3074,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", - "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -4306,7 +4443,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", - "dev": true, "optional": true, "dependencies": { "@emnapi/core": "^1.1.0", @@ -5711,7 +5847,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -5724,7 +5859,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -5737,7 +5871,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -5750,7 +5883,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5763,7 +5895,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5776,7 +5907,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5789,7 +5919,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5802,7 +5931,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5815,7 +5943,6 @@ "cpu": [ "wasm32" ], - "dev": true, "optional": true, "dependencies": { "@napi-rs/wasm-runtime": "^0.2.4" @@ -5831,7 +5958,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -5844,7 +5970,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -6983,7 +7108,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -6999,7 +7123,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -7015,7 +7138,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -7031,7 +7153,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -7047,7 +7168,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -7063,7 +7183,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -7079,7 +7198,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -7095,7 +7213,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -7111,7 +7228,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -7127,7 +7243,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -7533,7 +7648,6 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" diff --git a/package.json b/package.json index a32ab9ebd..95378cb63 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,15 @@ }, "devDependencies": { "@beaussan/nx-knip": "0.0.5-13", + "@code-pushup/cli": "^0.49.0", + "@code-pushup/core": "^0.49.0", + "@code-pushup/coverage-plugin": "^0.49.0", "@code-pushup/eslint-config": "^0.2.1", + "@code-pushup/eslint-plugin": "^0.49.0", + "@code-pushup/js-packages-plugin": "^0.49.0", + "@code-pushup/lighthouse-plugin": "^0.49.0", + "@code-pushup/models": "^0.49.0", + "@code-pushup/utils": "^0.49.0", "@commitlint/cli": "^17.7.1", "@commitlint/config-conventional": "^17.7.0", "@commitlint/config-nx-scopes": "^18.4.3", From 81d73be4c971e700031311fbd4e3347f62c98fe1 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 28 Aug 2024 22:02:19 +0200 Subject: [PATCH 12/32] fix lint --- .../tests/executor-cli.e2e.test.ts | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 97ebab90f..9db1fbd1d 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -1,15 +1,11 @@ -import { type Tree, updateProjectConfiguration } from '@nx/devkit'; -import { rm } from 'node:fs/promises'; -import { join, relative } from 'node:path'; -import { readProjectConfiguration } from 'nx/src/generators/utils/project-configuration'; -import { afterEach, expect } from 'vitest'; -import { generateCodePushupConfig } from '@code-pushup/nx-plugin'; -import { - generateWorkspaceAndProject, - materializeTree, -} from '@code-pushup/test-nx-utils'; -import { removeColorCodes } from '@code-pushup/test-utils'; -import { executeProcess, readJsonFile } from '@code-pushup/utils'; +import {type Tree, updateProjectConfiguration} from '@nx/devkit'; +import {join, relative} from 'node:path'; +import {readProjectConfiguration} from 'nx/src/generators/utils/project-configuration'; +import {afterEach, expect} from 'vitest'; +import {generateCodePushupConfig} from '@code-pushup/nx-plugin'; +import {generateWorkspaceAndProject, materializeTree,} from '@code-pushup/test-nx-utils'; +import {removeColorCodes} from '@code-pushup/test-utils'; +import {executeProcess, readJsonFile} from '@code-pushup/utils'; function relativePathToCwd(testDir: string): string { return relative(join(process.cwd(), testDir), process.cwd()); From 2b48975aca3cbd40b57b2231c7c906349f129967 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 29 Aug 2024 02:31:01 +0200 Subject: [PATCH 13/32] cleanup --- .../tests/executor-cli.e2e.test.ts | 19 +++++++++++-------- global-setup.verdaccio.ts | 1 - 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 9db1fbd1d..c27e5252d 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -1,11 +1,14 @@ -import {type Tree, updateProjectConfiguration} from '@nx/devkit'; -import {join, relative} from 'node:path'; -import {readProjectConfiguration} from 'nx/src/generators/utils/project-configuration'; -import {afterEach, expect} from 'vitest'; -import {generateCodePushupConfig} from '@code-pushup/nx-plugin'; -import {generateWorkspaceAndProject, materializeTree,} from '@code-pushup/test-nx-utils'; -import {removeColorCodes} from '@code-pushup/test-utils'; -import {executeProcess, readJsonFile} from '@code-pushup/utils'; +import { type Tree, updateProjectConfiguration } from '@nx/devkit'; +import { join, relative } from 'node:path'; +import { readProjectConfiguration } from 'nx/src/generators/utils/project-configuration'; +import { afterEach, expect } from 'vitest'; +import { generateCodePushupConfig } from '@code-pushup/nx-plugin'; +import { + generateWorkspaceAndProject, + materializeTree, +} from '@code-pushup/test-nx-utils'; +import { removeColorCodes } from '@code-pushup/test-utils'; +import { executeProcess, readJsonFile } from '@code-pushup/utils'; function relativePathToCwd(testDir: string): string { return relative(join(process.cwd(), testDir), process.cwd()); diff --git a/global-setup.verdaccio.ts b/global-setup.verdaccio.ts index 4985a3a93..c8ac69f1a 100644 --- a/global-setup.verdaccio.ts +++ b/global-setup.verdaccio.ts @@ -1,4 +1,3 @@ -import { bold, red } from 'ansis'; import { setup as globalSetup } from './global-setup'; import { nxRunManyNpmInstall } from './tools/src/npm/utils'; import { findLatestVersion, nxRunManyPublish } from './tools/src/publish/utils'; From bf62f81555794c7cecca4f611d3ef1f588b50205 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 1 Oct 2024 15:10:06 +0200 Subject: [PATCH 14/32] fix package.json --- global-setup.verdaccio.ts | 4 +- nx.json | 7 -- package-lock.json | 166 ++++++-------------------------------- package.json | 8 -- 4 files changed, 28 insertions(+), 157 deletions(-) diff --git a/global-setup.verdaccio.ts b/global-setup.verdaccio.ts index 10f3d7bf7..e1aa9f958 100644 --- a/global-setup.verdaccio.ts +++ b/global-setup.verdaccio.ts @@ -38,6 +38,6 @@ export async function setup() { export async function teardown() { // NOTICE - Time saving optimization // We skip uninstalling packages as the folder is deleted anyway - // comment out to see the folder and web interface - // await nxStopVerdaccioAndTeardownEnv(activeRegistry); + + await nxStopVerdaccioAndTeardownEnv(activeRegistry); } diff --git a/nx.json b/nx.json index 0ca975f6c..efc3fff0e 100644 --- a/nx.json +++ b/nx.json @@ -111,13 +111,6 @@ "releaseTagPattern": "v{version}" }, "plugins": [ - { - "plugin": "@code-pushup/nx-plugin", - "options": { - "targetName": "cp", - "projectPrefix": "cli" - } - }, "./tools/src/debug/debug.plugin.ts", { "plugin": "./tools/src/npm/npm.plugin.ts", diff --git a/package-lock.json b/package-lock.json index f840b3719..662c5ae60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,15 +34,7 @@ }, "devDependencies": { "@beaussan/nx-knip": "0.0.5-13", - "@code-pushup/cli": "^0.49.0", - "@code-pushup/core": "^0.49.0", - "@code-pushup/coverage-plugin": "^0.49.0", "@code-pushup/eslint-config": "^0.2.1", - "@code-pushup/eslint-plugin": "^0.49.0", - "@code-pushup/js-packages-plugin": "^0.49.0", - "@code-pushup/lighthouse-plugin": "^0.49.0", - "@code-pushup/models": "^0.49.0", - "@code-pushup/utils": "^0.49.0", "@commitlint/cli": "^17.7.1", "@commitlint/config-conventional": "^17.7.0", "@commitlint/config-nx-scopes": "^18.4.3", @@ -2064,64 +2056,6 @@ "knip": "5" } }, - "node_modules/@code-pushup/cli": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/cli/-/cli-0.49.0.tgz", - "integrity": "sha512-f7tt7EFoW42Ev2rkcwi3e8cWW7r1bR7GAMHJoNmJvHJfR1/N6AHBt0kl3d8VwSZkltJx1POivj7KIHjNb4xHMw==", - "dev": true, - "dependencies": { - "@code-pushup/core": "0.49.0", - "@code-pushup/models": "0.49.0", - "@code-pushup/utils": "0.49.0", - "ansis": "^3.3.0", - "simple-git": "^3.20.0", - "yargs": "^17.7.2" - }, - "bin": { - "code-pushup": "index.js" - } - }, - "node_modules/@code-pushup/core": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/core/-/core-0.49.0.tgz", - "integrity": "sha512-zJxbkfbQxeEQc9zNw8bT0nz7d/pO5g2DICI551yj4lQ/Eep85V7IhzTYP+RmfFTStfYy4ppjkcBKDVnZPlMFsw==", - "dev": true, - "dependencies": { - "@code-pushup/models": "0.49.0", - "@code-pushup/portal-client": "^0.9.0", - "@code-pushup/utils": "0.49.0", - "ansis": "^3.3.0" - } - }, - "node_modules/@code-pushup/coverage-plugin": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/coverage-plugin/-/coverage-plugin-0.49.0.tgz", - "integrity": "sha512-gSyn7TeRBNsyxANyh/s3VthvsPlLVoG5f4maGoNNuuf1FYs1iSliySUNrguhatcCD4nQMmS+Ht6RcVUcGKZo2w==", - "dev": true, - "dependencies": { - "@code-pushup/models": "0.49.0", - "@code-pushup/utils": "0.49.0", - "ansis": "^3.3.0", - "parse-lcov": "^1.0.4", - "zod": "^3.22.4" - }, - "peerDependencies": { - "@nx/devkit": "^17.0.0 || ^18.0.0 || ^19.0.0", - "@nx/jest": "^17.0.0 || ^18.0.0 || ^19.0.0", - "@nx/vite": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@nx/devkit": { - "optional": true - }, - "@nx/jest": { - "optional": true - }, - "@nx/vite": { - "optional": true - } - } - }, "node_modules/@code-pushup/eslint-config": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@code-pushup/eslint-config/-/eslint-config-0.2.1.tgz", @@ -2192,62 +2126,6 @@ } } }, - "node_modules/@code-pushup/eslint-plugin": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/eslint-plugin/-/eslint-plugin-0.49.0.tgz", - "integrity": "sha512-0sqX2zQuISUKpPbPLVWFYSyZOej7tB5ttezS7ubuWMtcnrG6Q+cl5tQUVpNOr8aaVQASsVdyppYzkR3doC4t7g==", - "dev": true, - "dependencies": { - "@code-pushup/models": "0.49.0", - "@code-pushup/utils": "0.49.0", - "eslint": "^8.46.0", - "zod": "^3.22.4" - }, - "peerDependencies": { - "@nx/devkit": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@nx/devkit": { - "optional": true - } - } - }, - "node_modules/@code-pushup/js-packages-plugin": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/js-packages-plugin/-/js-packages-plugin-0.49.0.tgz", - "integrity": "sha512-TsDRuAStPEnn8cIneRsOAicrX+fapkp9PLfntXMcCbgU+HD448e/C0fL9xDERQptnajNd3k3x2z68WF8NVyYGQ==", - "dev": true, - "dependencies": { - "@code-pushup/models": "0.49.0", - "@code-pushup/utils": "0.49.0", - "build-md": "^0.4.1", - "semver": "^7.6.0", - "zod": "^3.22.4" - } - }, - "node_modules/@code-pushup/lighthouse-plugin": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/lighthouse-plugin/-/lighthouse-plugin-0.49.0.tgz", - "integrity": "sha512-Mj5mxJRSIAX1Ku4azIFyIrnI5ZOMKdOyRKeBGn3pOKB7lMTJdSPofFpfG3LiOJS5IB9Sy6O27c+Nft3Xm+YHXw==", - "dev": true, - "dependencies": { - "@code-pushup/models": "0.49.0", - "@code-pushup/utils": "0.49.0", - "ansis": "^3.3.0", - "lighthouse": "^12.0.0", - "lighthouse-logger": "2.0.1" - } - }, - "node_modules/@code-pushup/models": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/models/-/models-0.49.0.tgz", - "integrity": "sha512-GIu5EkclSoDxGJuN5CxsBLIGNuSZ6xqHK/9QNfLJPtsNr8/faVXvoJLcMlPgRrMsj1BGYO4RhU/PEvrQFvA4eQ==", - "dev": true, - "dependencies": { - "vscode-material-icons": "^0.1.0", - "zod": "^3.22.1" - } - }, "node_modules/@code-pushup/portal-client": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@code-pushup/portal-client/-/portal-client-0.9.0.tgz", @@ -2259,24 +2137,6 @@ "vscode-material-icons": "^0.1.0" } }, - "node_modules/@code-pushup/utils": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@code-pushup/utils/-/utils-0.49.0.tgz", - "integrity": "sha512-guIRo23AHlBDnae7Q+wEz2rIfWNWQ3YG8S7QHE/0gwZP7QswDQV1i4xmwgfSKuzHjr/X3SjYRjWt8dLSUHLEPg==", - "dev": true, - "dependencies": { - "@code-pushup/models": "0.49.0", - "@isaacs/cliui": "^8.0.2", - "@poppinss/cliui": "^6.4.0", - "ansis": "^3.3.0", - "build-md": "^0.4.1", - "bundle-require": "^4.0.1", - "esbuild": "^0.19.2", - "multi-progress-bars": "^5.0.3", - "semver": "^7.6.0", - "simple-git": "^3.20.0" - } - }, "node_modules/@colors/colors": { "version": "1.5.0", "license": "MIT", @@ -3055,6 +2915,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz", "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==", + "dev": true, "optional": true, "dependencies": { "@emnapi/wasi-threads": "1.0.1", @@ -3065,6 +2926,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -3074,6 +2936,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -4443,6 +4306,7 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, "optional": true, "dependencies": { "@emnapi/core": "^1.1.0", @@ -5847,6 +5711,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -5859,6 +5724,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -5871,6 +5737,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -5883,6 +5750,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -5895,6 +5763,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -5907,6 +5776,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -5919,6 +5789,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -5931,6 +5802,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -5943,6 +5815,7 @@ "cpu": [ "wasm32" ], + "dev": true, "optional": true, "dependencies": { "@napi-rs/wasm-runtime": "^0.2.4" @@ -5958,6 +5831,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -5970,6 +5844,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -7108,6 +6983,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -7123,6 +6999,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -7138,6 +7015,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7153,6 +7031,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7168,6 +7047,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7183,6 +7063,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7198,6 +7079,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -7213,6 +7095,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -7228,6 +7111,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -7243,6 +7127,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -7648,6 +7533,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, "optional": true, "dependencies": { "tslib": "^2.4.0" diff --git a/package.json b/package.json index 95378cb63..a32ab9ebd 100644 --- a/package.json +++ b/package.json @@ -46,15 +46,7 @@ }, "devDependencies": { "@beaussan/nx-knip": "0.0.5-13", - "@code-pushup/cli": "^0.49.0", - "@code-pushup/core": "^0.49.0", - "@code-pushup/coverage-plugin": "^0.49.0", "@code-pushup/eslint-config": "^0.2.1", - "@code-pushup/eslint-plugin": "^0.49.0", - "@code-pushup/js-packages-plugin": "^0.49.0", - "@code-pushup/lighthouse-plugin": "^0.49.0", - "@code-pushup/models": "^0.49.0", - "@code-pushup/utils": "^0.49.0", "@commitlint/cli": "^17.7.1", "@commitlint/config-conventional": "^17.7.0", "@commitlint/config-nx-scopes": "^18.4.3", From 57d3bea5618bac9d098fed8c24e0092fae65f2ff Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 1 Oct 2024 21:31:13 +0200 Subject: [PATCH 15/32] fix 1 --- e2e/create-cli-e2e/tests/init.e2e.test.ts | 7 ++++++- e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts | 2 +- packages/models/package.json | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/e2e/create-cli-e2e/tests/init.e2e.test.ts b/e2e/create-cli-e2e/tests/init.e2e.test.ts index de5dd73e8..41b34e2ef 100644 --- a/e2e/create-cli-e2e/tests/init.e2e.test.ts +++ b/e2e/create-cli-e2e/tests/init.e2e.test.ts @@ -114,7 +114,12 @@ describe('create-cli-inti', () => { await expect( executeProcess({ command: 'npx', - args: ['@code-pushup/cli print-config', `--userconfig=${userconfig}`], + args: [ + '@code-pushup/cli', + 'print-config', + `--userconfig=${userconfig}`, + `--prefix=${dirname(userconfig)}`, + ], cwd, }), ) diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 1aec8348e..57f27ecab 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -59,7 +59,7 @@ describe('executor command', () => { }); afterEach(async () => { - await teardownTestFolder(baseDir); + // await teardownTestFolder(baseDir); }); it('should execute no specific command by default', async () => { diff --git a/packages/models/package.json b/packages/models/package.json index 643908a8f..c7155554e 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -1,6 +1,6 @@ { "name": "@code-pushup/models", - "version": "0.50.0", + "version": "0.60.0", "license": "MIT", "description": "Model definitions and validators for the Code PushUp CLI", "dependencies": { From cd00c8567eb3b2020a550af83d02d730a2707091 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 1 Oct 2024 21:49:24 +0200 Subject: [PATCH 16/32] fix 2 --- e2e/create-cli-e2e/tests/init.e2e.test.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/e2e/create-cli-e2e/tests/init.e2e.test.ts b/e2e/create-cli-e2e/tests/init.e2e.test.ts index 41b34e2ef..de5dd73e8 100644 --- a/e2e/create-cli-e2e/tests/init.e2e.test.ts +++ b/e2e/create-cli-e2e/tests/init.e2e.test.ts @@ -114,12 +114,7 @@ describe('create-cli-inti', () => { await expect( executeProcess({ command: 'npx', - args: [ - '@code-pushup/cli', - 'print-config', - `--userconfig=${userconfig}`, - `--prefix=${dirname(userconfig)}`, - ], + args: ['@code-pushup/cli print-config', `--userconfig=${userconfig}`], cwd, }), ) From 1071e6010cdc2d27b0ff02e69ba887069601ea9c Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 1 Oct 2024 21:51:41 +0200 Subject: [PATCH 17/32] fix 3 --- e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 57f27ecab..1aec8348e 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -59,7 +59,7 @@ describe('executor command', () => { }); afterEach(async () => { - // await teardownTestFolder(baseDir); + await teardownTestFolder(baseDir); }); it('should execute no specific command by default', async () => { From 465595b60bf059a63049099c4a53ea42e2752781 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Oct 2024 00:14:06 +0200 Subject: [PATCH 18/32] wip --- e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts | 12 +++++++++--- e2e/nx-plugin-e2e/vite.config.e2e.ts | 2 +- packages/nx-plugin/src/executors/internal/config.ts | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 1aec8348e..259b0ada0 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -45,6 +45,12 @@ async function addTargetToWorkspace( codeStrings: 'customPlugin()', }, ], + upload: { + server: 'https://dummy-server.dev', + organization: 'dummy-organization', + apiKey: 'dummy-api-key', + project: 'dummy-project', + }, }); await materializeTree(tree, cwd); } @@ -95,13 +101,13 @@ describe('executor command', () => { ).rejects.toThrow(''); }); - it('should execute collect executor', async () => { + it('should execute collect executor and add report to sub folder named by project', async () => { const cwd = join(baseDir, 'execute-collect-command'); await addTargetToWorkspace(tree, { cwd, project }); const { stdout, code } = await executeProcess({ - command: 'npx', - args: ['nx', 'run', `${project}:code-pushup`, 'collect'], + command: 'nx', + args: ['run', `${project}:code-pushup`, 'collect'], cwd, }); diff --git a/e2e/nx-plugin-e2e/vite.config.e2e.ts b/e2e/nx-plugin-e2e/vite.config.e2e.ts index 778d67ef9..9184cd3b7 100644 --- a/e2e/nx-plugin-e2e/vite.config.e2e.ts +++ b/e2e/nx-plugin-e2e/vite.config.e2e.ts @@ -6,7 +6,7 @@ export default defineConfig({ cacheDir: '../../node_modules/.vite/nx-plugin-e2e', test: { reporters: ['basic'], - testTimeout: 60_000, + testTimeout: 160_000, globals: true, alias: tsconfigPathAliases(), pool: 'threads', diff --git a/packages/nx-plugin/src/executors/internal/config.ts b/packages/nx-plugin/src/executors/internal/config.ts index 1e0295aff..f8437f613 100644 --- a/packages/nx-plugin/src/executors/internal/config.ts +++ b/packages/nx-plugin/src/executors/internal/config.ts @@ -56,7 +56,7 @@ export function uploadConfig( return { ...(projectName ? { - project: applyPrefix ? `${prefix}${projectName}` : projectName, // provide correct project + project: applyPrefix ? `${prefix}${projectName}` : projectName, } : {}), ...parseEnv(process.env), From 088422fcdb619871cbc3699543ea027fbb29517c Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Oct 2024 16:39:19 +0200 Subject: [PATCH 19/32] wip 2 --- tools/src/publish/bin/bump-package.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/src/publish/bin/bump-package.ts b/tools/src/publish/bin/bump-package.ts index d01e1cc98..a336ab0d9 100644 --- a/tools/src/publish/bin/bump-package.ts +++ b/tools/src/publish/bin/bump-package.ts @@ -26,7 +26,7 @@ try { if (version != null) { if (packageJson.version === version) { console.info(`Package version is already set to ${version}.`); - process.exit(0); + // process.exit(0); } console.info( @@ -34,7 +34,11 @@ try { ); writeFileSync( packageJsonFile, - JSON.stringify({ ...packageJson, version }, null, 2), + JSON.stringify( + { ...packageJson, version, description: 'E2E test' }, + null, + 2, + ), ); process.exit(0); } From 66fadfe71d2d9162296965a710f38078da07e533 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Oct 2024 16:54:55 +0200 Subject: [PATCH 20/32] wip 3 --- .../configuration/files/code-pushup.config.ts.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template b/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template index 42da5a08d..b354d3764 100644 --- a/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template +++ b/packages/nx-plugin/src/generators/configuration/files/code-pushup.config.ts.template @@ -3,7 +3,7 @@ // see: https://github.com/code-pushup/cli/blob/main/packages/models/docs/models-reference.md#coreconfig export default { <% if (persist) { %>persist: <%- persist %>,<% } %> - <% if (upload) { %>update: <%- upload %>,<% } %> + <% if (upload) { %>upload: <%- upload %>,<% } %> <% if (plugins) { %>plugins: <%- plugins %>,<% } %> <% if (categories) { %>categories: <%- categories %><% } %> } satisfies CoreConfig; From 103c1df9158d9d61d62ef66b850e169b33419576 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Oct 2024 16:59:05 +0200 Subject: [PATCH 21/32] fix snapshot --- .../configuration/__snapshots__/root-code-pushup.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts index 5056d9071..eae33ec78 100644 --- a/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts +++ b/packages/nx-plugin/src/generators/configuration/__snapshots__/root-code-pushup.config.ts @@ -7,7 +7,7 @@ export default { persist: { filename: 'report-123', }, - update: { + upload: { apiKey: '123', }, plugins: [myPlugin({ timeout: 42 })], From a930e65e6e478913813baca6c8ea0274224f05be Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Oct 2024 17:02:15 +0200 Subject: [PATCH 22/32] dont exec autorun --- .../tests/executor-cli.e2e.test.ts | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index 259b0ada0..a2b65d701 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -147,41 +147,4 @@ describe('executor command', () => { }), ).rejects.toThrow(/report.json/); }); - - it('should execute autorun executor', async () => { - const cwd = join(baseDir, 'execute-autorun-command'); - await addTargetToWorkspace(tree, { cwd, project }); - - const { stdout, code } = await executeProcess({ - command: 'npx', - args: ['nx', 'run', `${project}:code-pushup`, 'autorun'], - cwd, - }); - - expect(code).toBe(0); - const cleanStdout = removeColorCodes(stdout); - expect(cleanStdout).toContain('nx run my-lib:code-pushup autorun'); - expect(cleanStdout).toContain( - '> NX Successfully ran target code-pushup for project my-lib', - ); - - const report = await readJsonFile( - join(cwd, '.code-pushup', project, 'report.json'), - ); - expect(report).toStrictEqual( - expect.objectContaining({ - plugins: [ - expect.objectContaining({ - slug: 'good-feels', - audits: [ - expect.objectContaining({ - displayValue: '✅ Perfect! 👌', - slug: 'always-perfect', - }), - ], - }), - ], - }), - ); - }); }); From a3f9bfa1a3c9f9d3f5413d584b2278398e9eec77 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Oct 2024 17:26:41 +0200 Subject: [PATCH 23/32] update snapshot --- .../tests/__snapshots__/help.e2e.test.ts.snap | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap b/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap index 670d2e5ec..7b5b204e8 100644 --- a/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap +++ b/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap @@ -18,21 +18,17 @@ Commands: Global Options: - --progress Show progress bar in stdout. + --progress Show progress bar in stdout. [boolean] [default: true] - --verbose When true creates more verbose output. This is helpful w - hen debugging. [boolean] [default: false] - --config Path to config file. By default it loads code-pushup.con - fig.(ts|mjs|js). [string] - --tsconfig Path to a TypeScript config, to be used when loading con - fig file. [string] - --skipCategories List of categories to skip. If not set all categories ar - e run. [array] [default: []] - --onlyCategories List of categories to run. If not set all categories are - run. [array] [default: []] - -P, --skipPlugins List of plugins to skip. If not set all plugins are run. + --verbose When true creates more verbose output. This is helpful when + debugging. [boolean] [default: false] + --config Path to config file. By default it loads code-pushup.config + .(ts|mjs|js). [string] + --tsconfig Path to a TypeScript config, to be used when loading config + file. [string] + -p, --onlyPlugins List of plugins to run. If not set all plugins are run. [array] [default: []] - -p, --onlyPlugins List of plugins to run. If not set all plugins are run. + -P, --skipPlugins List of plugins to skip. If not set all plugins are run. [array] [default: []] Persist Options: From a494887e09fa4fd2b367c311ae781660715e8aa4 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 14 Oct 2024 17:48:40 +0200 Subject: [PATCH 24/32] fix --- e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts index a2b65d701..4f5ae3fdd 100644 --- a/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts +++ b/e2e/nx-plugin-e2e/tests/executor-cli.e2e.test.ts @@ -8,7 +8,7 @@ import { materializeTree, } from '@code-pushup/test-nx-utils'; import { teardownTestFolder } from '@code-pushup/test-setup'; -import { removeColorCodes } from '@code-pushup/test-utils'; +import { osAgnosticPath, removeColorCodes } from '@code-pushup/test-utils'; import { executeProcess, readJsonFile } from '@code-pushup/utils'; function relativePathToCwd(testDir: string): string { @@ -37,10 +37,12 @@ async function addTargetToWorkspace( plugins: [ { // @TODO replace with inline plugin - fileImports: `import {customPlugin} from "${join( - relativePathToCwd(cwd), - pathRelativeToPackage, - 'dist/testing/test-utils', + fileImports: `import {customPlugin} from "${osAgnosticPath( + join( + relativePathToCwd(cwd), + pathRelativeToPackage, + 'dist/testing/test-utils', + ), )}";`, codeStrings: 'customPlugin()', }, From 3c594e41c1f72cc9a9c960c54a47d087e34fede8 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:25:39 +0200 Subject: [PATCH 25/32] Update packages/nx-plugin/src/executors/cli/schema.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/nx-plugin/src/executors/cli/schema.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nx-plugin/src/executors/cli/schema.json b/packages/nx-plugin/src/executors/cli/schema.json index 743f64c66..e494c4cc0 100644 --- a/packages/nx-plugin/src/executors/cli/schema.json +++ b/packages/nx-plugin/src/executors/cli/schema.json @@ -8,7 +8,6 @@ "command": { "type": "string", "description": "The command to run.", - "x-prompt": "Which project should configure Code Pushup?", "$default": { "$source": "argv", "index": 0 From c777cb32d8515d1daf20cd2c6a31975e56e63eb1 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:25:52 +0200 Subject: [PATCH 26/32] Update packages/nx-plugin/src/executors/cli/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/nx-plugin/src/executors/cli/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nx-plugin/src/executors/cli/README.md b/packages/nx-plugin/src/executors/cli/README.md index 6ea426ab9..c5e5e8110 100644 --- a/packages/nx-plugin/src/executors/cli/README.md +++ b/packages/nx-plugin/src/executors/cli/README.md @@ -1,7 +1,7 @@ # Command Executor -This executor is used to run the code-pushup CLI autorun command in a Nx workspace. -For details on the CLI command read the [CLI autorun documentation](https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#autorun-command). +This executor is used to run the Code PushUp CLI in an Nx workspace. +For details on the CLI command read the [CLI commands documentation](https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#commands). #### @code-pushup/nx-plugin:cli From 57270dc9e61c925ace9c6f819bc36029917eea7e Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:26:17 +0200 Subject: [PATCH 27/32] Update packages/nx-plugin/src/executors/internal/types.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/nx-plugin/src/executors/internal/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nx-plugin/src/executors/internal/types.ts b/packages/nx-plugin/src/executors/internal/types.ts index 8f49a49f7..58dc91ec8 100644 --- a/packages/nx-plugin/src/executors/internal/types.ts +++ b/packages/nx-plugin/src/executors/internal/types.ts @@ -26,6 +26,7 @@ export type GlobalExecutorOptions = { | 'autorun' | 'print-config' | 'compare' + | 'merge-diffs' | 'history'; bin?: string; verbose?: boolean; From 11c55c8aae08967734e4f968cbd13ea15cd44947 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:26:28 +0200 Subject: [PATCH 28/32] Update packages/nx-plugin/src/plugin/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/nx-plugin/src/plugin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/plugin/README.md b/packages/nx-plugin/src/plugin/README.md index 1ff22e522..dc602af8e 100644 --- a/packages/nx-plugin/src/plugin/README.md +++ b/packages/nx-plugin/src/plugin/README.md @@ -1,6 +1,6 @@ # @code-pushup/nx-plugin -The Nx Plugin for CodePushup, an open source code quality and conformance tool. +The Nx Plugin for [Code PushUp](https://github.com/code-pushup/cli#readme), an open source code quality and conformance tool. Why should you use this plugin? From a92d9afb8adc1ec16c633fb4427898c89c4d3c38 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:26:35 +0200 Subject: [PATCH 29/32] Update packages/nx-plugin/src/plugin/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/nx-plugin/src/plugin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/plugin/README.md b/packages/nx-plugin/src/plugin/README.md index dc602af8e..2210a3dc7 100644 --- a/packages/nx-plugin/src/plugin/README.md +++ b/packages/nx-plugin/src/plugin/README.md @@ -51,7 +51,7 @@ Root/ └── ... ``` -For details visit the [configuration generator docs](../../src/generators/configuration/README.md). +For details visit the [configuration generator docs](../generators/configuration/README.md). With the configuration from above a `code-pushup` target is now present. From 190adfa3705b9c02235a4f317dc1eceb81731af3 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:26:41 +0200 Subject: [PATCH 30/32] Update packages/nx-plugin/src/plugin/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/nx-plugin/src/plugin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-plugin/src/plugin/README.md b/packages/nx-plugin/src/plugin/README.md index 2210a3dc7..89610da1f 100644 --- a/packages/nx-plugin/src/plugin/README.md +++ b/packages/nx-plugin/src/plugin/README.md @@ -77,7 +77,7 @@ Pass positional arguments to execute a specific command, use named arguments to - `nx run :code-pushup collect` - `nx run :code-pushup upload --upload.server=https://staging.code-pushup.dev` -For a full list of command visit the [CodePushup CLI documentation](../../../cli/README.md#commands). +For a full list of command visit the [Code PushUp CLI documentation](../../../cli/README.md#commands). ## Options From b39f5440d54615450a3d5143b2fbdc0127960e07 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:28:49 +0200 Subject: [PATCH 31/32] Update tools/src/publish/bin/bump-package.ts --- tools/src/publish/bin/bump-package.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/src/publish/bin/bump-package.ts b/tools/src/publish/bin/bump-package.ts index a336ab0d9..efd610e06 100644 --- a/tools/src/publish/bin/bump-package.ts +++ b/tools/src/publish/bin/bump-package.ts @@ -26,7 +26,6 @@ try { if (version != null) { if (packageJson.version === version) { console.info(`Package version is already set to ${version}.`); - // process.exit(0); } console.info( From 4e0c034a9ab1dbd041a69c0885dc5b46fa49f48c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Chalk?= Date: Wed, 16 Oct 2024 10:27:16 +0200 Subject: [PATCH 32/32] test(cli-e2e): ensure old e2e setup installs packages from local registry --- .../tests/__snapshots__/help.e2e.test.ts.snap | 22 +++++++++++-------- global-setup.e2e.ts | 3 +++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap b/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap index 7b5b204e8..670d2e5ec 100644 --- a/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap +++ b/e2e/cli-e2e/tests/__snapshots__/help.e2e.test.ts.snap @@ -18,17 +18,21 @@ Commands: Global Options: - --progress Show progress bar in stdout. + --progress Show progress bar in stdout. [boolean] [default: true] - --verbose When true creates more verbose output. This is helpful when - debugging. [boolean] [default: false] - --config Path to config file. By default it loads code-pushup.config - .(ts|mjs|js). [string] - --tsconfig Path to a TypeScript config, to be used when loading config - file. [string] - -p, --onlyPlugins List of plugins to run. If not set all plugins are run. + --verbose When true creates more verbose output. This is helpful w + hen debugging. [boolean] [default: false] + --config Path to config file. By default it loads code-pushup.con + fig.(ts|mjs|js). [string] + --tsconfig Path to a TypeScript config, to be used when loading con + fig file. [string] + --skipCategories List of categories to skip. If not set all categories ar + e run. [array] [default: []] + --onlyCategories List of categories to run. If not set all categories are + run. [array] [default: []] + -P, --skipPlugins List of plugins to skip. If not set all plugins are run. [array] [default: []] - -P, --skipPlugins List of plugins to skip. If not set all plugins are run. + -p, --onlyPlugins List of plugins to run. If not set all plugins are run. [array] [default: []] Persist Options: diff --git a/global-setup.e2e.ts b/global-setup.e2e.ts index 73d33148a..2ae31fc30 100644 --- a/global-setup.e2e.ts +++ b/global-setup.e2e.ts @@ -1,3 +1,4 @@ +import { rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { setup as globalSetup } from './global-setup'; import { setupTestFolder, teardownTestFolder } from './testing/test-setup/src'; @@ -35,6 +36,7 @@ export async function setup() { // package publish const { registry } = activeRegistry.registryData; + await writeFile('.npmrc', `@code-pushup:registry=${registry}`); try { console.info('Publish packages'); nxRunManyPublish({ @@ -64,5 +66,6 @@ export async function teardown() { stopLocalRegistry(stop); nxRunManyNpmUninstall({ parallel: 1 }); } + await rm('.npmrc'); await teardownTestFolder(e2eDir); }