Skip to content

Commit

Permalink
fix: remove --no-fail flag, add --continue flag
Browse files Browse the repository at this point in the history
  • Loading branch information
vCaisim committed Oct 4, 2024
1 parent 7673d5a commit a84b773
Show file tree
Hide file tree
Showing 13 changed files with 414 additions and 109 deletions.
83 changes: 34 additions & 49 deletions packages/cmd/src/commands/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CommanderError } from '@commander-js/extra-typings';
import { error, warnWithNoTrace } from '@logger';
import { describe, expect, it, vi, beforeEach } from 'vitest';
import { error } from '@logger';
import { beforeEach, describe, expect, it, MockInstance, vi } from 'vitest';
import { enableDebug } from '../../debug';
import { commandHandler, parseCommaSeparatedList } from '../utils';

Expand Down Expand Up @@ -41,70 +41,55 @@ describe('parseCommaSeparatedList', () => {
});

describe('commandHandler', () => {
const mockAction = vi.fn();
let mockExit = vi.spyOn(process, 'exit').mockImplementation((code) => {
throw new Error(`process.exit(${code})`);
});
let exitSpy: MockInstance<never, [code?: string | number | null | undefined]>;

beforeEach(() => {
vi.clearAllMocks();
// @ts-ignore
exitSpy = vi.spyOn(process, 'exit').mockImplementation((code) => {
return code as never;
});
});

it('should call the action and exit with code 0 on success', async () => {
mockAction.mockResolvedValueOnce(undefined);
// @ts-ignore
mockExit = vi.spyOn(process, 'exit').mockImplementationOnce(() => void 0);
it('should call action with the given options and exit with code 0 on success', async () => {
const mockAction = vi.fn().mockResolvedValue(undefined);
const mockOptions = { debug: false };

await commandHandler(mockAction, { debug: false });
expect(mockAction).toHaveBeenCalled();
expect(mockExit).toHaveBeenCalledWith(0);
await commandHandler(mockAction, mockOptions);
expect(mockAction).toHaveBeenCalledWith(mockOptions);
expect(exitSpy).toHaveBeenCalledWith(0);
});

it('should enable debug mode if debug is true', async () => {
mockAction.mockResolvedValueOnce(undefined);
// @ts-ignore
mockExit = vi.spyOn(process, 'exit').mockImplementationOnce(() => void 0);
it('should enable debug mode if debug option is true', async () => {
const mockAction = vi.fn().mockResolvedValue(undefined);
const mockOptions = { debug: true };

await commandHandler(mockAction, { debug: true });
await commandHandler(mockAction, mockOptions);
expect(enableDebug).toHaveBeenCalled();
expect(mockAction).toHaveBeenCalled();
expect(mockExit).toHaveBeenCalledWith(0);
expect(mockAction).toHaveBeenCalledWith(mockOptions);
expect(exitSpy).toHaveBeenCalledWith(0);
});

it('should log error and exit with code 1 if an error occurs and failOnError is true', async () => {
const errorMessage = 'Test error';
mockAction.mockRejectedValueOnce(new Error(errorMessage));
it('should log an error and exit with code 1 if action throws a generic error', async () => {
const mockAction = vi.fn().mockRejectedValue(new Error('Test Error'));
const mockOptions = { debug: false };

await expect(commandHandler(mockAction, { debug: false })).rejects.toThrow(
'process.exit(1)'
);
expect(error).toHaveBeenCalledWith(errorMessage);
expect(mockExit).toHaveBeenCalledWith(1);
await commandHandler(mockAction, mockOptions);
expect(error).toHaveBeenCalledWith('Test Error');
expect(exitSpy).toHaveBeenCalledWith(1);
});

it('should log error and exit with specific exitCode if CommanderError occurs', async () => {
const commandError = new CommanderError(
123,
it('should exit with CommanderError exitCode if action throws a CommanderError', async () => {
const commanderError = new CommanderError(
2,
'commander.error',
'Commander failed'
'Commander Error'
);
mockAction.mockRejectedValueOnce(commandError);

await expect(commandHandler(mockAction, { debug: false })).rejects.toThrow(
'process.exit(123)'
);
expect(error).toHaveBeenCalledWith('Commander failed');
expect(mockExit).toHaveBeenCalledWith(123);
});

it('should log a warning and exit with code 0 if failOnError is false', async () => {
const errorMessage = 'Test warning';
mockAction.mockRejectedValueOnce(new Error(errorMessage));
const mockAction = vi.fn().mockRejectedValue(commanderError);
const mockOptions = { debug: false };

await expect(
commandHandler(mockAction, { debug: false }, { failOnError: false })
).rejects.toThrow('process.exit(0)');
expect(warnWithNoTrace).toHaveBeenCalledWith(errorMessage);
expect(mockExit).toHaveBeenCalledWith(0);
await commandHandler(mockAction, mockOptions);
expect(error).toHaveBeenCalledWith('Commander Error');
expect(exitSpy).toHaveBeenCalledWith(2);
});
});
24 changes: 9 additions & 15 deletions packages/cmd/src/commands/cache/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,15 @@ export type CacheGetCommandOpts = ReturnType<
>;

export async function getCacheGetHandler(options: CacheGetCommandOpts) {
await commandHandler(
async (opts) => {
setCacheGetCommandConfig(cacheGetCommandOptsToConfig(opts));
const config = getCacheCommandConfig();
await commandHandler(async (opts) => {
setCacheGetCommandConfig(cacheGetCommandOptsToConfig(opts));
const config = getCacheCommandConfig();

debug('Config: %o', {
...config.values,
recordKey: config.values?.recordKey ? '*****' : undefined,
});
debug('Config: %o', {
...config.values,
recordKey: config.values?.recordKey ? '*****' : undefined,
});

await handleGetCache();
},
options,
{
failOnError: options.fail,
}
);
await handleGetCache();
}, options);
}
5 changes: 2 additions & 3 deletions packages/cmd/src/commands/cache/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { dim } from '@logger';
import chalk from 'chalk';
import { getCacheGetHandler } from './get';
import {
continueOption,
debugOption,
idOption,
matrixIndexOption,
matrixTotalOption,
noFailOption,
outputDirOption,
pathOption,
presetOption,
Expand Down Expand Up @@ -63,7 +63,6 @@ export const getCacheSetCommand = () => {
.addOption(pwOutputDirOption)
.addOption(matrixIndexOption)
.addOption(matrixTotalOption)
.addOption(noFailOption)
.action(getCacheSetHandler);

return command;
Expand All @@ -81,7 +80,7 @@ export const getCacheGetCommand = () => {
.addOption(debugOption)
.addOption(matrixIndexOption)
.addOption(matrixTotalOption)
.addOption(noFailOption)
.addOption(continueOption)
.action(getCacheGetHandler);

return command;
Expand Down
8 changes: 4 additions & 4 deletions packages/cmd/src/commands/cache/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function validatePositiveInteger(value: string) {
return parsedValue;
}

export const noFailOption = new Option(
'--no-fail',
'Do not fail the process if the command fails'
);
export const continueOption = new Option(
'--continue',
'Continue the script execution if the cache is not found'
).default(false);
24 changes: 9 additions & 15 deletions packages/cmd/src/commands/cache/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,15 @@ export type CacheSetCommandOpts = ReturnType<
>;

export async function getCacheSetHandler(options: CacheSetCommandOpts) {
await commandHandler(
async (opts) => {
setCacheSetCommandConfig(cacheSetCommandOptsToConfig(opts));
const config = getCacheCommandConfig();
await commandHandler(async (opts) => {
setCacheSetCommandConfig(cacheSetCommandOptsToConfig(opts));
const config = getCacheCommandConfig();

debug('Config: %o', {
...config.values,
recordKey: config.values?.recordKey ? '*****' : undefined,
});
debug('Config: %o', {
...config.values,
recordKey: config.values?.recordKey ? '*****' : undefined,
});

await handleSetCache();
},
options,
{
failOnError: options.fail,
}
);
await handleSetCache();
}, options);
}
20 changes: 5 additions & 15 deletions packages/cmd/src/commands/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommanderError } from '@commander-js/extra-typings';
import { error, warnWithNoTrace } from '@logger';
import { error } from '@logger';
import { enableDebug } from '../debug';

export function parseCommaSeparatedList(
Expand All @@ -14,27 +14,17 @@ export function parseCommaSeparatedList(

export async function commandHandler<T extends Record<string, unknown>>(
action: (options: T) => Promise<void>,
commandOptions: T,
options?: {
failOnError?: boolean;
}
commandOptions: T
) {
try {
if (commandOptions.debug) {
enableDebug();
}
await action(commandOptions);
process.exit(0);
} catch (_e) {
const e = _e as Error;
const failOnError = options?.failOnError ?? true;
if (failOnError) {
error(e.message);
} else {
warnWithNoTrace(e.message);
}

} catch (e) {
error((e as Error).message);
const exitCode = e instanceof CommanderError ? e.exitCode : 1;
process.exit(failOnError ? exitCode : 0);
process.exit(exitCode);
}
}
1 change: 1 addition & 0 deletions packages/cmd/src/config/cache/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type CacheSetCommandConfig = CacheCommandConfig &

export type CacheGetCommandConfig = CacheCommandConfig &
CommonConfig & {
continue?: boolean;
outputDir?: string;
presetOutput?: string;
};
Expand Down
4 changes: 4 additions & 0 deletions packages/cmd/src/config/cache/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ const cacheGetCommandConfigKeys = {
name: 'Matrix total',
cli: '--matrix-total',
},
continue: {
name: 'Continue on cache miss',
cli: '--continue',
},
} as const;

export const configKeys = {
Expand Down
1 change: 1 addition & 0 deletions packages/cmd/src/config/cache/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export function cacheGetCommandOptsToConfig(
debug: options.debug,
matrixIndex: options.matrixIndex,
matrixTotal: options.matrixTotal,
continue: options.continue,
};
}

Expand Down
Loading

0 comments on commit a84b773

Please sign in to comment.