From 814f6f04c4129aea8841a0c5ba448550e5629823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Thu, 6 May 2021 15:56:29 +0300 Subject: [PATCH] feat: pass count of scanned repositories to `config.onComplete` (#102) --- README.md | 34 +++++++++++++------------- docs/onComplete-arguments.json | 3 ++- lib/config/types.ts | 3 ++- lib/progress-logger/exit-handler.ts | 7 ++++-- lib/progress-logger/progress-logger.ts | 6 ++--- test/integration/integration.test.ts | 9 ++++++- 6 files changed, 37 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index e43e2ab3..b02fd9e5 100644 --- a/README.md +++ b/README.md @@ -75,23 +75,23 @@ module.exports = { #### Configuration options -| Name | Description                               | Type | Required | Default | Example | -| :-------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | :----------------- | :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | -| `repositories` | Repositories to scan in format of `owner/project`. See [eslint-remote-tester-repositories] for shared list of repositories. | `string[]` | :white_check_mark: | :x: | `['mui-org/material-ui', 'reach/reach-ui']` | -| `extensions` | Extensions of files under scanning | `string[]` | :white_check_mark: | :x: | `['js', 'jsx', 'ts', 'tsx']` | -| `eslintrc` | ESLint configuration | See [Configuring ESLint] | :white_check_mark: | :x: | `{ root: true, extends: ['eslint:all'] }` | -| `pathIgnorePattern` | Regexp pattern string used to exclude paths | `string` | :x: | :x: | `(node_modules\|docs\|\\/\\.git)` | -| `maxFileSizeBytes` | Max file size used to exclude bigger files | `number` | :x: | `2000000` | `1500000` | -| `rulesUnderTesting` | Array of rules or a filter method used to filter out results. Use `undefined` or empty array when ESLint crashes are the only interest. Filter method is called with `ruleId` and `options`. | `string[] \| (ruleId, { repository }) => boolean` | :x: | `[]` | `['no-empty', 'react/sort-prop-types']` `(ruleId, options) => ruleId === 'no-undef' && options.repository === 'owner/repo'` | -| `resultParser` | Syntax for the result parser | `plaintext\|markdown` | :x: | `markdown` on CLI. `plaintext` on CI | `markdown` | -| `concurrentTasks` | Maximum amount of tasks run concurrently | `number` | :x: | `5` | `3` | -| `CI` | Flag used to set CI mode. `process.env.CI` is used when not set. | `boolean` | :x: | value of `process.env.CI === 'true'` | `true` | -| `logLevel` | Filter log messages based on their priority | `verbose\|info\|warn\|error` | :x: | `verbose` | `warn` | -| `cache` | Flag used to enable caching of cloned repositories. For CIs it's ideal to disable caching due to limited disk space. | `boolean` | :x: | `true` | `true` | -| `timeLimit` | Time limit before scan is interrupted and **exited successfully**. Ideal for avoiding CI timeouts in regression tests. | `number` | :x: | `5.5 * 60 * 60, // 5 hours 30 minutes` | `5 * 60 * 60 // 5 hours` | -| `compare` | Flag used to enable result comparison mode. Compares results of two scans and output the diff. Ideal for identifying new false positives when fixing existing rules. See [Fixing existing rules]. | `boolean` | :x: | `false` | `true` | -| `updateComparisonReference` | Flag used to enable result comparison reference updating. Indicates whether comparison base should be updated after scan has finished. Ideal to be turned off once initial comparison base has been collected. | `boolean` | :x: | `true` | `true` | -| `onComplete` | Callback invoked once scan is completed. Asynchronous functions are supported. Ideal for extending the process with custom features. | `(results, comparisonResults) => void`\|`Promise`. See [onComplete example]. | :x: | :x: | `async (results, comparisonResults) => {}` | +| Name | Description                               | Type | Required | Default | Example | +| :-------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------- | :----------------- | :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | +| `repositories` | Repositories to scan in format of `owner/project`. See [eslint-remote-tester-repositories] for shared list of repositories. | `string[]` | :white_check_mark: | :x: | `['mui-org/material-ui', 'reach/reach-ui']` | +| `extensions` | Extensions of files under scanning | `string[]` | :white_check_mark: | :x: | `['js', 'jsx', 'ts', 'tsx']` | +| `eslintrc` | ESLint configuration | See [Configuring ESLint] | :white_check_mark: | :x: | `{ root: true, extends: ['eslint:all'] }` | +| `pathIgnorePattern` | Regexp pattern string used to exclude paths | `string` | :x: | :x: | `(node_modules\|docs\|\\/\\.git)` | +| `maxFileSizeBytes` | Max file size used to exclude bigger files | `number` | :x: | `2000000` | `1500000` | +| `rulesUnderTesting` | Array of rules or a filter method used to filter out results. Use `undefined` or empty array when ESLint crashes are the only interest. Filter method is called with `ruleId` and `options`. | `string[] \| (ruleId, { repository }) => boolean` | :x: | `[]` | `['no-empty', 'react/sort-prop-types']` `(ruleId, options) => ruleId === 'no-undef' && options.repository === 'owner/repo'` | +| `resultParser` | Syntax for the result parser | `plaintext\|markdown` | :x: | `markdown` on CLI. `plaintext` on CI | `markdown` | +| `concurrentTasks` | Maximum amount of tasks run concurrently | `number` | :x: | `5` | `3` | +| `CI` | Flag used to set CI mode. `process.env.CI` is used when not set. | `boolean` | :x: | value of `process.env.CI === 'true'` | `true` | +| `logLevel` | Filter log messages based on their priority | `verbose\|info\|warn\|error` | :x: | `verbose` | `warn` | +| `cache` | Flag used to enable caching of cloned repositories. For CIs it's ideal to disable caching due to limited disk space. | `boolean` | :x: | `true` | `true` | +| `timeLimit` | Time limit before scan is interrupted and **exited successfully**. Ideal for avoiding CI timeouts in regression tests. | `number` | :x: | `5.5 * 60 * 60, // 5 hours 30 minutes` | `5 * 60 * 60 // 5 hours` | +| `compare` | Flag used to enable result comparison mode. Compares results of two scans and output the diff. Ideal for identifying new false positives when fixing existing rules. See [Fixing existing rules]. | `boolean` | :x: | `false` | `true` | +| `updateComparisonReference` | Flag used to enable result comparison reference updating. Indicates whether comparison base should be updated after scan has finished. Ideal to be turned off once initial comparison base has been collected. | `boolean` | :x: | `true` | `true` | +| `onComplete` | Callback invoked once scan is completed. Asynchronous functions are supported. Ideal for extending the process with custom features. | `(results, comparisonResults, repositoryCount) => void`\|`Promise`. See [onComplete example]. | :x: | :x: | `async (results, comparisonResults, repositoryCount) => {}` | [configuring eslint]: https://eslint.org/docs/user-guide/configuring [fixing existing rules]: #fixing-existing-rules diff --git a/docs/onComplete-arguments.json b/docs/onComplete-arguments.json index d473b034..dc7991f6 100644 --- a/docs/onComplete-arguments.json +++ b/docs/onComplete-arguments.json @@ -76,5 +76,6 @@ "source": " 5 | \n 6 | new Vue({\n> 7 | render: h => h(App),\n | ^\n 8 | }).$mount('#app')\n 9 | " } ] - } + }, + "repositoryCount": 123 } diff --git a/lib/config/types.ts b/lib/config/types.ts index f141e380..a59858d9 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -32,7 +32,8 @@ export interface Config { updateComparisonReference: boolean; onComplete?: ( results: Result[], - comparisonResults: ComparisonResults | null + comparisonResults: ComparisonResults | null, + repositoryCount: number ) => Promise | void; } diff --git a/lib/progress-logger/exit-handler.ts b/lib/progress-logger/exit-handler.ts index 8c74ff37..8c65766e 100644 --- a/lib/progress-logger/exit-handler.ts +++ b/lib/progress-logger/exit-handler.ts @@ -11,7 +11,9 @@ import { LogMessage } from './types'; /** * Callback invoked once scan is complete and application is about to exit */ -export default async function onExit(): Promise { +export default async function onExit( + scannedRepositories: number +): Promise { const messages: LogMessage[] = []; const errors = []; @@ -43,7 +45,8 @@ export default async function onExit(): Promise { try { const onCompletePromise = config.onComplete( results, - comparisonResults + comparisonResults, + scannedRepositories ); if (onCompletePromise instanceof Promise) { diff --git a/lib/progress-logger/progress-logger.ts b/lib/progress-logger/progress-logger.ts index b92674fd..7579ddd5 100644 --- a/lib/progress-logger/progress-logger.ts +++ b/lib/progress-logger/progress-logger.ts @@ -167,14 +167,14 @@ class ProgressLogger { const notifyListeners = () => this.listeners.exit.forEach(listener => listener()); - // Erroneous exit handler should not crash whole application. - // Log the error and move on. - exitHandler() + exitHandler(this.scannedRepositories) .then(messages => { messages.forEach(message => this.addNewMessage(message)); notifyListeners(); }) .catch(error => { + // Erroneous exit handler should not crash whole application. + // Log the error and move on. console.error(error); notifyListeners(); }); diff --git a/test/integration/integration.test.ts b/test/integration/integration.test.ts index 3734e4c1..2b0f1d10 100644 --- a/test/integration/integration.test.ts +++ b/test/integration/integration.test.ts @@ -308,9 +308,13 @@ describe('integration', () => { test('calls onComplete hook with the results', async () => { const { output } = await runProductionBuild({ CI: true, - onComplete: function onComplete(results) { + onComplete: function onComplete(results, _, repositoryCount) { console.log('[TEST-ON-COMPLETE-START]'); + console.log('[REPOSITORY-COUNT-START]'); + console.log(repositoryCount); + console.log('[REPOSITORY-COUNT-END]'); + results.forEach(result => { Object.entries(result).forEach(([key, value]) => { if (key === '__internalHash') return; @@ -335,6 +339,9 @@ describe('integration', () => { expect(onCompleteCall).toMatchInlineSnapshot(` "[TEST-ON-COMPLETE-START] + [REPOSITORY-COUNT-START] + 1 + [REPOSITORY-COUNT-END] . [REPOSITORY] eslint-remote-tester-integration-test-target