Skip to content

Commit

Permalink
feat(config): adds logLevel
Browse files Browse the repository at this point in the history
- New configuration option: logLevel
- Possible values `verbose|warn|error`
  • Loading branch information
AriPerkkio committed Dec 4, 2020
1 parent 32c2b5c commit f538ff7
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 10 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ module.exports = {
/** Optional boolean flag used to set CI mode. process.env.CI is used when not set. */
CI: false,

/** Optional setting for log level. Valid values are verbose, warn, error. Defaults to verbose. */
logLevel: 'verbose',

/** Optional boolean flag used to enable caching of cloned repositories. For CIs it's ideal to disable caching. Defauls to true. */
cache: true,

Expand Down
3 changes: 3 additions & 0 deletions lib/config/config-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ export const CONFIGURATION_FILE_TEMPLATE =
/** Optional boolean flag used to set CI mode. process.env.CI is used when not set. */
CI: false,
/** Optional setting for log level. Valid values are verbose, warn, error. Defaults to verbose. */
logLevel: 'verbose',
/** Optional boolean flag used to enable caching of cloned repositories. For CIs it's ideal to disable caching. Defauls to true. */
cache: true,
Expand Down
2 changes: 2 additions & 0 deletions lib/config/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Linter } from 'eslint';
import { ResultTemplateOptions } from '@file-client/result-templates';

export type ResultParser = 'plaintext' | 'markdown';
export type LogLevel = 'verbose' | 'warn' | 'error';

