Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nx-plugin): add executor to nx-plugin #737

Merged
merged 116 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
870fc10
feat(nx-plugin): add basic executor
BioPhoton Apr 15, 2024
fb701fd
wip
BioPhoton Apr 15, 2024
cd143ec
wip
BioPhoton Apr 15, 2024
405a47b
wip
BioPhoton Apr 15, 2024
d630581
refactor(nx-plugin): polish executor logic
BioPhoton Apr 16, 2024
922f2bc
wip
BioPhoton Jul 3, 2024
9b065c6
Merge branch 'main' into add-executor-to-nx-plugin
BioPhoton Jul 3, 2024
c8f68ee
feat(nx-plugin): adjust executor
BioPhoton Jul 8, 2024
34e16fd
Merge branch 'main' into add-executor-to-nx-plugin
BioPhoton Jul 8, 2024
1f21131
feat(nx-plugin): fix lint
BioPhoton Jul 8, 2024
3827a3c
feat(nx-plugin): fix unit-test
BioPhoton Jul 8, 2024
cf78b86
wip
BioPhoton Jul 8, 2024
d9858db
wip
BioPhoton Jul 8, 2024
aae0ad0
wip
BioPhoton Jul 8, 2024
0cc5154
wip
BioPhoton Jul 8, 2024
75943a4
wip
BioPhoton Jul 8, 2024
1e83a23
wip
BioPhoton Jul 8, 2024
25c2249
wip
BioPhoton Jul 8, 2024
2565427
wip
BioPhoton Jul 8, 2024
2db1813
wip
BioPhoton Jul 8, 2024
7811728
wip
BioPhoton Jul 8, 2024
7057b19
wip
BioPhoton Jul 8, 2024
9355e5c
wip
BioPhoton Jul 8, 2024
a36b50f
wip
BioPhoton Jul 8, 2024
0e51f38
wip
BioPhoton Jul 9, 2024
a3ebae2
wip
BioPhoton Jul 9, 2024
acdde87
wip
BioPhoton Jul 9, 2024
e68b265
wip
BioPhoton Jul 9, 2024
52063a6
add texts
BioPhoton Jul 9, 2024
65446b7
wip
BioPhoton Jul 9, 2024
556e3e7
wip
BioPhoton Jul 9, 2024
fb363d9
wip
BioPhoton Jul 9, 2024
eaa6ce1
wip
BioPhoton Jul 9, 2024
414181c
wip
BioPhoton Jul 9, 2024
937a3d9
wip
BioPhoton Jul 9, 2024
a22c47c
wip
BioPhoton Jul 9, 2024
06b7f73
wip
BioPhoton Jul 10, 2024
b7c24e6
feat(nx-plugin): add general executor logic
BioPhoton Jul 10, 2024
83acdd7
feat(testing-utils): add test helper for paths
BioPhoton Jul 10, 2024
7a7afcd
test(nx-plugin): add tests
BioPhoton Jul 10, 2024
86a3c0e
fix(nx-plugin): fix lint
BioPhoton Jul 10, 2024
ac147ca
fix(nx-plugin): fix test for windows
BioPhoton Jul 10, 2024
5186c69
test(nx-plugin): use test helper for paths
BioPhoton Jul 11, 2024
330e9d6
test(nx-plugin): use test helper for paths 2
BioPhoton Jul 11, 2024
2e15bd6
test(nx-plugin): use test helper for paths 3
BioPhoton Jul 11, 2024
e68f754
test(nx-plugin): adjust test
BioPhoton Jul 11, 2024
2d1796f
test(nx-plugin): add tests
BioPhoton Jul 11, 2024
95dfbcf
test(nx-plugin): add tests 2
BioPhoton Jul 11, 2024
4f2f4f9
refactor(nx-plugins): adjust tests and logic
BioPhoton Jul 12, 2024
6d79171
refactor(nx-plugins): adjust tests
BioPhoton Jul 12, 2024
44deae9
Update packages/nx-plugin/src/generators/configuration/generator.ts
BioPhoton Jul 12, 2024
e802585
Update packages/nx-plugin/src/generators/configuration/schema.json
BioPhoton Jul 12, 2024
68ce2fa
refactor(nx-plugins): adjust docs
BioPhoton Jul 12, 2024
2ad2e93
refactor(nx-plugins): reduce logic
BioPhoton Jul 12, 2024
1972ba8
refactor(nx-plugins): cleanup
BioPhoton Jul 12, 2024
5573e7a
refactor(nx-plugins): format
BioPhoton Jul 12, 2024
0fda1da
Update packages/nx-plugin/src/executors/internal/env.unit.test.ts
BioPhoton Jul 12, 2024
fc411fa
refactor(nx-plugins): adjust outputDir
BioPhoton Jul 12, 2024
5885d18
Merge branch 'executor-utils' into add-executor-to-nx-plugin
BioPhoton Jul 12, 2024
04d4c11
merge utils
BioPhoton Jul 12, 2024
74c43a8
Merge branch 'main' into add-executor-to-nx-plugin
BioPhoton Jul 12, 2024
94f5fe0
cleanup
BioPhoton Jul 12, 2024
3977d59
fix tests
BioPhoton Jul 12, 2024
3472f48
fix tests
BioPhoton Jul 12, 2024
8de7250
fix tests
BioPhoton Jul 12, 2024
5403273
fix ci
BioPhoton Jul 12, 2024
2a31c3b
fix tests
BioPhoton Jul 12, 2024
5ab915c
fix tests
BioPhoton Jul 12, 2024
2b6cff6
fix lint
BioPhoton Jul 12, 2024
62683fd
fix test
BioPhoton Jul 12, 2024
13812f4
Update project.json
BioPhoton Jul 15, 2024
4c68466
wip
BioPhoton Jul 15, 2024
e364691
wip
BioPhoton Jul 15, 2024
c3aa7e8
Update packages/nx-plugin/src/executors/autorun/utils.ts
BioPhoton Jul 16, 2024
d67353e
refactor(nx-plugin): fix test
BioPhoton Jul 16, 2024
4d0260c
refactor(nx-plugin): add autorun executor usage example
BioPhoton Jul 17, 2024
56d61f2
Merge branch 'main' into add-executor-to-nx-plugin
BioPhoton Jul 17, 2024
231218f
merge main
BioPhoton Jul 17, 2024
47d0011
refactor: use nx-plugin:autorun options
BioPhoton Jul 17, 2024
b37e553
wip
BioPhoton Jul 17, 2024
99cd568
wip
BioPhoton Jul 17, 2024
cd12054
wip
BioPhoton Jul 17, 2024
57b64b8
wip
BioPhoton Jul 17, 2024
675c05d
Update packages/nx-plugin/src/executors/autorun/Readme.md
BioPhoton Jul 20, 2024
20e0f78
test(nx-plugin): refactor tests
BioPhoton Jul 21, 2024
100e10a
docs(nx-plugin): add better text
BioPhoton Jul 21, 2024
9773acc
docs(nx-plugin): fix typo
BioPhoton Jul 21, 2024
1948804
docs(nx-plugin): fix typo
BioPhoton Jul 21, 2024
bfcfb7e
docs(nx-plugin): fix typo
BioPhoton Jul 21, 2024
8aaa544
test(nx-plugin): refactor mocking strategy
BioPhoton Jul 21, 2024
7db01ff
Update packages/nx-plugin/src/executors/autorun/schema.json
BioPhoton Jul 21, 2024
83bb0bc
refactor(nx-plugin): fix bad descriptions in schema
BioPhoton Jul 21, 2024
f80c1b4
refactor(nx-plugin): lint
BioPhoton Jul 21, 2024
a704286
test(nx-plugin): fix test for CI
BioPhoton Jul 21, 2024
8f6a398
test(nx-plugin): fix test
BioPhoton Jul 21, 2024
4e94077
test(nx-plugin): fix format normalization
BioPhoton Jul 21, 2024
e18c731
wip
BioPhoton Jul 21, 2024
8de874a
wip
BioPhoton Jul 21, 2024
2c7011a
Update .github/workflows/code-pushup.yml
BioPhoton Jul 21, 2024
ff9613b
Merge branch 'main' into add-executor-to-nx-plugin
BioPhoton Jul 22, 2024
b534f23
refactor(utils): support nested objects in cliObjToArgs
BioPhoton Jul 22, 2024
d1c960c
refactor(utils): fix lint
BioPhoton Jul 22, 2024
6c270d3
refactor(utils): fix format
BioPhoton Jul 22, 2024
a1d03f1
Merge branch 'main' into add-executor-to-nx-plugin
BioPhoton Jul 22, 2024
069372f
refactor(nx-plugin): fix error logging
BioPhoton Jul 22, 2024
e576eb7
refactor: fix main and configure models cp config
BioPhoton Jul 23, 2024
0ce701d
refactor: format
BioPhoton Jul 23, 2024
1126253
refactor: types
BioPhoton Jul 23, 2024
4df20f5
refactor: lint
BioPhoton Jul 23, 2024
06dd2b6
Update packages/nx-plugin/src/executors/autorun/executor.ts
BioPhoton Jul 23, 2024
94afcbc
Merge branch 'main' into add-executor-to-nx-plugin
BioPhoton Jul 23, 2024
eae02e2
test(test-utils): remove default value for project name
BioPhoton Jul 23, 2024
e7aedb6
Update packages/nx-plugin/src/executors/autorun/utils.ts
BioPhoton Jul 23, 2024
02794d7
rename
BioPhoton Jul 23, 2024
009d6f2
fix typo
BioPhoton Jul 23, 2024
8764e8e
remove config
BioPhoton Jul 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
**/*.mock.*
**/code-pushup.config.ts
**/mocks/fixtures/**
9 changes: 9 additions & 0 deletions packages/nx-plugin/executors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"executors": {
"autorun": {
"implementation": "./src/executors/autorun/executor",
"schema": "./src/executors/autorun/schema.json",
"description": "CodePushup CLI autorun command executor. Executes the @code-pushup/cli autorun command See: https://github.com/code-pushup/cli/blob/main/packages/cli/README.md#autorun-command"
}
}
}
16 changes: 16 additions & 0 deletions packages/nx-plugin/mock/utils/executor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NormalizedExecutorContext } from '../../src/executors/internal/context';

Check failure on line 1 in packages/nx-plugin/mock/utils/executor.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<↗> Code coverage | Branch coverage

1st branch is not taken in any test case.

export function normalizedExecutorContext(
nameOrOpt: string | { projectName: string },
): NormalizedExecutorContext {
const { projectName } =
typeof nameOrOpt === 'string' ? { projectName: nameOrOpt } : nameOrOpt;

Check failure on line 7 in packages/nx-plugin/mock/utils/executor.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<↗> Code coverage | Branch coverage

1st branch is not taken in any test case.
return {
projectName,
workspaceRoot: 'workspaceRoot',
projectConfig: {
name: projectName,
root: 'root',
},
};
}
3 changes: 2 additions & 1 deletion packages/nx-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
"type": "commonjs",
"main": "./src/index.js",
"typings": "./src/index.d.ts",
"generators": "./generators.json"
"generators": "./generators.json",
"executors": "./executors.json"
}
1 change: 1 addition & 0 deletions packages/nx-plugin/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/nx-plugin/src",
"projectType": "library",
"implicitDependencies": ["cli"],
"targets": {
"build": {
"executor": "@nx/js:tsc",
Expand Down
60 changes: 60 additions & 0 deletions packages/nx-plugin/src/executors/autorun/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Autorun 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).

#### @code-pushup/nx-plugin:autorun

## Usage

// project.json

```json
{
"name": "my-project",
"targets": {
"code-pushup": {
"executor": "@code-pushup/nx-plugin:autorun"
}
}
}
```

By default, the Nx plugin will derive the options from the executor config.

The following things happen:

- the output directory defaults to `${workspaceRoot}/.code-pushup/${projectName}`
- the config file defaults to `${projectRoot}/code-pushup.config.ts`
- parses terminal arguments and forwards them to the CLI command (they override the executor config)
- the CLI command is executed

```jsonc
{
"name": "my-project",
"targets": {
"code-pushup": {
"executor": "@code-pushup/nx-plugin:autorun",
"options": {
"projectPrefix": "cli", // upload.project = cli-my-project
"verbose": true,
"progress": false
// persist and upload options as defined in CoreConfig
}
}
}
}
```

Show what will be executed without actually executing it:

`nx run my-project:code-pushup --dryRun`

## Options

| Name | type | description |
| ----------------- | --------- | ------------------------------------------------------------------ |
| **projectPrefix** | `string` | prefix for upload.project on non root projects |
| **dryRun** | `boolean` | To debug the executor, dry run the command without real execution. |

For all other options see the [CLI autorun documentation](../../cli/packages/cli/README.md#autorun-command).
1 change: 1 addition & 0 deletions packages/nx-plugin/src/executors/autorun/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const AUTORUN_COMMAND = 'autorun';
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// eslint-disable-next-line n/no-sync
import { execSync } from 'node:child_process';
import { afterEach, expect, vi } from 'vitest';
import { executorContext } from '@code-pushup/test-utils';
import runAutorunExecutor from './executor';
import * as utils from './utils';

vi.mock('node:child_process', async () => {
const actual = await vi.importActual('node:child_process');
return {
...actual,
// eslint-disable-next-line n/no-sync
execSync: vi.fn(),
};
});

describe('runAutorunExecutor', () => {
const parseAutorunExecutorOptionsSpy = vi.spyOn(
utils,
'parseAutorunExecutorOptions',
);
afterEach(() => {
parseAutorunExecutorOptionsSpy.mockReset();
});
it('should normalize context, parse CLI options and execute command', async () => {
const output = await runAutorunExecutor(
{ verbose: true },
executorContext('utils'),
);
expect(output.success).toBe(true);

expect(parseAutorunExecutorOptionsSpy).toHaveBeenCalledTimes(1);

//is context normalized
expect(parseAutorunExecutorOptionsSpy).toHaveBeenCalledWith(
{ verbose: true },
expect.objectContaining({
projectConfig: expect.objectContaining({ name: 'utils' }),
}),
);
// eslint-disable-next-line n/no-sync
expect(execSync).toHaveBeenCalledTimes(1);
// eslint-disable-next-line n/no-sync
expect(execSync).toHaveBeenCalledWith(expect.stringContaining('utils'), {});
});
});
53 changes: 53 additions & 0 deletions packages/nx-plugin/src/executors/autorun/executor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { ExecutorContext, logger } from '@nx/devkit';
// eslint-disable-next-line n/no-sync
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';

export type ExecutorOutput = {
success: boolean;
command?: string;
error?: Error;
};

export default function runAutorunExecutor(
terminalAndExecutorOptions: AutorunCommandExecutorOptions,
context: ExecutorContext,
) {
const normalizedContext = normalizeContext(context);
const cliArgumentObject = parseAutorunExecutorOptions(
terminalAndExecutorOptions,
normalizedContext,
);
const { dryRun, verbose } = terminalAndExecutorOptions;
const command = createCliCommand(AUTORUN_COMMAND, cliArgumentObject);
const commandOptions = context.cwd ? { cwd: context.cwd } : {};
if (verbose) {
logger.info(`Run ${AUTORUN_COMMAND} executor`);
logger.info(`Command: ${command}`);
}
if (dryRun) {

Check failure on line 32 in packages/nx-plugin/src/executors/autorun/executor.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<↗> Code coverage | Branch coverage

1st branch is not taken in any test case.
logger.warn(`DryRun execution of: ${command}`);
} else {
try {
// @TODO use executeProcess instead of execSync -> non blocking, logs #761
// eslint-disable-next-line n/no-sync
execSync(command, commandOptions);
} catch (error) {

Check failure on line 39 in packages/nx-plugin/src/executors/autorun/executor.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<↗> Code coverage | Branch coverage

1st branch is not taken in any test case.

Check failure on line 39 in packages/nx-plugin/src/executors/autorun/executor.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<↗> Code coverage | Branch coverage

1st branch is not taken in any test case.
logger.error(error);
return Promise.resolve({
success: false,
command,
error,
});
}

Check warning on line 46 in packages/nx-plugin/src/executors/autorun/executor.ts

View workflow job for this annotation

GitHub Actions / Code PushUp

<↗> Code coverage | Line coverage

Lines 40-46 are not covered in any test case.
}

return Promise.resolve({
success: true,
command,
} satisfies ExecutorOutput);
}
115 changes: 115 additions & 0 deletions packages/nx-plugin/src/executors/autorun/executor.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { logger } from '@nx/devkit';
// eslint-disable-next-line n/no-sync
import { execSync } from 'node:child_process';
import { afterEach, beforeEach, expect, vi } from 'vitest';
import { executorContext } from '@code-pushup/test-utils';
import runAutorunExecutor from './executor';

vi.mock('node:child_process', async () => {
const actual = await vi.importActual('node:child_process');

return {
...actual,
// eslint-disable-next-line n/no-sync
execSync: vi.fn((command: string) => {
if (command.includes('THROW_ERROR')) {
throw new Error(command);
}
}),
};
});

describe('runAutorunExecutor', () => {
const envSpy = vi.spyOn(process, 'env', 'get');
const loggerInfoSpy = vi.spyOn(logger, 'info');
const loggerWarnSpy = vi.spyOn(logger, 'warn');

beforeEach(() => {
envSpy.mockReturnValue({});
});
afterEach(() => {
loggerWarnSpy.mockReset();
loggerInfoSpy.mockReset();
envSpy.mockReset().mockReturnValue({});
});

it('should call execSync with autorun command and return result', async () => {
const output = await runAutorunExecutor({}, executorContext('utils'));
expect(output.success).toBe(true);
expect(output.command).toMatch('npx @code-pushup/cli autorun');
// eslint-disable-next-line n/no-sync
expect(execSync).toHaveBeenCalledWith(
expect.stringContaining('npx @code-pushup/cli autorun'),
{},
);
});

it('should normalize context', async () => {
const output = await runAutorunExecutor(
{},
{
...executorContext('utils'),
cwd: 'cwd-form-context',
},
);
expect(output.success).toBe(true);
expect(output.command).toMatch('utils');
// eslint-disable-next-line n/no-sync
expect(execSync).toHaveBeenCalledWith(expect.stringContaining('utils'), {
cwd: 'cwd-form-context',
});
});

it('should process executorOptions', async () => {
const output = await runAutorunExecutor(
{ persist: { filename: 'REPORT' } },
executorContext('testing-utils'),
);
expect(output.success).toBe(true);
expect(output.command).toMatch('--persist.filename="REPORT"');
});

it('should create command from context, options and arguments', async () => {
envSpy.mockReturnValue({ CP_PROJECT: 'CLI' });
const output = await runAutorunExecutor(
{ persist: { filename: 'REPORT', format: ['md', 'json'] } },
executorContext('core'),
);
expect(output.command).toMatch('--persist.filename="REPORT"');
expect(output.command).toMatch(
'--persist.format="md" --persist.format="json"',
);
expect(output.command).toMatch('--upload.project="CLI"');
});

it('should log information if verbose is set', async () => {
const output = await runAutorunExecutor(
{ verbose: true },
{ ...executorContext('github-action'), cwd: '<CWD>' },
);
// eslint-disable-next-line n/no-sync
expect(execSync).toHaveBeenCalledTimes(1);

expect(output.command).toMatch('--verbose');
expect(loggerWarnSpy).toHaveBeenCalledTimes(0);
expect(loggerInfoSpy).toHaveBeenCalledTimes(2);
expect(loggerInfoSpy).toHaveBeenCalledWith(
expect.stringContaining('Run autorun executor'),
);
expect(loggerInfoSpy).toHaveBeenCalledWith(
expect.stringContaining('Command: npx @code-pushup/cli autorun'),
);
});

it('should log command if dryRun is set', async () => {
await runAutorunExecutor({ dryRun: true }, executorContext('utils'));

expect(loggerInfoSpy).toHaveBeenCalledTimes(0);
expect(loggerWarnSpy).toHaveBeenCalledTimes(1);
expect(loggerWarnSpy).toHaveBeenCalledWith(
expect.stringContaining(
'DryRun execution of: npx @code-pushup/cli autorun --dryRun',
),
);
});
});
Loading