From 417f74a55596e4fe1294e2634f040ea0cb1d4a66 Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sun, 16 Feb 2025 08:20:51 -0500 Subject: [PATCH 1/7] Update test to show expected behaviour --- __tests__/changedFiles.test.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/__tests__/changedFiles.test.ts b/__tests__/changedFiles.test.ts index 07e0b7575..e0927bf88 100644 --- a/__tests__/changedFiles.test.ts +++ b/__tests__/changedFiles.test.ts @@ -100,12 +100,11 @@ describe('toChangedFilesMatchConfig', () => { describe('but the glob pattern config key is not provided', () => { const config = {'changed-files': ['bar']}; - it('throws the error', () => { - expect(() => { - toChangedFilesMatchConfig(config); - }).toThrow( - `The "changed-files" section must have a valid config structure. Please read the action documentation for more information` - ); + it('defaults to anyGlobToAnyFile', () => { + const result = toChangedFilesMatchConfig(config); + expect(result).toEqual({ + changedFiles: [{anyGlobToAnyFile: ['bar']}] + }); }); }); From 08676b1dc53955bc191152f8115433fbba255e49 Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sun, 16 Feb 2025 10:30:38 -0500 Subject: [PATCH 2/7] Update config to default to any option --- src/changedFiles.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/changedFiles.ts b/src/changedFiles.ts index a5038f96a..def32a2d6 100644 --- a/src/changedFiles.ts +++ b/src/changedFiles.ts @@ -57,6 +57,19 @@ export function toChangedFilesMatchConfig( const validChangedFilesConfigs: ChangedFilesGlobPatternsConfig[] = []; changedFilesConfigs.forEach(changedFilesConfig => { + if ( + typeof changedFilesConfig === 'string' || + (Array.isArray(changedFilesConfig) && + changedFilesConfig.every(config => typeof config === 'string')) + ) { + const value = + typeof changedFilesConfig === 'string' + ? [changedFilesConfig] + : changedFilesConfig; + validChangedFilesConfigs.push({anyGlobToAnyFile: value}); + return; + } + if (!isObject(changedFilesConfig)) { throw new Error( `The "changed-files" section must have a valid config structure. Please read the action documentation for more information` From 65a1fbecea92a46c20cef2b3a3fa9ea09074d497 Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sun, 16 Feb 2025 10:32:50 -0500 Subject: [PATCH 3/7] Add option for defaulting to all --- __tests__/changedFiles.test.ts | 9 +++++++++ src/changedFiles.ts | 6 ++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/__tests__/changedFiles.test.ts b/__tests__/changedFiles.test.ts index e0927bf88..2851cb7cf 100644 --- a/__tests__/changedFiles.test.ts +++ b/__tests__/changedFiles.test.ts @@ -106,6 +106,15 @@ describe('toChangedFilesMatchConfig', () => { changedFiles: [{anyGlobToAnyFile: ['bar']}] }); }); + + describe('and the defaultToAll option is passed', () => { + it('defaults to allGlobToAllFiles', () => { + const result = toChangedFilesMatchConfig(config, true); + expect(result).toEqual({ + changedFiles: [{allGlobsToAllFiles: ['bar']}] + }); + }); + }); }); describe('but the glob pattern config key is not valid', () => { diff --git a/src/changedFiles.ts b/src/changedFiles.ts index def32a2d6..8ab645363 100644 --- a/src/changedFiles.ts +++ b/src/changedFiles.ts @@ -45,7 +45,8 @@ export async function getChangedFiles( } export function toChangedFilesMatchConfig( - config: any + config: any, + defaultToAll = false ): ChangedFilesMatchConfig { if (!config['changed-files'] || !config['changed-files'].length) { return {}; @@ -62,11 +63,12 @@ export function toChangedFilesMatchConfig( (Array.isArray(changedFilesConfig) && changedFilesConfig.every(config => typeof config === 'string')) ) { + const key = defaultToAll ? 'allGlobsToAllFiles' : 'anyGlobToAnyFile'; const value = typeof changedFilesConfig === 'string' ? [changedFilesConfig] : changedFilesConfig; - validChangedFilesConfigs.push({anyGlobToAnyFile: value}); + validChangedFilesConfigs.push({[key]: value}); return; } From ffd34551debe6f55eb33479d4e37162d25abc1e5 Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sun, 16 Feb 2025 11:12:39 -0500 Subject: [PATCH 4/7] Parse configs to default options --- __tests__/fixtures/default_any_and_all.yml | 6 ++ __tests__/labeler.test.ts | 80 +++++++++++++--------- __tests__/main.test.ts | 5 +- src/api/get-label-configs.ts | 11 ++- 4 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 __tests__/fixtures/default_any_and_all.yml diff --git a/__tests__/fixtures/default_any_and_all.yml b/__tests__/fixtures/default_any_and_all.yml new file mode 100644 index 000000000..8fe0e28cd --- /dev/null +++ b/__tests__/fixtures/default_any_and_all.yml @@ -0,0 +1,6 @@ +default_any: + - changed-files: ['glob'] + +default_all: + - all: + - changed-files: ['glob'] diff --git a/__tests__/labeler.test.ts b/__tests__/labeler.test.ts index b780c82ff..ae07fab17 100644 --- a/__tests__/labeler.test.ts +++ b/__tests__/labeler.test.ts @@ -24,37 +24,55 @@ const loadYaml = (filepath: string) => { }; describe('getLabelConfigMapFromObject', () => { - const yamlObject = loadYaml('__tests__/fixtures/all_options.yml'); - const expected = new Map(); - expected.set('label1', [ - { - any: [ - {changedFiles: [{anyGlobToAnyFile: ['glob']}]}, - {baseBranch: undefined, headBranch: ['regexp']}, - {baseBranch: ['regexp'], headBranch: undefined} - ] - }, - { - all: [ - {changedFiles: [{allGlobsToAllFiles: ['glob']}]}, - {baseBranch: undefined, headBranch: ['regexp']}, - {baseBranch: ['regexp'], headBranch: undefined} - ] - } - ]); - expected.set('label2', [ - { - any: [ - {changedFiles: [{anyGlobToAnyFile: ['glob']}]}, - {baseBranch: undefined, headBranch: ['regexp']}, - {baseBranch: ['regexp'], headBranch: undefined} - ] - } - ]); - - it('returns a MatchConfig', () => { - const result = getLabelConfigMapFromObject(yamlObject); - expect(result).toEqual(expected); + describe('when all options are present', () => { + const yamlObject = loadYaml('__tests__/fixtures/all_options.yml'); + const expected = new Map(); + expected.set('label1', [ + { + any: [ + {changedFiles: [{anyGlobToAnyFile: ['glob']}]}, + {baseBranch: undefined, headBranch: ['regexp']}, + {baseBranch: ['regexp'], headBranch: undefined} + ] + }, + { + all: [ + {changedFiles: [{allGlobsToAllFiles: ['glob']}]}, + {baseBranch: undefined, headBranch: ['regexp']}, + {baseBranch: ['regexp'], headBranch: undefined} + ] + } + ]); + expected.set('label2', [ + { + any: [ + {changedFiles: [{anyGlobToAnyFile: ['glob']}]}, + {baseBranch: undefined, headBranch: ['regexp']}, + {baseBranch: ['regexp'], headBranch: undefined} + ] + } + ]); + + it('returns a MatchConfig', () => { + const result = getLabelConfigMapFromObject(yamlObject); + expect(result).toEqual(expected); + }); + }); + + describe('when no any or all key are present', () => { + const yamlObject = loadYaml('__tests__/fixtures/default_any_and_all.yml'); + const expected = new Map(); + expected.set('default_any', [ + {any: [{changedFiles: [{anyGlobToAnyFile: ['glob']}]}]} + ]); + expected.set('default_all', [ + {all: [{changedFiles: [{allGlobsToAllFiles: ['glob']}]}]} + ]); + + it('returns a MatchConfig', () => { + const result = getLabelConfigMapFromObject(yamlObject); + expect(result).toEqual(expected); + }); }); }); diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 0490f7953..ee8d33ef2 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -37,7 +37,10 @@ const yamlFixtures = { 'branches.yml': fs.readFileSync('__tests__/fixtures/branches.yml'), 'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml'), 'not_supported.yml': fs.readFileSync('__tests__/fixtures/not_supported.yml'), - 'any_and_all.yml': fs.readFileSync('__tests__/fixtures/any_and_all.yml') + 'any_and_all.yml': fs.readFileSync('__tests__/fixtures/any_and_all.yml'), + 'default_any_and_all.yml': fs.readFileSync( + '__tests__/fixtures/default_any_and_all.yml' + ) }; const configureInput = ( diff --git a/src/api/get-label-configs.ts b/src/api/get-label-configs.ts index 4db33f28e..219c8a795 100644 --- a/src/api/get-label-configs.ts +++ b/src/api/get-label-configs.ts @@ -83,7 +83,9 @@ export function getLabelConfigMapFromObject( // our config objects. if (key === 'any' || key === 'all') { if (Array.isArray(value)) { - const newConfigs = value.map(toMatchConfig); + const newConfigs = value.map(config => + toMatchConfig(config, key === 'all') + ); updatedConfig.push({[key]: newConfigs}); } } else if (ALLOWED_CONFIG_KEYS.includes(key)) { @@ -115,8 +117,11 @@ export function getLabelConfigMapFromObject( return labelMap; } -export function toMatchConfig(config: any): BaseMatchConfig { - const changedFilesConfig = toChangedFilesMatchConfig(config); +export function toMatchConfig( + config: any, + defaultToAll = false +): BaseMatchConfig { + const changedFilesConfig = toChangedFilesMatchConfig(config, defaultToAll); const branchConfig = toBranchMatchConfig(config); return { From 0c2df5e12f2b92c4b8b27167a0618b396754bf1c Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sun, 16 Feb 2025 11:20:53 -0500 Subject: [PATCH 5/7] Update documentation with examples --- README.md | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 05bfaea6a..4f5ed6687 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ The match object allows control over the matching options. You can specify the l The base match object is defined as: ```yml -- changed-files: +- changed-files: - any-glob-to-any-file: ['list', 'of', 'globs'] - any-glob-to-all-files: ['list', 'of', 'globs'] - all-globs-to-any-file: ['list', 'of', 'globs'] @@ -87,7 +87,35 @@ Documentation: - any-glob-to-any-file: 'docs/*' ``` - If path globs are combined with `!` negation, you can write complex matching rules. See the examples below for more information. +If path globs are combined with `!` negation, you can write complex matching rules. See the examples below for more information. + +Furthermore, if a top-level key is omitted, or is `any` then a `changed-files` key without any further options will default to `any-glob-to-any-file`, though if an `all` key is provided it will default to `all-globs-to-all-files`. + +For example the following would be the same: +```yml +Documentation: +- changed-files: 'docs/*' +``` +and +```yml +Documentation: +- any + - changed-files: + - any-glob-to-any-file: 'docs/*' +``` +along with +```yml +Documentation: +- all: + - changed-files: 'docs/*' +``` +and +```yml +Documentation: +- all: + - changed-files: + - all-globs-to-all-files: 'docs/*' +``` #### Basic Examples @@ -125,7 +153,7 @@ Documentation: - changed-files: - any-glob-to-any-file: ['docs/*', 'guides/*'] -# Add 'Documentation' label to any change to .md files within the entire repository +# Add 'Documentation' label to any change to .md files within the entire repository Documentation: - changed-files: - any-glob-to-any-file: '**/*.md' @@ -206,10 +234,10 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - + # Label PRs 1, 2, and 3 - uses: actions/labeler@v5 - with: + with: pr-number: | 1 2 @@ -218,9 +246,9 @@ jobs: **Note:** in normal usage the `pr-number` input is not required as the action will detect the PR number from the workflow context. -#### Outputs +#### Outputs -Labeler provides the following outputs: +Labeler provides the following outputs: | Name | Description | |--------------|-----------------------------------------------------------| @@ -242,13 +270,13 @@ jobs: steps: - id: label-the-PR uses: actions/labeler@v5 - + - id: run-frontend-tests if: contains(steps.label-the-PR.outputs.all-labels, 'frontend') run: | echo "Running frontend tests..." # Put your commands for running frontend tests here - + - id: run-backend-tests if: contains(steps.label-the-PR.outputs.all-labels, 'backend') run: | From e0744f1a7ee0f4ae59b882d15fc2f3ae306869ef Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sun, 16 Feb 2025 11:54:47 -0500 Subject: [PATCH 6/7] Run build --- dist/index.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dist/index.js b/dist/index.js index c049f02d7..79bb5b391 100644 --- a/dist/index.js +++ b/dist/index.js @@ -320,7 +320,7 @@ function getLabelConfigMapFromObject(configObject) { // our config objects. if (key === 'any' || key === 'all') { if (Array.isArray(value)) { - const newConfigs = value.map(toMatchConfig); + const newConfigs = value.map(config => toMatchConfig(config, key === 'all')); updatedConfig.push({ [key]: newConfigs }); } } @@ -349,8 +349,8 @@ function getLabelConfigMapFromObject(configObject) { } return labelMap; } -function toMatchConfig(config) { - const changedFilesConfig = (0, changedFiles_1.toChangedFilesMatchConfig)(config); +function toMatchConfig(config, defaultToAll = false) { + const changedFilesConfig = (0, changedFiles_1.toChangedFilesMatchConfig)(config, defaultToAll); const branchConfig = (0, branch_1.toBranchMatchConfig)(config); return Object.assign(Object.assign({}, changedFilesConfig), branchConfig); } @@ -663,7 +663,7 @@ function getChangedFiles(client, prNumber) { return changedFiles; }); } -function toChangedFilesMatchConfig(config) { +function toChangedFilesMatchConfig(config, defaultToAll = false) { if (!config['changed-files'] || !config['changed-files'].length) { return {}; } @@ -672,6 +672,16 @@ function toChangedFilesMatchConfig(config) { : [config['changed-files']]; const validChangedFilesConfigs = []; changedFilesConfigs.forEach(changedFilesConfig => { + if (typeof changedFilesConfig === 'string' || + (Array.isArray(changedFilesConfig) && + changedFilesConfig.every(config => typeof config === 'string'))) { + const key = defaultToAll ? 'allGlobsToAllFiles' : 'anyGlobToAnyFile'; + const value = typeof changedFilesConfig === 'string' + ? [changedFilesConfig] + : changedFilesConfig; + validChangedFilesConfigs.push({ [key]: value }); + return; + } if (!(0, utils_1.isObject)(changedFilesConfig)) { throw new Error(`The "changed-files" section must have a valid config structure. Please read the action documentation for more information`); } From b28fd7b64228b94ddce2a4a1dbfc08d88150f660 Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sun, 16 Feb 2025 11:55:48 -0500 Subject: [PATCH 7/7] Update formatting --- __tests__/fixtures/default_any_and_all.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__tests__/fixtures/default_any_and_all.yml b/__tests__/fixtures/default_any_and_all.yml index 8fe0e28cd..16a6d01c4 100644 --- a/__tests__/fixtures/default_any_and_all.yml +++ b/__tests__/fixtures/default_any_and_all.yml @@ -3,4 +3,4 @@ default_any: default_all: - all: - - changed-files: ['glob'] + - changed-files: ['glob']