/** Contents of the `eslint-remote-tester.config.js` */
export interface Config {
Expand All @@ -15,6 +16,7 @@ export interface Config {
concurrentTasks: number;
eslintrc: Linter.Config;
CI: boolean;
logLevel: LogLevel;
cache: boolean;
onComplete?: (results: ResultTemplateOptions[]) => Promise<void> | void;
}
16 changes: 15 additions & 1 deletion lib/config/validator.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import chalk from 'chalk';
import { ESLint } from 'eslint';

import { Config, ResultParser } from './types';
import { Config, ResultParser, LogLevel } from './types';

const RESULT_PARSERS: ResultParser[] = ['plaintext', 'markdown'];
const LOG_LEVELS: LogLevel[] = ['verbose', 'warn', 'error'];

const DEFAULT_RESULT_PARSER_CLI: ResultParser = 'markdown';
const DEFAULT_RESULT_PARSER_CI: ResultParser = 'plaintext';
const DEFAULT_LOG_LEVEL: LogLevel = 'verbose';
const DEFAULT_CONCURRENT_TASKS = 5;
const DEFAULT_MAX_FILE_SIZE_BYTES = 2000000;

Expand All @@ -24,6 +27,7 @@ export default function constructAndValidateConfiguration(
concurrentTasks,
eslintrc,
CI,
logLevel,
cache,
onComplete,
} = configToValidate;
Expand Down Expand Up @@ -76,6 +80,16 @@ export default function constructAndValidateConfiguration(
config.CI = CI == null ? process.env.CI === 'true' : CI;
}

if (logLevel && !LOG_LEVELS.includes(logLevel)) {
errors.push(
`logLevel (${logLevel}) is not valid value. Known values are ${LOG_LEVELS.join(
', '
)}`
);
} else if (!logLevel) {
config.logLevel = DEFAULT_LOG_LEVEL;
}

if (cache != null && typeof cache !== 'boolean') {
errors.push(`cache (${cache}) should be a boolean.`);
} else if (cache == null) {
Expand Down
55 changes: 48 additions & 7 deletions lib/progress-logger/progress-logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,57 @@ export function resolveColor(
return (taskOrMessage.color && chalk[taskOrMessage.color]) || DEFAULT_COLOR;
}

/**
* Check whether log is filtered out by `config.logLevel`
*/
function isLogVisible(log: LogMessage): boolean {
switch (config.logLevel) {
case 'verbose':
return true;

case 'warn':
return ['warn', 'error'].includes(log.level);

case 'error':
return log.level === 'error';

default:
return false;
}
}

/**
* Check whether task is filtered out by `config.logLevel`
* - Tasks are considered as "logs" on CI only. CLI mode displays only active ones.
*/
function isTasksVisible(): boolean {
return config.CI === false || config.logLevel === 'verbose';
}

/**
* Logger for holding state of current progress
* - Exposes different logs via `on` subscribe method
*/
class ProgressLogger {
/** Messages printed as a list under tasks */
messages: LogMessage[] = [];
private messages: LogMessage[] = [];

/** Messages of the task runners */
tasks: Task[] = [];
private tasks: Task[] = [];

/** Count of finished repositories */
scannedRepositories = 0;

/** Event listeners */
listeners: Listeners = {
private listeners: Listeners = {
exit: [],
message: [],
task: [],
ciKeepAlive: [],
};

/** Interval of CI status messages. Used to avoid CIs timeouting. */
ciKeepAliveIntervalHandle: NodeJS.Timeout | null = null;
private ciKeepAliveIntervalHandle: NodeJS.Timeout | null = null;

constructor() {
if (config.CI) {
Expand Down Expand Up @@ -85,7 +112,14 @@ class ProgressLogger {
*/
addNewMessage(message: LogMessage) {
this.messages.push(message);
this.listeners.message.forEach(listener => listener(message));

if (isLogVisible(message)) {
this.listeners.message.forEach(listener => listener(message));
}
}

getMessages(): LogMessage[] {
return this.messages.filter(message => isLogVisible(message));
}

/**
Expand Down Expand Up @@ -157,7 +191,9 @@ class ProgressLogger {
this.tasks.push(updatedTask);
}

this.listeners.task.forEach(listener => listener(updatedTask));
if (isTasksVisible()) {
this.listeners.task.forEach(listener => listener(updatedTask));
}
}

/**
Expand Down Expand Up @@ -222,7 +258,10 @@ class ProgressLogger {

if (task) {
this.tasks = this.tasks.filter(t => t !== task);
this.listeners.task.forEach(listener => listener(task, true));

if (isTasksVisible()) {
this.listeners.task.forEach(listener => listener(task, true));
}
}
}

Expand Down Expand Up @@ -355,13 +394,15 @@ class ProgressLogger {

/**
* Log status of scanning to CI
* - These are used to avoid CI timeouts
*/
onCiStatus() {
const message = Templates.CI_STATUS_TEMPLATE(
this.scannedRepositories,
this.tasks
);

// Note that these are never excluded from CI - no matter what `config.logLevel` value is
this.listeners.ciKeepAlive.forEach(listener => listener(message));
}
}
Expand Down
4 changes: 3 additions & 1 deletion lib/progress-logger/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ForegroundColor } from 'chalk';

import { LogLevel } from '@config/types';

export interface Task {
step?: 'START' | 'CLONE' | 'PULL' | 'READ' | 'LINT';
color?: typeof ForegroundColor;
Expand All @@ -12,7 +14,7 @@ export interface Task {
export interface LogMessage {
content: string;
color?: typeof ForegroundColor;
level: 'verbose' | 'warn' | 'error';
level: LogLevel;
}

// prettier-ignore
Expand Down
10 changes: 9 additions & 1 deletion lib/ui/components/FinalLog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ const START_MESSAGE: Omit<LogMessage, 'level'> = {
color: 'yellow',
};

const NO_ERRORS_MESSAGE: Omit<LogMessage, 'level'> = {
content: 'No errors',
color: 'green',
};

/**
* Final log of the scan
* - Displayed only on CLI mode after scan has completed
Expand All @@ -19,8 +24,11 @@ const START_MESSAGE: Omit<LogMessage, 'level'> = {
export default function FinalLog(): JSX.Element {
useExitAfterRender();

const logMessages = ProgressLogger.getMessages();
const messages = logMessages.length > 0 ? logMessages : [NO_ERRORS_MESSAGE];

return (
<Static items={[START_MESSAGE, ...ProgressLogger.messages]}>
<Static items={[START_MESSAGE, ...messages]}>
{({ color, content }, index) => (
<Text key={index} color={color}>
{content}
Expand Down
1 change: 1 addition & 0 deletions test/validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const DEFAULT_CONFIGURATION: Config = {
eslintrc: {},
CI: undefined as any,
cache: undefined as any,
logLevel: undefined as any,
};

describe('Config validator', () => {
Expand Down

0 comments on commit f538ff7

Please sign in to comment.