-
Notifications
You must be signed in to change notification settings - Fork 16
feat(nx-plugin): add general executor logic #740
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
Merged
Merged
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
b7c24e6
feat(nx-plugin): add general executor logic
BioPhoton 83acdd7
feat(testing-utils): add test helper for paths
BioPhoton 7a7afcd
test(nx-plugin): add tests
BioPhoton 86a3c0e
fix(nx-plugin): fix lint
BioPhoton ac147ca
fix(nx-plugin): fix test for windows
BioPhoton 5186c69
test(nx-plugin): use test helper for paths
BioPhoton 330e9d6
test(nx-plugin): use test helper for paths 2
BioPhoton 2e15bd6
test(nx-plugin): use test helper for paths 3
BioPhoton e68f754
test(nx-plugin): adjust test
BioPhoton 2d1796f
test(nx-plugin): add tests
BioPhoton 95dfbcf
test(nx-plugin): add tests 2
BioPhoton 4f2f4f9
refactor(nx-plugins): adjust tests and logic
BioPhoton 6d79171
refactor(nx-plugins): adjust tests
BioPhoton 44deae9
Update packages/nx-plugin/src/generators/configuration/generator.ts
BioPhoton e802585
Update packages/nx-plugin/src/generators/configuration/schema.json
BioPhoton 68ce2fa
refactor(nx-plugins): adjust docs
BioPhoton 2ad2e93
refactor(nx-plugins): reduce logic
BioPhoton 1972ba8
refactor(nx-plugins): cleanup
BioPhoton 5573e7a
refactor(nx-plugins): format
BioPhoton 0fda1da
Update packages/nx-plugin/src/executors/internal/env.unit.test.ts
BioPhoton fc411fa
refactor(nx-plugins): adjust outputDir
BioPhoton File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| export const ENV = { | ||
| CP_SERVER: 'https://portal.code.pushup.dev', | ||
| CP_ORGANIZATION: 'code-pushup', | ||
| CP_PROJECT: 'utils', | ||
| CP_API_KEY: '23456789098765432345678909876543', | ||
| CP_TIMEOUT: '9', | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| export function createCliCommand( | ||
| command: string, | ||
| args: Record<string, unknown>, | ||
| ): string { | ||
| return `npx @code-pushup/cli ${command} ${objectToCliArgs(args).join(' ')}`; | ||
| } | ||
|
|
||
| type ArgumentValue = number | string | boolean | string[]; | ||
| export type CliArgsObject<T extends object = Record<string, ArgumentValue>> = | ||
| T extends never | ||
| ? // eslint-disable-next-line @typescript-eslint/naming-convention | ||
| Record<string, ArgumentValue | undefined> | { _: string } | ||
| : T; | ||
| // @TODO import from @code-pushup/utils => get rid of poppins for cjs support | ||
| // eslint-disable-next-line sonarjs/cognitive-complexity | ||
| export function objectToCliArgs< | ||
| T extends object = Record<string, ArgumentValue>, | ||
| >(params?: CliArgsObject<T>): string[] { | ||
| if (!params) { | ||
| return []; | ||
| } | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
| return Object.entries(params).flatMap(([key, value]) => { | ||
| // process/file/script | ||
| if (key === '_') { | ||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
| return Array.isArray(value) ? value : [`${value}`]; | ||
| } | ||
| const prefix = key.length === 1 ? '-' : '--'; | ||
| // "-*" arguments (shorthands) | ||
| if (Array.isArray(value)) { | ||
| return value.map(v => `${prefix}${key}="${v}"`); | ||
| } | ||
|
|
||
| if (typeof value === 'object') { | ||
| return Object.entries(value as Record<string, unknown>).map( | ||
| ([k, v]) => `${prefix}${key}.${k}="${v?.toString()}"`, | ||
| ); | ||
| } | ||
|
|
||
| if (typeof value === 'string') { | ||
| return [`${prefix}${key}="${value}"`]; | ||
| } | ||
|
|
||
| if (typeof value === 'number') { | ||
| return [`${prefix}${key}=${value}`]; | ||
| } | ||
|
|
||
| if (typeof value === 'boolean') { | ||
| return [`${prefix}${value ? '' : 'no-'}${key}`]; | ||
| } | ||
|
|
||
| if (value === undefined) { | ||
| return []; | ||
| } | ||
|
|
||
| throw new Error(`Unsupported type ${typeof value} for key ${key}`); | ||
| }); | ||
| } |
84 changes: 84 additions & 0 deletions
84
packages/nx-plugin/src/executors/internal/cli.unit.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| import { describe, expect, it } from 'vitest'; | ||
| import { createCliCommand, objectToCliArgs } from './cli'; | ||
|
|
||
| describe('objectToCliArgs', () => { | ||
| it('should empty params', () => { | ||
| const result = objectToCliArgs(); | ||
| expect(result).toEqual([]); | ||
| }); | ||
|
|
||
| it('should handle the "_" argument as script', () => { | ||
| const params = { _: 'bin.js' }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual(['bin.js']); | ||
| }); | ||
|
|
||
| it('should handle the "_" argument with multiple values', () => { | ||
| const params = { _: ['bin.js', '--help'] }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual(['bin.js', '--help']); | ||
| }); | ||
|
|
||
| it('should handle shorthands arguments', () => { | ||
| const params = { | ||
| e: `test`, | ||
| }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual([`-e="${params.e}"`]); | ||
| }); | ||
|
|
||
| it('should handle string arguments', () => { | ||
| const params = { name: 'Juanita' }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual(['--name="Juanita"']); | ||
| }); | ||
|
|
||
| it('should handle number arguments', () => { | ||
| const params = { parallel: 5 }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual(['--parallel=5']); | ||
| }); | ||
|
|
||
| it('should handle boolean arguments', () => { | ||
| const params = { progress: true }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual(['--progress']); | ||
| }); | ||
|
|
||
| it('should handle negated boolean arguments', () => { | ||
| const params = { progress: false }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual(['--no-progress']); | ||
| }); | ||
|
|
||
| it('should handle array of string arguments', () => { | ||
| const params = { format: ['json', 'md'] }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toEqual(['--format="json"', '--format="md"']); | ||
| }); | ||
|
|
||
| it('should handle objects', () => { | ||
| const params = { format: { json: 'simple' } }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toStrictEqual(['--format.json="simple"']); | ||
| }); | ||
|
|
||
| it('should handle objects with undefined', () => { | ||
| const params = { format: undefined }; | ||
| const result = objectToCliArgs(params); | ||
| expect(result).toStrictEqual([]); | ||
| }); | ||
|
|
||
| it('should throw error for unsupported type', () => { | ||
| expect(() => objectToCliArgs({ param: Symbol('') })).toThrow( | ||
| 'Unsupported type', | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe('createCliCommand', () => { | ||
| it('should create command out of command name and an object for arguments', () => { | ||
| const result = createCliCommand('autorun', { verbose: true }); | ||
| expect(result).toBe('npx @code-pushup/cli autorun --verbose'); | ||
| }); | ||
| }); |
45 changes: 45 additions & 0 deletions
45
packages/nx-plugin/src/executors/internal/config.integration.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { MockInstance, describe, expect } from 'vitest'; | ||
| import { ENV } from '../../../mock/fixtures/env'; | ||
| import { uploadConfig } from './config'; | ||
| import * as env from './env'; | ||
|
|
||
| describe('uploadConfig', () => { | ||
| let parseEnvSpy: MockInstance<[], NodeJS.ProcessEnv>; | ||
| let processEnvSpy: MockInstance<[], NodeJS.ProcessEnv>; | ||
|
|
||
| beforeAll(() => { | ||
| processEnvSpy = vi.spyOn(process, 'env', 'get').mockReturnValue({}); | ||
| parseEnvSpy = vi.spyOn(env, 'parseEnv'); | ||
| }); | ||
|
|
||
| afterAll(() => { | ||
| processEnvSpy.mockRestore(); | ||
| parseEnvSpy.mockRestore(); | ||
| }); | ||
|
|
||
| it('should call parseEnv function with values from process.env', () => { | ||
| processEnvSpy.mockReturnValue(ENV); | ||
| expect( | ||
| uploadConfig( | ||
| {}, | ||
| { | ||
| workspaceRoot: 'workspaceRoot', | ||
| projectConfig: { | ||
| name: 'my-app', | ||
| root: 'root', | ||
| }, | ||
| }, | ||
| ), | ||
| ).toEqual( | ||
| expect.objectContaining({ | ||
| server: ENV.CP_SERVER, | ||
| apiKey: ENV.CP_API_KEY, | ||
| organization: ENV.CP_ORGANIZATION, | ||
| project: ENV.CP_PROJECT, | ||
| }), | ||
| ); | ||
|
|
||
| expect(parseEnvSpy).toHaveBeenCalledTimes(1); | ||
| expect(parseEnvSpy).toHaveBeenCalledWith(ENV); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { join } from 'node:path'; | ||
| import type { PersistConfig, UploadConfig } from '@code-pushup/models'; | ||
| import { parseEnv } from './env'; | ||
| import { | ||
| BaseNormalizedExecutorContext, | ||
| GlobalExecutorOptions, | ||
| ProjectExecutorOnlyOptions, | ||
| } from './types'; | ||
|
|
||
| export function globalConfig( | ||
| options: Partial<GlobalExecutorOptions>, | ||
| context: BaseNormalizedExecutorContext, | ||
| ): Required<GlobalExecutorOptions> { | ||
| const { projectConfig } = context; | ||
| const { root: projectRoot = '' } = projectConfig ?? {}; | ||
| // For better debugging use `--verbose --no-progress` as default | ||
| const { verbose, progress, config } = options; | ||
| return { | ||
| verbose: !!verbose, | ||
| progress: !!progress, | ||
| config: config ?? join(projectRoot, 'code-pushup.config.ts'), | ||
| }; | ||
| } | ||
|
|
||
| export function persistConfig( | ||
| options: Partial<PersistConfig & ProjectExecutorOnlyOptions>, | ||
| context: BaseNormalizedExecutorContext, | ||
| ): Partial<PersistConfig> { | ||
| const { projectConfig } = context; | ||
|
|
||
| const { name: projectName = '', root: projectRoot = '' } = | ||
| projectConfig ?? {}; | ||
| const { | ||
| format, | ||
| outputDir = join(projectRoot, '.code-pushup', projectName), // always in <root>/.code-pushup/<project-name>, | ||
| filename, | ||
| } = options; | ||
|
|
||
| return { | ||
| outputDir, | ||
| ...(format ? { format } : {}), | ||
| ...(filename ? { filename } : {}), | ||
| }; | ||
| } | ||
|
|
||
| export function uploadConfig( | ||
| options: Partial<UploadConfig & ProjectExecutorOnlyOptions>, | ||
| context: BaseNormalizedExecutorContext, | ||
| ): Partial<UploadConfig> { | ||
| const { projectConfig, workspaceRoot } = context; | ||
|
|
||
| const { name: projectName } = projectConfig ?? {}; | ||
| const { projectPrefix, server, apiKey, organization, project, timeout } = | ||
| options; | ||
| const applyPrefix = workspaceRoot === '.'; | ||
| const prefix = projectPrefix ? `${projectPrefix}-` : ''; | ||
| return { | ||
| ...(projectName | ||
| ? { | ||
| project: applyPrefix ? `${prefix}${projectName}` : projectName, // provide correct project | ||
| } | ||
| : {}), | ||
| ...parseEnv(process.env), | ||
| ...Object.fromEntries( | ||
| Object.entries({ server, apiKey, organization, project, timeout }).filter( | ||
| ([_, v]) => v !== undefined, | ||
| ), | ||
| ), | ||
| }; | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.