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(cli): initial collect command #45

Merged
merged 108 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
d067799
feat(models): setup types and parser with zod
BioPhoton Aug 30, 2023
46d4408
fix(models): add package.lock
BioPhoton Aug 30, 2023
0e5ef27
refactor(models): format
BioPhoton Aug 30, 2023
1369565
refactor(models): align package.json
BioPhoton Aug 30, 2023
63c1bcc
refactor(models): format
BioPhoton Aug 30, 2023
8096b85
refactor(models): package.lock
BioPhoton Aug 31, 2023
70fc405
Update packages/models/project.json
BioPhoton Aug 31, 2023
c885349
Update packages/models/project.json
BioPhoton Aug 31, 2023
a71955e
feat(utils): add collect utils
BioPhoton Aug 31, 2023
337c9c2
refactor(models): remove budgets from initial code base
BioPhoton Aug 31, 2023
aaa17a5
Update packages/models/src/lib/category-config.ts
BioPhoton Aug 31, 2023
0a67872
refactor(models): remove budgets
BioPhoton Aug 31, 2023
2ce3136
Merge branch 'main' into add-package-for-cli-independent-logic
BioPhoton Sep 1, 2023
48dd062
Update packages/models/src/lib/plugins.ts
BioPhoton Sep 1, 2023
3b35871
Update packages/models/src/lib/plugins.ts
BioPhoton Sep 1, 2023
34ceba1
Update packages/models/src/lib/upload.ts
BioPhoton Sep 1, 2023
71c5a4d
Update packages/models/src/lib/upload.ts
BioPhoton Sep 1, 2023
05486fd
refactor(models): add int and non negative validators
BioPhoton Sep 1, 2023
23cf79a
refactor(models): add cross field validators
BioPhoton Sep 4, 2023
d52de86
refactor(models): format files
BioPhoton Sep 4, 2023
b9e1244
refactor(models): implement feedback from PR, format
BioPhoton Sep 5, 2023
8dc0e53
Merge branch 'main' into add-package-for-cli-independent-logic
BioPhoton Sep 5, 2023
9bc21e6
Update packages/models/project.json
BioPhoton Sep 5, 2023
20ccf92
Update packages/models/src/lib/category-config.ts
BioPhoton Sep 5, 2023
401ed9a
Update packages/models/src/lib/implementation/schemas.ts
BioPhoton Sep 5, 2023
cbee718
Update packages/models/src/lib/category-config.ts
BioPhoton Sep 5, 2023
a000ee9
Update packages/models/src/lib/core-config.spec.ts
BioPhoton Sep 5, 2023
651498b
Update packages/models/src/lib/output.ts
BioPhoton Sep 5, 2023
4ec4bc4
Update packages/models/src/lib/output.ts
BioPhoton Sep 5, 2023
c0b4164
Update packages/models/src/lib/plugins.ts
BioPhoton Sep 5, 2023
462c5ed
Update packages/models/src/lib/plugins.ts
BioPhoton Sep 5, 2023
deb7209
Update packages/models/src/lib/core-config.spec.ts
BioPhoton Sep 5, 2023
d3cbc08
Update packages/models/src/lib/output.ts
BioPhoton Sep 5, 2023
82cc90f
Update packages/models/src/lib/output.ts
BioPhoton Sep 5, 2023
7fcdf05
Update packages/models/src/lib/core-config.ts
BioPhoton Sep 5, 2023
b7e985c
Update packages/models/src/lib/core-config.ts
BioPhoton Sep 5, 2023
fca30a4
Update packages/models/src/lib/implementation/utils.spec.ts
BioPhoton Sep 5, 2023
74e6594
Update packages/models/src/lib/implementation/utils.spec.ts
BioPhoton Sep 5, 2023
9a1a2c6
Merge remote-tracking branch 'origin/main' into add-models
BioPhoton Sep 5, 2023
4e0fd2e
refactor(models): add regex and validators and tests
BioPhoton Sep 5, 2023
66a5399
refactor(models): fix tests and lint errors
BioPhoton Sep 5, 2023
ce2362b
refactor(models): fix tests and comments
BioPhoton Sep 5, 2023
1c0e36e
refactor(models): add test case
BioPhoton Sep 5, 2023
9979695
Update schemas.ts
BioPhoton Sep 6, 2023
c000792
Update schemas.ts
BioPhoton Sep 6, 2023
acf20d6
Update schemas.ts
BioPhoton Sep 6, 2023
8b3c562
Update schemas.ts
BioPhoton Sep 6, 2023
ad2f7e9
Update utils.ts
BioPhoton Sep 6, 2023
ea3d7b1
Update utils.ts
BioPhoton Sep 6, 2023
5406c96
Update global-cli-options.ts
BioPhoton Sep 6, 2023
d6a82d6
refactor(models): merge suggestions, fix tests
BioPhoton Sep 6, 2023
7831a5a
Update packages/models/src/lib/category-config.spec.ts
BioPhoton Sep 6, 2023
2f7b498
Update packages/models/src/lib/implementation/schemas.ts
BioPhoton Sep 6, 2023
8f2e201
Update packages/models/src/lib/category-config.spec.ts
BioPhoton Sep 6, 2023
41b4edc
refactor(models): reinstall
BioPhoton Sep 6, 2023
9e97fa4
refactor(models): fix dependencies
BioPhoton Sep 6, 2023
c54d461
refactor(models): fix dependencies 2
BioPhoton Sep 6, 2023
d2ea0f4
refactor(models): fix dependencies 2
BioPhoton Sep 6, 2023
d6fd5e8
refactor(models): fix dependencies 3
BioPhoton Sep 6, 2023
28e6f63
Merge branch 'add-models' into add-package-for-cli-independent-logic
BioPhoton Sep 6, 2023
9719316
Merge branch 'main' into add-package-for-cli-independent-logic
BioPhoton Sep 6, 2023
437334d
refactor(models): adopt refinement logic
BioPhoton Sep 6, 2023
b217954
refactor(models): make buildable
BioPhoton Sep 6, 2023
e7d5c5c
refactor(utils): make buildable, adopt tests
BioPhoton Sep 6, 2023
1d63d45
refactor(utils): add vfs for unit tests
BioPhoton Sep 6, 2023
295cfd3
refactor(utils): remove vfs code
BioPhoton Sep 6, 2023
08609c2
refactor(utils): fix package.lock
BioPhoton Sep 6, 2023
b34defc
refactor(utils): format
BioPhoton Sep 6, 2023
1f7b685
test(utils): fix tests
BioPhoton Sep 6, 2023
0d1f0a0
refactor(utils): cleanup
BioPhoton Sep 6, 2023
ff7e114
feat(cli): rearrange files
BioPhoton Sep 7, 2023
c62b0af
Update packages/utils/src/lib/collect/implementation/execute-plugin.s…
BioPhoton Sep 7, 2023
2b87136
Update packages/utils/src/lib/collect/implementation/execute-plugin.ts
BioPhoton Sep 7, 2023
dfbb504
Update packages/utils/src/lib/collect/implementation/execute-plugin.ts
BioPhoton Sep 7, 2023
9acdc40
Update packages/utils/src/lib/collect/implementation/execute-plugin.ts
BioPhoton Sep 7, 2023
b5fb118
Update packages/utils/src/lib/collect/index.ts
BioPhoton Sep 7, 2023
61046d6
Update packages/utils/src/lib/collect/implementation/mock/execute-pro…
BioPhoton Sep 7, 2023
8e02d5a
Update packages/utils/src/lib/collect/implementation/mock/process-hel…
BioPhoton Sep 7, 2023
19a68b0
feat(cli): refactor types, adopt lib setup for build and test
BioPhoton Sep 7, 2023
7a2ca23
feat(utils): format
BioPhoton Sep 7, 2023
22bf8d2
feat(utils): lint fix
BioPhoton Sep 7, 2023
5d9ed9c
feat(utils): fix build
BioPhoton Sep 7, 2023
58a1860
Update packages/utils/src/lib/collect/implementation/execute-process.…
BioPhoton Sep 7, 2023
f6829cf
Apply suggestions from code review
BioPhoton Sep 7, 2023
ddc6dad
feat(utils): adopt test text
BioPhoton Sep 7, 2023
409883b
feat(utils): add package `utils` for cli independent logic (#39)
BioPhoton Sep 7, 2023
60d26b8
feat(cli): adopt typings
BioPhoton Sep 7, 2023
705e627
refactor(cli): adopt types, naming and tests
BioPhoton Sep 7, 2023
fdbdf4a
refactor(cli): adopt engine and types
BioPhoton Sep 7, 2023
1a9d323
Merge branch 'main' into setup-yargs-for-cli
BioPhoton Sep 7, 2023
3825c83
refactor(plugins): adopt output data to models
BioPhoton Sep 7, 2023
7308533
refactor(plugins): format
BioPhoton Sep 7, 2023
c20849b
test(cli-e2e): fix e2e tests for new plugins
BioPhoton Sep 7, 2023
653ed21
test(cli-e2e): format
BioPhoton Sep 7, 2023
03beb2f
Merge branch 'setup-yargs-for-cli' into initial-collect-command
BioPhoton Sep 7, 2023
d421094
feat(cli): add collect command
BioPhoton Sep 7, 2023
38055bb
feat(cli,utils): export code for plugin authors
BioPhoton Sep 8, 2023
e113d00
feat(cli,utils): format
BioPhoton Sep 8, 2023
d006e42
Apply suggestions from code review
BioPhoton Sep 8, 2023
7b2706b
feat(cli,models): fix typings
BioPhoton Sep 8, 2023
1652b3b
Merge branch 'setup-yargs-for-cli' into initial-collect-command
BioPhoton Sep 8, 2023
d895156
feat(cli,models): wip
BioPhoton Sep 8, 2023
b73927a
fix(cli): log middleware errors and flush before yargs exits process
matejchalk Sep 8, 2023
c15861c
fix(cli): fix report structure and tests
matejchalk Sep 8, 2023
57e7390
refactor(models): shared scorableSchema for category and auditGroup
matejchalk Sep 8, 2023
6b0ce6f
Merge branch 'main' into initial-collect-command
matejchalk Sep 8, 2023
3e0b63f
fix(cli): update package.json deps
matejchalk Sep 8, 2023
61efaca
style(cli): fix formatting
matejchalk Sep 8, 2023
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
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"chalk": "^5.3.0",
"yargs": "^17.7.2",
"zod": "^3.22.1",
"@quality-metrics/models": "^0.0.1"
"@quality-metrics/models": "^0.0.1",
"@quality-metrics/utils": "^0.0.1"
}
}
6 changes: 3 additions & 3 deletions packages/cli/src/lib/cli.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { join } from 'path';
import { describe, expect, it } from 'vitest';
import { yargsCli } from './cli';
import { join } from 'path';
import { yargsGlobalOptionsDefinition } from './options';
import { middlewares } from './middlewares';
import { CommandBase } from './implementation/base-command-config';
import { getDirname } from './implementation/utils';
import { middlewares } from './middlewares';
import { yargsGlobalOptionsDefinition } from './options';

