Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The base match object is defined as:
- head-branch: ['list', 'of', 'regexps']
```

There are two top-level keys, `any` and `all`, which both accept the same configuration options:
There are three top-level keys, `any`, `all` and `none`, which all accept the same configuration options:
```yml
- any:
- changed-files:
Expand All @@ -66,12 +66,13 @@ There are two top-level keys, `any` and `all`, which both accept the same config
- head-branch: ['list', 'of', 'regexps']
```

From a boolean logic perspective, top-level match objects, and options within `all` are `AND`-ed together and individual match rules within the `any` object are `OR`-ed.
From a boolean logic perspective, top-level match objects, and options within `all` are `AND`-ed together and individual match rules within the `any` object are `OR`-ed. `none` is the inverse of `any`.

One or all fields can be provided for fine-grained matching.
The fields are defined as follows:
- `all`: ALL of the provided options must match for the label to be applied
- `any`: if ANY of the provided options match then the label will be applied
- `none`: will assign the label if none of the provided options match - e.g. missing changes to documentation or unit tests
- `base-branch`: match regexps against the base branch name
- `head-branch`: match regexps against the head branch name
- `changed-files`: match glob patterns against the changed paths
Expand Down Expand Up @@ -137,6 +138,12 @@ Documentation:
- changed-files:
- any-glob-to-any-file: '**/*.md'

# Add `Missing Documentation` label to any code change which doesn't include doc changes
Missing Documentation:
- none:
- changed-files:
- any-glob-to-any-file: '**/*.md'

# Add 'source' label to any change to src files within the source dir EXCEPT for the docs sub-folder
source:
- all:
Expand Down
5 changes: 5 additions & 0 deletions __tests__/fixtures/all_options.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ label1:
- all-globs-to-all-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
- none:
- changed-files:
- all-globs-to-all-files: ['notthisglob']
- head-branch: ['notthisone']
- base-branch: ['notthisone']

label2:
- changed-files:
Expand Down
37 changes: 37 additions & 0 deletions __tests__/labeler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ describe('getLabelConfigMapFromObject', () => {
{baseBranch: undefined, headBranch: ['regexp']},
{baseBranch: ['regexp'], headBranch: undefined}
]
},
{
none: [
{changedFiles: [{allGlobsToAllFiles: ['notthisglob']}]},
{baseBranch: undefined, headBranch: ['notthisone']},
{baseBranch: ['notthisone'], headBranch: undefined}
]
}
]);
expected.set('label2', [
Expand Down Expand Up @@ -135,6 +142,36 @@ describe('checkMatchConfigs', () => {

expect(result).toBeTruthy();
});

it('returns true when no files match the "none" config', () => {
const matchConfig: MatchConfig[] = [
{
none: [
{changedFiles: [{anyGlobToAnyFile: ['*.md']}]},
{headBranch: ['some-branch']}
]
}
];
const changedFiles = ['foo.txt', 'bar.txt'];

const result = checkMatchConfigs(changedFiles, matchConfig, false);
expect(result).toBe(true);
});

it('returns false when files match the "none" config', () => {
const matchConfig: MatchConfig[] = [
{
none: [
{changedFiles: [{anyGlobToAnyFile: ['*.md']}]},
{headBranch: ['some-branch']}
]
}
];
const changedFiles = ['foo.md', 'bar.md'];

const result = checkMatchConfigs(changedFiles, matchConfig, false);
expect(result).toBe(false);
});
});

describe('when multiple MatchConfigs are supplied', () => {
Expand Down
5 changes: 3 additions & 2 deletions src/api/get-label-configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {toBranchMatchConfig, BranchMatchConfig} from '../branch';
export interface MatchConfig {
all?: BaseMatchConfig[];
any?: BaseMatchConfig[];
none?: BaseMatchConfig[];
}

export type BaseMatchConfig = BranchMatchConfig & ChangedFilesMatchConfig;
Expand Down Expand Up @@ -79,9 +80,9 @@ export function getLabelConfigMapFromObject(
}

Object.entries(configValue).forEach(([key, value]) => {
// If the top level `any` or `all` keys are provided then set them, and convert their values to
// If the top level `any`, `all` or `none` keys are provided then set them, and convert their values to
// our config objects.
if (key === 'any' || key === 'all') {
if (key === 'any' || key === 'all' || key === 'none') {
if (Array.isArray(value)) {
const newConfigs = value.map(toMatchConfig);
updatedConfig.push({[key]: newConfigs});
Expand Down
6 changes: 6 additions & 0 deletions src/labeler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ function checkMatch(
}
}

if (matchConfig.none) {
if (checkAny(matchConfig.none, changedFiles, dot)) {
return false;
}
}

return true;
}

Expand Down