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

introduce CLI aliases #697

Merged
merged 10 commits into from
May 8, 2024
2 changes: 1 addition & 1 deletion src/__tests__/unit/config/strings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('config/strings: ', () => {
it('successfully injects path into message.', () => {
const path = 'mock/path';
const expectedMessage = `
[!important] You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`;
You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`;

expect(NOT_NATIVE_PLUGIN(path)).toEqual(expectedMessage);
});
Expand Down
17 changes: 1 addition & 16 deletions src/__tests__/unit/util/args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,12 @@ import path = require('path');
import {parseArgs} from '../../../util/args';
import {ERRORS} from '../../../util/errors';

import {STRINGS, CONFIG} from '../../../config';
const {impact} = CONFIG;
const {HELP} = impact;
import {STRINGS} from '../../../config';

const {CliInputError} = ERRORS;

const {MANIFEST_IS_MISSING, FILE_IS_NOT_YAML} = STRINGS;

const info = jest.spyOn(console, 'info').mockImplementation(() => {});

describe('util/args: ', () => {
const originalEnv = process.env;

Expand Down Expand Up @@ -143,17 +139,6 @@ describe('util/args: ', () => {
expect(result).toEqual(expectedResult);
});

it('returns manifest with help.', () => {
expect.assertions(2);

process.env.result = 'help';

const result = parseArgs();

expect(info).toHaveBeenCalledWith(HELP);
expect(result).toBeUndefined();
});

it('returns manifest and output path.', () => {
expect.assertions(1);

Expand Down
65 changes: 24 additions & 41 deletions src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,71 +1,54 @@
import {ArgumentConfig} from 'ts-command-line-args';
import {ArgumentConfig, ParseOptions} from 'ts-command-line-args';

import {STRINGS} from './strings';

import {ManifestProcessArgs} from '../types/process-args';

const {DISCLAIMER_MESSAGE} = STRINGS;

export const CONFIG = {
impact: {
IE: {
ARGS: {
manifest: {
type: String,
optional: true,
alias: 'i',
description: 'Path to an input manifest file.',
alias: 'm',
description: '[path to the input file]',
},
output: {
type: String,
optional: true,
description:
'Path to the output file where the results as saved, if none is provided it prints to stdout.',
alias: 'o',
description: '[path to the output file]',
},
'override-params': {
type: String,
optional: true,
description: 'Path to a parameter file that overrides our defaults.',
},
format: {
type: String,
optional: true,
description:
'The output file format. default to yaml but if csv is specified then it formats the outputs as a csv file for loading into another program.',
defaultValue: 'yaml',
},
verbose: {
type: Boolean,
optional: true,
description:
'How much information to output about the calculation to aid investigation and debugging.',
alias: 'p',
description: '[path to a parameter file that overrides our defaults]',
},
stdout: {
type: Boolean,
optional: true,
description: 'Prints output to the console.',
alias: 's',
description: '[prints out to the console]',
},
help: {
type: Boolean,
optional: true,
alias: 'h',
description: 'Prints this usage guide.',
description: '[prints out the above help instruction]',
},
} as ArgumentConfig<ManifestProcessArgs>,
HELP: `impact
-manifest [path to the input file]
-output [path to the output file]
-format [yaml|csv]
-verbose
--stdout
-help
manifest: path to an input manifest
output: path to the output file where the results as saved, if none is provided it prints to stdout.
format: the output file format. default to yaml but if csv is specified then it formats the outputs as a csv file for loading into another program.
verbose: how much information to output about the calculation to aid investigation and debugging.
help: prints out the above help instruction.
stdout: Prints output to the console.
`,
NO_OUTPUT: `
You have not selected an output method. To see your output data, you can choose from:
--stdout: this will print your output data to the console
--output <savepath>: this will save your output data to the given filepath (do not provide file extension)
Note that for the '--output' option you also need to define the output type in your manifest file. See https://if.greensoftware.foundation/major-concepts/manifest-file#initialize`,
HELP: {
helpArg: 'help',
headerContentSections: [
{header: 'Impact Framework', content: 'Helpful keywords:'},
],
footerContentSections: [
{header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE},
],
} as ParseOptions<any>,
},
GITHUB_PATH: 'https://github.com',
NATIVE_PLUGIN: 'if-plugins',
Expand Down
9 changes: 7 additions & 2 deletions src/config/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ export const STRINGS = {
OVERRIDE_WARNING:
'\n**WARNING**: You are overriding the IF default parameters file. Please be extremely careful of unintended side-effects in your plugin pipeline!\n',
DISCLAIMER_MESSAGE: `
[!important] Incubation Project
Incubation Project

This project is an incubation project being run inside the Green Software Foundation; as such, we DON’T recommend using it in any critical use case.
Incubation projects are experimental, offer no support guarantee, have minimal governance and process, and may be retired at any moment. This project may one day graduate, in which case this disclaimer will be removed.`,
NOT_NATIVE_PLUGIN: (path: string) =>
`
[!important] You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`,
You are using plugin ${path} which is not part of the Impact Framework standard library. You should do your own research to ensure the plugins are up to date and accurate. They may not be actively maintained.`,
SOMETHING_WRONG: 'Something wrong with cli arguments. Please check docs.',
ISSUE_TEMPLATE: `
Impact Framework is an alpha release from the Green Software Foundation and is released to capture early feedback. If you'd like to offer some feedback, please use this issue template:
Expand Down Expand Up @@ -47,4 +47,9 @@ https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=fee
`Unknown parameter: ${name}. Using 'sum' aggregation method.`,
NOT_INITALIZED_PLUGIN: (name: string) =>
`Not initalized plugin: ${name}. Check if ${name} is in 'manifest.initalize.plugins'.`,
NO_OUTPUT: `
You have not selected an output method. To see your output data, you can choose from:
--stdout: this will print your output data to the console
--output <savepath>: this will save your output data to the given filepath (do not provide file extension)
Note that for the '--output' option you also need to define the output type in your manifest file. See https://if.greensoftware.foundation/major-concepts/manifest-file#initialize`,
};
8 changes: 1 addition & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,16 @@ const {DISCLAIMER_MESSAGE} = STRINGS;
const impactEngine = async () => {
const options = parseArgs();

if (!options) {
return;
}

logger.info(DISCLAIMER_MESSAGE);
const {inputPath, paramPath, outputOptions} = options;

const {tree, rawContext, parameters} = await load(inputPath!, paramPath);
const {tree, rawContext, parameters} = await load(inputPath, paramPath);
const context = await injectEnvironment(rawContext);
parameterize.combine(context.params, parameters);
const pluginStorage = await initalize(context.initialize.plugins);
const computedTree = await compute(tree, {context, pluginStorage});
const aggregatedTree = aggregate(computedTree, context.aggregation);
exhaust(aggregatedTree, context, outputOptions);

return;
};

impactEngine().catch(andHandle);
3 changes: 1 addition & 2 deletions src/types/process-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ export interface ManifestProcessArgs {
manifest?: string;
output?: string;
'override-params'?: string;
help?: boolean;
stdout?: boolean;
}

Expand All @@ -12,7 +11,7 @@ export interface Options {
}

export interface ProcessArgsOutputs {
inputPath?: string;
inputPath: string;
outputOptions: {
outputPath?: string;
stdout?: boolean;
Expand Down
16 changes: 5 additions & 11 deletions src/util/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ import {ManifestProcessArgs, ProcessArgsOutputs} from '../types/process-args';

const {CliInputError} = ERRORS;

const {impact} = CONFIG;
const {ARGS, HELP, NO_OUTPUT} = impact;
const {IE} = CONFIG;
const {ARGS, HELP} = IE;

const {FILE_IS_NOT_YAML, MANIFEST_IS_MISSING} = STRINGS;
const {FILE_IS_NOT_YAML, MANIFEST_IS_MISSING, NO_OUTPUT} = STRINGS;

/**
* Validates process arguments
*/
const validateAndParseProcessArgs = () => {
try {
return parse<ManifestProcessArgs>(ARGS);
return parse<ManifestProcessArgs>(ARGS, HELP);
} catch (error) {
if (error instanceof Error) {
throw new CliInputError(error.message);
Expand Down Expand Up @@ -52,20 +52,14 @@ const prependFullFilePath = (filePath: string) => {
* If it is, then returns object containing full path.
* 4. If params are missing or invalid, then rejects with `CliInputError`.
*/
export const parseArgs = (): ProcessArgsOutputs | undefined => {
export const parseArgs = (): ProcessArgsOutputs => {
const {
manifest,
output,
'override-params': overrideParams,
help,
stdout,
} = validateAndParseProcessArgs();

if (help) {
console.info(HELP);
return;
}

if (!output && !stdout) {
logger.warn(NO_OUTPUT);
}
Expand Down