Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for labeling based on PR size #632

Open
wants to merge 4 commits into
base: v5.0.0-beta
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 9 additions & 2 deletions __tests__/changedFiles.test.ts
Expand Up @@ -4,12 +4,16 @@ import {
checkAnyChangedFiles,
toChangedFilesMatchConfig
} from '../src/changedFiles';
import {PrFileType} from '../src/labeler';

jest.mock('@actions/core');
jest.mock('@actions/github');

describe('checkAllChangedFiles', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 6},
{name: 'bar.txt', size: 20}
];

describe('when the globs match every file that has been changed', () => {
const globs = ['*.txt'];
Expand All @@ -31,7 +35,10 @@ describe('checkAllChangedFiles', () => {
});

describe('checkAnyChangedFiles', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 6},
{name: 'bar.txt', size: 20}
];

describe('when any glob matches any of the files that have changed', () => {
const globs = ['*.txt', '*.md'];
Expand Down
36 changes: 23 additions & 13 deletions __tests__/fixtures/all_options.yml
@@ -1,14 +1,24 @@
label1:
- any:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
- all:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
label-config:
label1:
- any:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
- all:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']

label2:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
label2:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
size-config: >
{
"100": "XS",
"200": "S",
"500": "M",
"800": "L",
"1000": "XL",
"2000": "XXL"
}
13 changes: 7 additions & 6 deletions __tests__/fixtures/any_and_all.yml
@@ -1,6 +1,7 @@
tests:
- any:
- head-branch: ['^tests/', '^test/']
- changed-files: ['tests/**/*']
- all:
- changed-files: ['!tests/requirements.txt']
label-config:
tests:
- any:
- head-branch: ['^tests/', '^test/']
- changed-files: ['tests/**/*']
- all:
- changed-files: ['!tests/requirements.txt']
17 changes: 9 additions & 8 deletions __tests__/fixtures/branches.yml
@@ -1,11 +1,12 @@
test-branch:
- head-branch: '^test/'
label-config:
test-branch:
- head-branch: '^test/'

feature-branch:
- head-branch: '/feature/'
feature-branch:
- head-branch: '/feature/'

bug-branch:
- head-branch: '^bug/|fix/'
bug-branch:
- head-branch: '^bug/|fix/'

array-branch:
- head-branch: ['^array/']
array-branch:
- head-branch: ['^array/']
15 changes: 15 additions & 0 deletions __tests__/fixtures/no_size_config.yml
@@ -0,0 +1,15 @@
label-config:
label1:
- any:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
- all:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']

label2:
- changed-files: ['glob']
- head-branch: ['regexp']
- base-branch: ['regexp']
7 changes: 4 additions & 3 deletions __tests__/fixtures/not_supported.yml
@@ -1,3 +1,4 @@
label:
- all:
- unknown: 'this-is-not-supported'
label-config:
label:
- all:
- unknown: 'this-is-not-supported'
5 changes: 3 additions & 2 deletions __tests__/fixtures/only_pdfs.yml
@@ -1,2 +1,3 @@
touched-a-pdf-file:
- changed-files: ['*.pdf']
label-config:
touched-a-pdf-file:
- changed-files: ['*.pdf']
12 changes: 12 additions & 0 deletions __tests__/fixtures/only_pdfs_custom_size.yml
@@ -0,0 +1,12 @@
label-config:
touched-a-pdf-file:
- changed-files: ['*.pdf']
size-config: >
{
"100": "XS",
"200": "S",
"500": "M",
"800": "L",
"1000": "XL",
"2000": "XXL"
}
145 changes: 140 additions & 5 deletions __tests__/labeler.test.ts
@@ -1,9 +1,12 @@
import {
checkMatchConfigs,
checkSizeConfigs,
MatchConfig,
toMatchConfig,
getLabelConfigMapFromObject,
BaseMatchConfig
getSizeConfigMapFromObject,
BaseMatchConfig,
PrFileType
} from '../src/labeler';
import * as yaml from 'js-yaml';
import * as core from '@actions/core';
Expand Down Expand Up @@ -58,6 +61,40 @@ describe('getLabelConfigMapFromObject', () => {
});
});

describe('getSizeConfigMapFromObject', () => {
describe('get default sizes when size-config is present', () => {
const yamlObject = loadYaml('__tests__/fixtures/no_size_config.yml');
const expected = new Map<number, string>();
expected.set(0, 'XS');
expected.set(10, 'S');
expected.set(30, 'M');
expected.set(100, 'L');
expected.set(500, 'XL');
expected.set(1000, 'XXL');

it('returns a SizeConfig', () => {
const result = getSizeConfigMapFromObject(yamlObject);
expect(result).toEqual(expected);
});
});

describe('get configured sizes when size-config is present', () => {
const yamlObject = loadYaml('__tests__/fixtures/all_options.yml');
const expected = new Map<number, string>();
expected.set(100, 'XS');
expected.set(200, 'S');
expected.set(500, 'M');
expected.set(800, 'L');
expected.set(1000, 'XL');
expected.set(2000, 'XXL');

it('returns a SizeConfig', () => {
const result = getSizeConfigMapFromObject(yamlObject);
expect(result).toEqual(expected);
});
});
});

describe('toMatchConfig', () => {
describe('when all expected config options are present', () => {
const config = {
Expand Down Expand Up @@ -92,14 +129,17 @@ describe('checkMatchConfigs', () => {
const matchConfig: MatchConfig[] = [{any: [{changedFiles: ['*.txt']}]}];

it('returns true when our pattern does match changed files', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 6},
{name: 'bar.txt', size: 20}
];
const result = checkMatchConfigs(changedFiles, matchConfig);

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

it('returns false when our pattern does not match changed files', () => {
const changedFiles = ['foo.docx'];
const changedFiles: PrFileType[] = [{name: 'foo.docx', size: 13}];
const result = checkMatchConfigs(changedFiles, matchConfig);

expect(result).toBeFalsy();
Expand All @@ -109,7 +149,10 @@ describe('checkMatchConfigs', () => {
const matchConfig: MatchConfig[] = [
{any: [{changedFiles: ['*.txt']}, {headBranch: ['some-branch']}]}
];
const changedFiles = ['foo.txt', 'bar.txt'];
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 6},
{name: 'bar.txt', size: 20}
];

const result = checkMatchConfigs(changedFiles, matchConfig);
expect(result).toBe(true);
Expand All @@ -121,7 +164,10 @@ describe('checkMatchConfigs', () => {
{any: [{changedFiles: ['*.txt']}]},
{any: [{headBranch: ['some-branch']}]}
];
const changedFiles = ['foo.txt', 'bar.md'];
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 6},
{name: 'bar.md', size: 20}
];

it('returns false when only one config matches', () => {
const result = checkMatchConfigs(changedFiles, matchConfig);
Expand All @@ -138,3 +184,92 @@ describe('checkMatchConfigs', () => {
});
});
});

describe('checkSizeConfigs', () => {
describe('when a single size config is provided', () => {
const sizeConfig: Map<number, string> = new Map<number, string>();
sizeConfig.set(100, 'XS');
sizeConfig.set(200, 'S');
sizeConfig.set(500, 'M');
sizeConfig.set(800, 'L');
sizeConfig.set(1000, 'XL');
sizeConfig.set(2000, 'XXL');

it('returns size/XXS when the size is less than the smallest size', () => {
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 10},
{name: 'baz.txt', size: 10},
{name: 'bar.txt', size: 10}
];
const result = checkSizeConfigs(changedFiles, sizeConfig);

expect(result).toBe('size/XXS');
});

it('returns size/XS when the size is less than the smallest size', () => {
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 50},
{name: 'baz.txt', size: 50},
{name: 'bar.txt', size: 50}
];
const result = checkSizeConfigs(changedFiles, sizeConfig);

expect(result).toBe('size/XS');
});

it('returns size/S when the size is less than the smallest size', () => {
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 100},
{name: 'baz.txt', size: 100},
{name: 'bar.txt', size: 100}
];
const result = checkSizeConfigs(changedFiles, sizeConfig);

expect(result).toBe('size/S');
});

it('returns size/M when the size is less than the smallest size', () => {
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 200},
{name: 'baz.txt', size: 200},
{name: 'bar.txt', size: 200}
];
const result = checkSizeConfigs(changedFiles, sizeConfig);

expect(result).toBe('size/M');
});

it('returns size/L when the size is less than the smallest size', () => {
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 300},
{name: 'baz.txt', size: 300},
{name: 'bar.txt', size: 300}
];
const result = checkSizeConfigs(changedFiles, sizeConfig);

expect(result).toBe('size/L');
});

it('returns size/XL when the size is less than the smallest size', () => {
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 400},
{name: 'baz.txt', size: 400},
{name: 'bar.txt', size: 400}
];
const result = checkSizeConfigs(changedFiles, sizeConfig);

expect(result).toBe('size/XL');
});

it('returns size/XXL when the size is less than the smallest size', () => {
const changedFiles: PrFileType[] = [
{name: 'foo.txt', size: 700},
{name: 'baz.txt', size: 700},
{name: 'bar.txt', size: 700}
];
const result = checkSizeConfigs(changedFiles, sizeConfig);

expect(result).toBe('size/XXL');
});
});
});