diff --git a/config/generation.config.js b/config/generation.config.js index a8e8add1a98..bb1cd66f143 100644 --- a/config/generation.config.js +++ b/config/generation.config.js @@ -5,27 +5,20 @@ module.exports = { 'specs/bundled/*.yml', 'clients/**', - 'clients/**/.*', // hidden files are not ignored by default '!clients/README.md', '!clients/**/.openapi-generator-ignore', // Java - '!clients/algoliasearch-client-java-2/*.gradle', - '!clients/algoliasearch-client-java-2/gradlew', - '!clients/algoliasearch-client-java-2/.gitignore', - '!clients/algoliasearch-client-java-2/gradle/wrapper/**', - '!clients/algoliasearch-client-java-2/algoliasearch-core/build.gradle', - '!clients/algoliasearch-client-java-2/algoliasearch-core/gradle.properties', - '!clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/exceptions/**', - '!clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/utils/**', + '!clients/algoliasearch-client-java-2/**', + 'clients/algoliasearch-client-java-2/gradle.properties', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/ApiClient.java', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/api/**', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/model/**', 'tests/output/java/build.gradle', - 'tests/output/java/src/test/java/com/algolia/methods/**', // this could be added automatically by the script, but with overhead - 'tests/output/java/src/test/java/com/algolia/client/**', // JavaScript '!clients/algoliasearch-client-javascript/*', - '!clients/algoliasearch-client-javascript/.*', '!clients/algoliasearch-client-javascript/.github/**', '!clients/algoliasearch-client-javascript/.yarn/**', '!clients/algoliasearch-client-javascript/scripts/**', @@ -34,12 +27,9 @@ module.exports = { '!clients/algoliasearch-client-javascript/packages/client-common/**', 'tests/output/javascript/package.json', - 'tests/output/javascript/src/methods/**', - 'tests/output/javascript/src/client/**', // PHP '!clients/algoliasearch-client-php/*', - '!clients/algoliasearch-client-php/.*', '!clients/algoliasearch-client-php/lib/*', '!clients/algoliasearch-client-php/lib/Cache/**', '!clients/algoliasearch-client-php/lib/Exceptions/**', @@ -50,8 +40,5 @@ module.exports = { '!clients/algoliasearch-client-php/lib/Support/**', '!clients/algoliasearch-client-php/lib/Configuration/**', 'clients/algoliasearch-client-php/lib/Configuration/Configuration.php', - - 'tests/output/php/src/methods/**', - 'tests/output/php/src/client/**', ], }; diff --git a/scripts/ci/husky/__tests__/pre-commit.test.js b/scripts/ci/husky/__tests__/pre-commit.test.js index bad3774922d..c547069a23f 100644 --- a/scripts/ci/husky/__tests__/pre-commit.test.js +++ b/scripts/ci/husky/__tests__/pre-commit.test.js @@ -1,24 +1,63 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable import/no-commonjs */ -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { createMemoizedMicromatchMatcher } = require('../pre-commit'); +const micromatch = require('micromatch'); -describe('createMemoizedMicromatchMatcher', () => { +const { getPatterns } = require('../pre-commit'); + +describe('micromatch', () => { it('matches correctly', () => { - const matcher = createMemoizedMicromatchMatcher([ - 'clients/**', - '!clients/README.md', - ]); + expect( + micromatch + .match( + [ + 'clients/algoliasearch-client-java-2/build.gradle', + 'clients/algoliasearch-client-java-2/.gitignore', + 'clients/algoliasearch-client-java-2/gradle.properties', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/api/SearchClient.java', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/model/search/Test.java', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/utils/AlgoliaAgent.java', - expect(matcher('clients/README.md')).toEqual(false); - expect(matcher('clients/CONTRIBUTING.md')).toEqual(true); - }); + 'clients/algoliasearch-client-javascript/.prettierrc', + 'clients/algoliasearch-client-javascript/lerna.json', + 'clients/algoliasearch-client-javascript/packages/client-common/whatever.test', + 'clients/algoliasearch-client-javascript/packages/client-search/ignore.txt', + + 'clients/algoliasearch-client-php/.gitignore', + 'clients/algoliasearch-client-php/lib/Api/SearchClient.php', + 'clients/algoliasearch-client-php/lib/Cache/FileCacheDriver.php', + + 'tests/output/java/build.gradle', + 'tests/output/java/settings.gradle', + 'tests/output/java/src/test/java/com/algolia/EchoResponse.java', + 'tests/output/java/src/test/java/com/algolia/client/test.java', + + 'tests/output/javascript/jest.config.ts', + 'tests/output/javascript/package.json', + 'tests/output/javascript/src/client/test.ts', + + 'tests/output/php/src/methods/requests/test.php', + ], + getPatterns() + ) + .sort() + ).toEqual( + [ + 'clients/algoliasearch-client-java-2/gradle.properties', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/api/SearchClient.java', + 'clients/algoliasearch-client-java-2/algoliasearch-core/src/main/java/com/algolia/model/search/Test.java', + + 'clients/algoliasearch-client-javascript/packages/client-search/ignore.txt', + + 'clients/algoliasearch-client-php/lib/Api/SearchClient.php', + + 'tests/output/java/build.gradle', + 'tests/output/java/src/test/java/com/algolia/client/test.java', - it('prioritizes the exact match when two patterns conflict', () => { - const matcher = createMemoizedMicromatchMatcher([ - '!lib/Configuration/*', - 'lib/Configuration/Configuration.php', - ]); + 'tests/output/javascript/package.json', + 'tests/output/javascript/src/client/test.ts', - expect(matcher('lib/Configuration/Configuration.php')).toEqual(true); + 'tests/output/php/src/methods/requests/test.php', + ].sort() + ); }); }); diff --git a/scripts/ci/husky/pre-commit.js b/scripts/ci/husky/pre-commit.js index c53832ce79f..a56b35c2dd6 100755 --- a/scripts/ci/husky/pre-commit.js +++ b/scripts/ci/husky/pre-commit.js @@ -1,11 +1,11 @@ #!/usr/bin/env node -/* eslint-disable no-console */ /* eslint-disable import/no-commonjs */ /* eslint-disable @typescript-eslint/no-var-requires */ const chalk = require('chalk'); const execa = require('execa'); const micromatch = require('micromatch'); +const clientConfig = require('../../../config/clients.config.json'); const GENERATED_FILE_PATTERNS = require('../../../config/generation.config').patterns; @@ -15,60 +15,35 @@ const run = async (command, { cwd } = {}) => { ); }; -function createMemoizedMicromatchMatcher(patterns = []) { - const exactMatchers = []; - const positiveMatchers = []; - const negativeMatchers = []; - - patterns.forEach((pattern) => { - if (pattern.startsWith('!')) { - // Patterns starting with `!` are negated - negativeMatchers.push(micromatch.matcher(pattern.slice(1))); - } else if (!pattern.includes('*')) { - exactMatchers.push(micromatch.matcher(pattern)); - } else { - positiveMatchers.push(micromatch.matcher(pattern)); - } - }); - - return function matcher(str) { - if (exactMatchers.some((match) => match(str))) { - return true; - } - - // As `some` returns false on empty array, test will always fail if we only - // provide `negativeMatchers`. We fallback to `true` is it's the case. - const hasPositiveMatchers = - Boolean(positiveMatchers.length === 0 && negativeMatchers.length) || - positiveMatchers.some((match) => match(str)); - - return hasPositiveMatchers && !negativeMatchers.some((match) => match(str)); - }; +function getPatterns() { + const patterns = GENERATED_FILE_PATTERNS; + for (const [language, { tests }] of Object.entries(clientConfig)) { + patterns.push(`tests/output/${language}/${tests.outputFolder}/client/**`); + patterns.push(`tests/output/${language}/${tests.outputFolder}/methods/**`); + } + return patterns; } async function preCommit() { - const stagedFiles = (await run('git diff --name-only --cached')).split('\n'); - const deletedFiles = new Set( - (await run('git diff --name-only --staged --diff-filter=D')).split('\n') - ); - const matcher = createMemoizedMicromatchMatcher(GENERATED_FILE_PATTERNS); + // when merging, we want to stage all the files + if ((await run('git merge HEAD')) !== 'Already up to date.') { + return; + } - for (const stagedFile of stagedFiles) { - // keep the deleted files staged even if they were generated before. - if (deletedFiles.has(stagedFile)) { - continue; - } + const stagedFiles = ( + await run('git diff --name-only --cached --diff-filter=d') + ).split('\n'); - if (!matcher(stagedFile)) { - continue; - } + const toUnstage = micromatch.match(stagedFiles, getPatterns()); + for (const file of toUnstage) { + // eslint-disable-next-line no-console console.log( chalk.black.bgYellow('[INFO]'), - `Generated file found, unstaging: ${stagedFile}` + `Generated file found, unstaging: ${file}` ); - await run(`git restore --staged ${stagedFile}`); + await run(`git restore --staged ${file}`); } } @@ -76,6 +51,4 @@ if (require.main === module && !process.env.CI) { preCommit(); } -module.exports = { - createMemoizedMicromatchMatcher, -}; +module.exports = { getPatterns };