const __dirname = getDirname(import.meta.url);
const withDirName = (path: string) => join(__dirname, path);
Expand Down
28 changes: 22 additions & 6 deletions packages/cli/src/lib/cli.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { CoreConfig } from '@quality-metrics/models';
import chalk from 'chalk';
import yargs, {
Argv,
CommandModule,
MiddlewareFunction,
Options,
ParserConfigurationOptions,
} from 'yargs';
import chalk from 'chalk';
import { CoreConfig } from '@quality-metrics/models';
import { logErrorBeforeThrow } from './implementation/utils';

/**
* returns configurable yargs CLI for code-pushup
Expand Down Expand Up @@ -40,6 +41,8 @@ export function yargsCli(

// setup yargs
cli
.help()
.alias('h', 'help')
.parserConfiguration({
'strip-dashed': true,
} satisfies Partial<ParserConfigurationOptions>)
Expand All @@ -57,12 +60,25 @@ export function yargsCli(
}

// add middlewares
middlewares.forEach(({ middlewareFunction, applyBeforeValidation }) =>
cli.middleware(middlewareFunction, applyBeforeValidation),
);
middlewares.forEach(({ middlewareFunction, applyBeforeValidation }) => {
cli.middleware(
logErrorBeforeThrow(middlewareFunction),
applyBeforeValidation,
);
});

// add commands
commands.forEach(commandObj => cli.command(commandObj));
commands.forEach(commandObj => {
cli.command({
...commandObj,
...(commandObj.handler && {
handler: logErrorBeforeThrow(commandObj.handler),
}),
...(typeof commandObj.builder === 'function' && {
builder: logErrorBeforeThrow(commandObj.builder),
}),
});
});

// return CLI object
return cli as unknown as Argv<CoreConfig>;
Expand Down
41 changes: 41 additions & 0 deletions packages/cli/src/lib/collect/_command-object-config.mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const { runnerOutputSchema } = require('@quality-metrics/models');
module.exports = {
persist: { outputPath: 'command-object-config-out.json' },
plugins: [
{
audits: [
{
slug: 'command-object-audit-slug',
title: 'audit title',
description: 'audit description',
label: 'mock audit label',
docsUrl: 'http://www.my-docs.dev',
},
],
runner: {
command: 'bash',
args: [
'-c',
`echo '${JSON.stringify(
runnerOutputSchema.parse({
audits: [
{
slug: 'command-object-audit-slug',
value: 0,
score: 0,
},
],
}),
)}' > command-object-config-out.json`,
],
outputPath: 'command-object-config-out.json',
},
groups: [],
meta: {
slug: 'command-object-plugin',
name: 'command-object plugin',
},
},
],
categories: [],
};
90 changes: 90 additions & 0 deletions packages/cli/src/lib/collect/command-object.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { CoreConfig, PluginConfig, Report } from '@quality-metrics/models';
import { CollectOptions } from '@quality-metrics/utils';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { yargsCli } from '../cli';
import { getDirname } from '../implementation/utils';
import { middlewares } from '../middlewares';
import { yargsGlobalOptionsDefinition } from '../options';
import { yargsCollectCommandObject } from './command-object';

const outputPath = 'collect-command-object.json';
const dummyConfig: CoreConfig = {
persist: { outputPath },
plugins: [mockPlugin()],
categories: [],
};

describe('collect-command-object', () => {
it('should parse arguments correctly', async () => {
const args = ['collect', '--verbose', '--configPath', ''];
const cli = yargsCli([], { options: yargsGlobalOptionsDefinition() })
.config(dummyConfig)
.command(yargsCollectCommandObject());
const parsedArgv = (await cli.parseAsync(
args,
)) as unknown as CollectOptions;
const { persist } = parsedArgv;
const { outputPath: outPath } = persist;
expect(outPath).toBe(outputPath);
return Promise.resolve(void 0);
});

it('should execute middleware correctly', async () => {
const args = [
'collect',
'--configPath',
join(
getDirname(import.meta.url),
'..',
'implementation',
'mock',
'config-middleware-config.mock.mjs',
),
];
await yargsCli([], { middlewares })
.config(dummyConfig)
.command(yargsCollectCommandObject())
.parseAsync(args);
const report = JSON.parse(readFileSync(outputPath).toString()) as Report;
expect(report.plugins[0]?.meta.slug).toBe('collect-command-object');
expect(report.plugins[0]?.audits[0]?.slug).toBe(
'command-object-audit-slug',
);
});
});

function mockPlugin(): PluginConfig {
return {
audits: [
{
slug: 'command-object-audit-slug',
title: 'audit title',
description: 'audit description',
label: 'mock audit label',
docsUrl: 'http://www.my-docs.dev',
},
],
runner: {
command: 'bash',
args: [
'-c',
`echo '${JSON.stringify({
audits: [
{
slug: 'command-object-audit-slug',
value: 0,
score: 0,
},
],
})}' > ${outputPath}`,
],
outputPath,
},
groups: [],
meta: {
slug: 'collect-command-object',
name: 'collect command object',
},
} satisfies PluginConfig;
}
18 changes: 18 additions & 0 deletions packages/cli/src/lib/collect/command-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { collect, CollectOptions } from '@quality-metrics/utils';
import { writeFile } from 'fs/promises';
import { CommandModule } from 'yargs';

export function yargsCollectCommandObject() {
const handler = async (args: CollectOptions): Promise<void> => {
const collectOutput = await collect(args);

const { persist } = args;
await writeFile(persist.outputPath, JSON.stringify(collectOutput, null, 2));
};

return {
command: 'collect',
describe: 'Run Plugins and collect results',
handler: handler as unknown as CommandModule['handler'],
} satisfies CommandModule;
}
3 changes: 2 additions & 1 deletion packages/cli/src/lib/commands.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandModule } from 'yargs';
import { yargsCollectCommandObject } from './collect/command-object';

export const commands: CommandModule[] = [];
export const commands: CommandModule[] = [yargsCollectCommandObject()];
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { join } from 'path';
import { configMiddleware, ConfigParseError } from './config-middleware';
import { expect } from 'vitest';
import { configMiddleware, ConfigParseError } from './config-middleware';
import { getDirname } from './utils';

const __dirname = getDirname(import.meta.url);
Expand Down
9 changes: 7 additions & 2 deletions packages/cli/src/lib/implementation/config-middleware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { existsSync } from 'node:fs';
import { bundleRequire } from 'bundle-require';
import { stat } from 'fs/promises';

import { GlobalCliArgs, globalCliArgsSchema } from '@quality-metrics/models';
import { CommandBase, commandBaseSchema } from './base-command-config';
Expand All @@ -15,7 +15,12 @@ export async function configMiddleware<T = unknown>(
): Promise<CommandBase> {
const globalCfg: GlobalCliArgs = globalCliArgsSchema.parse(processArgs);
const { configPath } = globalCfg;
if (!existsSync(configPath)) {
try {
const stats = await stat(configPath);
if (!stats.isFile) {
throw new ConfigParseError(configPath);
}
} catch (err) {
throw new ConfigParseError(configPath);
}

Expand Down
18 changes: 18 additions & 0 deletions packages/cli/src/lib/implementation/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,21 @@ import { fileURLToPath } from 'url';

export const getDirname = (import_meta_url: string) =>
dirname(fileURLToPath(import_meta_url));

// log error and flush stdout so that Yargs doesn't supress it
// related issue: https://github.com/yargs/yargs/issues/2118
export function logErrorBeforeThrow<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends (...args: any[]) => any,
>(fn: T): T {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (async (...args: any[]) => {
try {
return await fn(...args);
} catch (err) {
console.error(err);
await new Promise(resolve => process.stdout.write('', resolve));
throw err;
}
}) as T;
}
2 changes: 1 addition & 1 deletion packages/cli/src/lib/middlewares.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { configMiddleware } from './implementation/config-middleware';
import { MiddlewareFunction } from 'yargs';
import { configMiddleware } from './implementation/config-middleware';

export const middlewares: {
middlewareFunction: MiddlewareFunction;
Expand Down
27 changes: 17 additions & 10 deletions packages/models/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
export { CategoryConfig, categoryConfigSchema } from './lib/category-config';
export {
unrefinedCoreConfigSchema,
refineCoreConfig,
coreConfigSchema,
CoreConfig,
coreConfigSchema,
refineCoreConfig,
unrefinedCoreConfigSchema,
} from './lib/core-config';
export { uploadConfigSchema, UploadConfig } from './lib/upload-config';
export { GlobalCliArgs, globalCliArgsSchema } from './lib/global-cli-options';
export { PersistConfig, persistConfigSchema } from './lib/persist-config';
export {
pluginConfigSchema,
AuditGroup,
AuditMetadata,
Issue,
PluginConfig,
RunnerOutput,
auditGroupSchema,
auditMetadataSchema,
issueSchema,
pluginConfigSchema,
runnerOutputSchema,
} from './lib/plugin-config';
export {
runnerOutputAuditRefsPresentInPluginConfigs,
reportSchema,
PluginOutput,
PluginReport,
Report,
runnerOutputAuditRefsPresentInPluginConfigs,
} from './lib/report';
export { persistConfigSchema, PersistConfig } from './lib/persist-config';
export { categoryConfigSchema, CategoryConfig } from './lib/category-config';
export { globalCliArgsSchema, GlobalCliArgs } from './lib/global-cli-options';
export { UploadConfig, uploadConfigSchema } from './lib/upload-config';
Loading