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

Assigns labels based on branch names #203

Merged
merged 119 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
2bf42e4
Add branch to MatchConfig interface
joshdales Aug 7, 2021
ad73546
Add function for checking branches
joshdales Aug 7, 2021
6c50d09
include checkBranch in checkMatch
joshdales Aug 7, 2021
ee0e0eb
Add a new fixture and test for the branch checking
joshdales Aug 7, 2021
a01b9ae
Add another test to make sure that partial branch naming works
joshdales Aug 7, 2021
bce88a9
Update new test description
joshdales Aug 7, 2021
765934f
Run build
joshdales Aug 7, 2021
827e118
Fix PR branch labeler
amiel Sep 15, 2021
8aa7614
Run build
amiel Sep 15, 2021
cb5f448
Use correct branch name and update tests
amiel Sep 15, 2021
2ced1f3
Run build
amiel Sep 15, 2021
d9ed3e8
Format
amiel Sep 15, 2021
79c0cc7
Include a test for branching
amiel Sep 15, 2021
27a1d89
Update src/labeler.ts
amiel Sep 16, 2021
7624214
Merge pull request #1 from bentohq/fix-branch-labeler
joshdales Sep 16, 2021
2d63815
Allow branch config to be an array as well
joshdales Sep 29, 2021
ab49f7a
Add tests for array branh labelling
joshdales Sep 29, 2021
2246b66
Run build
joshdales Sep 29, 2021
89f6b77
minor adjustment for successful branch matching.
joshdales Oct 29, 2021
7aadc17
Update the tests for applying multiple branch based labels
joshdales Oct 29, 2021
71fc664
run the build script
joshdales Oct 29, 2021
818399d
Merge branch 'main' into main
joshdales Jun 11, 2022
6e27606
Update README with reference to branch options
joshdales Jun 11, 2022
0ad789c
Merge branch 'main' into main
joshdales Aug 30, 2022
0861fa5
Run the build command
joshdales Aug 30, 2022
4c74e84
Fix typo in the README
joshdales Sep 22, 2022
7f8d8e4
Merge branch 'main' into main
joshdales Jan 11, 2023
c54c5a2
Run prettier
joshdales Jan 11, 2023
7b1327b
Run the build command
joshdales Jan 11, 2023
8c59ecc
Rename the getBranchName helper
joshdales Jan 28, 2023
f2b2513
Update the matching to use a regexp rather than minimatch
joshdales Jan 28, 2023
2343710
Move all the branch checking into its own file
joshdales Jan 28, 2023
cd3a8df
Create a test file for branch
joshdales Jan 28, 2023
0b6e68d
Add options for getting the head or base branch
joshdales Jan 28, 2023
2daf35a
Add an extra test now that we can check the base branch
joshdales Jan 28, 2023
231de6b
Remove the branch option and replace with just head-branch and base-b…
joshdales Jan 29, 2023
922ffdf
Remove deprecated IMinimatch import from labeler.ts
joshdales Jan 29, 2023
7a5c525
Create new interfaces for MatchConfig
joshdales Jan 29, 2023
969899d
Add the changedFiles key and update logic in labeler
joshdales Jan 29, 2023
7d17531
Update the labeler tests
joshdales Jan 29, 2023
b071d82
Run the build command
joshdales Jan 29, 2023
0eb9d49
reverse the conditions of checkMatch
joshdales Jan 29, 2023
09f0853
Fix some typos in the branch checks
joshdales Feb 19, 2023
ed31b27
Rename some functions and variables to match what they are doing
joshdales Feb 19, 2023
da83a18
Make sure that the changed files config values are an array
joshdales Feb 19, 2023
56347d5
Add unit tests for toBranchMatchConfig
joshdales Feb 21, 2023
8943ca2
Merge pull request #3 from joshdales/new-config-structure
joshdales Feb 21, 2023
e5b1bdd
Update the README with documentation about the new config structure
joshdales Feb 21, 2023
2e10ffb
Reference minimatch in docs
joshdales Mar 3, 2023
2a5bc55
Fix bad test descriptions
joshdales Mar 3, 2023
394a01b
Make getBranchName argument non-optional
joshdales Mar 3, 2023
5e6bdf6
update the example workflow in the readme
joshdales Mar 3, 2023
84e83a9
Merge branch 'main' into main
joshdales Mar 8, 2023
f40b387
Correct errors and typos in the README
joshdales Mar 17, 2023
90ef370
Merge branch 'actions:main' into main
joshdales Mar 18, 2023
3eec5d8
Update the syntax for checking a match
joshdales Mar 15, 2023
fc5eb71
Revert "reverse the conditions of checkMatch"
joshdales Mar 15, 2023
e4486e9
Throw an error if the config is the wrong type
joshdales Mar 18, 2023
e939550
Simplfy the conditions in toBranchMatchConfig
joshdales Mar 18, 2023
51b763c
Update comments in getMatchConfigs to represent updated types
joshdales Mar 18, 2023
c08f5fa
Condense assignment of further config options in toChangedFilesMatchC…
joshdales Mar 18, 2023
9f259ee
Rename checkGlobs to checkMatchConfigs and check each property
joshdales Mar 18, 2023
1ce9b35
Move all changedFiles logic into it's own file
joshdales Mar 18, 2023
ef108a9
Convert the yaml output to a matchConfig in getLabelConfigMapFromObject
joshdales Mar 18, 2023
a988f4e
Add todo tests for changedFiles
joshdales Mar 18, 2023
3af9a47
Add unit tests for toChangedFilesMatchConfig
joshdales Mar 18, 2023
c31ee1f
Add more unit tests for changedFiles.ts
joshdales Mar 18, 2023
17694aa
Update the argument type for toMatchConfig
joshdales Mar 18, 2023
e9a1777
Fix linting and formatting
joshdales Mar 18, 2023
65b7640
Add unit tests for toMatchConfig
joshdales Mar 18, 2023
7741e57
Run the build command
joshdales Mar 18, 2023
64ce5e9
Update README with better description for branches
joshdales Mar 20, 2023
cc1e025
Update object assignment in toChangedFilesMatchConfig
joshdales Mar 20, 2023
d0d3628
Add extra tests and use toEqual matcher.
joshdales Mar 20, 2023
92990c0
Don't allow empty changed-files objects through
joshdales Mar 20, 2023
d31255f
Make sure that empty config options don't accidently label things
joshdales Mar 20, 2023
b25e3a8
Better wording for the new test
joshdales Mar 20, 2023
1c9c27e
Run the build command
joshdales Mar 21, 2023
8e6367d
Merge branch 'main' into main
joshdales Mar 23, 2023
9bfc999
Run build and fix bad merge
joshdales Mar 23, 2023
5d0a66e
Run the build command again
joshdales Mar 23, 2023
e51b118
Change the structure of the config
joshdales Mar 25, 2023
a9e07ce
Add some new tests
joshdales Mar 25, 2023
3bec922
Add any and all functions for both checks
joshdales Mar 25, 2023
432b275
Get all the tests passings
joshdales Mar 25, 2023
4967646
Run the build command
joshdales Mar 25, 2023
4554c0d
Add a bunch more tests
joshdales Mar 25, 2023
5ac9519
Update the README
joshdales Mar 25, 2023
ef6ab1b
Add function for checking if any path matches
joshdales Mar 25, 2023
62f22bd
Run the build command
joshdales Mar 25, 2023
0b2cfb0
Im an idiot, bad copy pasta
joshdales Mar 25, 2023
29382eb
Build command
joshdales Mar 25, 2023
fa7f98c
Yikes, still missed that
joshdales Mar 25, 2023
210043e
Run the build command
joshdales Mar 25, 2023
938f9c9
Update the readme a little more
joshdales Mar 26, 2023
3ddce51
Update the debug values
joshdales Mar 27, 2023
4be192c
Run the build command
joshdales Mar 27, 2023
67604ee
Update more debugging statements
joshdales Mar 27, 2023
b1a2f85
Update debugging indentation on the branch checks
joshdales Mar 27, 2023
2f1dfd1
Adjust the indenting again
joshdales Mar 27, 2023
7f169bc
Merge pull request #4 from joshdales/another-config-setup
joshdales Mar 27, 2023
d4d4a10
Have a single isMatch for checking changed files
joshdales Apr 13, 2023
2637d23
Add test for when not all globs match any changed file
joshdales Apr 13, 2023
c1b0ca7
Run the build command
joshdales Apr 13, 2023
2a3422a
Better description for the new test
joshdales Apr 13, 2023
13e75b4
minor update to the readme
joshdales Apr 13, 2023
68a2598
Merge branch 'actions:main' into main
joshdales Apr 13, 2023
11812c3
Revert "Have a single isMatch for checking changed files"
joshdales May 5, 2023
9488def
Update tests and build
joshdales May 5, 2023
3aa0d43
Better test description
joshdales May 5, 2023
9cfddd0
Consolidate the new any change files test into the old one
joshdales May 5, 2023
51cc5e0
Update text in test descriptions and logging
joshdales May 11, 2023
09645fd
Move the allowed Matchconfig keys into a constant
joshdales May 11, 2023
34a5bf6
Update the validation when there are no options in the matchConfigs
joshdales May 11, 2023
4ac1764
Add a guard clause to stop false changed-files positives
joshdales May 11, 2023
a5bed11
Run the build command
joshdales May 11, 2023
a256a58
Add check for empty objects in checkAll
joshdales May 15, 2023
57d3407
Better check for empty configs in checkAll
joshdales May 17, 2023
3352df1
Bring test I accidently deleted
joshdales May 17, 2023
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
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</a>
</p>

Automatically label new pull requests based on the paths of files being changed.
Automatically label new pull requests based on the paths of files being changed or the branch name.

## Usage

Expand All @@ -26,13 +26,15 @@ For more control over matching, you can provide a match object instead of a simp
```yml
- any: ['list', 'of', 'globs']
all: ['list', 'of', 'globs']
branch: ['list', 'of, 'globs']
joshdales marked this conversation as resolved.
Show resolved Hide resolved
```

One or both fields can be provided for fine-grained matching. Unlike the top-level list, the list of path globs provided to `any` and `all` must ALL match against a path for the label to be applied.
One or all fields can be provided for fine-grained matching. Unlike the top-level list, the list of path globs provided to `any` and `all` must ALL match against a path for the label to be applied.

The fields are defined as follows:
* `any`: match ALL globs against ANY changed path
* `all`: match ALL globs against ALL changed paths
* `branch`: match ANY glob against the branch name

A simple path glob is the equivalent to `any: ['glob']`. More specifically, the following two configurations are equivalent:
```yml
Expand Down Expand Up @@ -61,6 +63,10 @@ label2: example2/*
label3:
- '**/*.txt'


# Add 'label4' to any PR where the branch name starts with 'example4'
label4:
- branch: 'example4/**'
```

#### Common Examples
Expand All @@ -87,6 +93,10 @@ source:
frontend:
- any: ['src/**/*.js']
all: ['!src/main.js']

# Add 'feature' label to any branch that starts with `feature` or has a `feature` section in the name
joshdales marked this conversation as resolved.
Show resolved Hide resolved
feature:
- branch: ['feature/**', '*/feature/**']
```

### Create Workflow
Expand Down
8 changes: 7 additions & 1 deletion __mocks__/@actions/github.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
export const context = {
payload: {
pull_request: {
number: 123
number: 123,
head: {
ref: 'head-branch-name'
},
base: {
ref: 'base-branch-name'
}
}
},
repo: {
Expand Down
155 changes: 155 additions & 0 deletions __tests__/branch.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import {
getBranchName,
checkBranch,
toBranchMatchConfig,
BranchMatchConfig
} from '../src/branch';
import * as github from '@actions/github';

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

describe('getBranchName', () => {
describe('when the pull requests base branch is requested', () => {
it('returns the base branch name', () => {
const result = getBranchName('base');
expect(result).toEqual('base-branch-name');
});
});

describe('when the pull requests head branch is requested', () => {
it('returns the head branch name', () => {
const result = getBranchName('head');
expect(result).toEqual('head-branch-name');
});
});

describe('when no branch is specified', () => {
it('returns the head branch name', () => {
const result = getBranchName();
expect(result).toEqual('head-branch-name');
});
});
});

describe('checkBranch', () => {
beforeEach(() => {
github.context.payload.pull_request!.head = {
ref: 'test/feature/123'
};
github.context.payload.pull_request!.base = {
ref: 'main'
};
});

describe('when a single pattern is provided', () => {
describe('and the pattern matches the head branch', () => {
it('returns true', () => {
const result = checkBranch(['^test']);
expect(result).toBe(true);
});
});

describe('and the pattern does not match the head branch', () => {
it('returns false', () => {
const result = checkBranch(['^feature/']);
expect(result).toBe(false);
});
});
});

describe('when multiple patterns are provided', () => {
describe('and at least one pattern matches', () => {
it('returns true', () => {
const result = checkBranch(['^test/', '^feature/']);
expect(result).toBe(true);
});
});

describe('and all patterns match', () => {
it('returns true', () => {
const result = checkBranch(['^test/', '/feature/']);
expect(result).toBe(true);
});
});

describe('and no patterns match', () => {
it('returns false', () => {
const result = checkBranch(['^feature/', '/test$']);
expect(result).toBe(false);
});
});
});

describe('when the branch to check is specified as the base branch', () => {
describe('and the pattern matches the base branch', () => {
it('returns true', () => {
const result = checkBranch(['^main$'], 'base');
expect(result).toBe(true);
});
});
});
});

describe('toBranchMatchConfig', () => {
describe('when there are no branch keys in the config', () => {
const config = {'changed-files': [{any: ['testing']}]};
it('returns an empty object', () => {
const result = toBranchMatchConfig(config);
expect(result).toMatchObject({});
});
});

describe('when the config contains a head-branch option', () => {
const config = {'head-branch': ['testing']};
it('sets headBranch in the matchConfig', () => {
const result = toBranchMatchConfig(config);
expect(result).toMatchObject<BranchMatchConfig>({
headBranch: ['testing']
});
});

describe('and the matching option is a string', () => {
const stringConfig = {'head-branch': 'testing'};

it('sets headBranch in the matchConfig', () => {
const result = toBranchMatchConfig(stringConfig);
expect(result).toMatchObject<BranchMatchConfig>({
headBranch: ['testing']
});
});
});
});

describe('when the config contains a base-branch option', () => {
const config = {'base-branch': ['testing']};
it('sets headBranch in the matchConfig', () => {
joshdales marked this conversation as resolved.
Show resolved Hide resolved
const result = toBranchMatchConfig(config);
expect(result).toMatchObject<BranchMatchConfig>({
baseBranch: ['testing']
});
});

describe('and the matching option is a string', () => {
const stringConfig = {'base-branch': 'testing'};

it('sets headBranch in the matchConfig', () => {
joshdales marked this conversation as resolved.
Show resolved Hide resolved
const result = toBranchMatchConfig(stringConfig);
expect(result).toMatchObject<BranchMatchConfig>({
baseBranch: ['testing']
});
});
});
});

describe('when the config contains both a base-branch and head-branch option', () => {
const config = {'base-branch': ['testing'], 'head-branch': ['testing']};
it('sets headBranch in the matchConfig', () => {
joshdales marked this conversation as resolved.
Show resolved Hide resolved
const result = toBranchMatchConfig(config);
expect(result).toMatchObject<BranchMatchConfig>({
baseBranch: ['testing'],
headBranch: ['testing']
});
});
});
});
11 changes: 11 additions & 0 deletions __tests__/fixtures/branches.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
test-branch:
- head-branch: "^test/"

feature-branch:
- head-branch: "/feature/"

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

array-branch:
- head-branch: ["^array/"]
3 changes: 2 additions & 1 deletion __tests__/fixtures/only_pdfs.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
touched-a-pdf-file:
- any: ['*.pdf']
- changed-files:
- any: ['*.pdf']
8 changes: 6 additions & 2 deletions __tests__/labeler.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {checkGlobs} from '../src/labeler';
import {checkGlobs, MatchConfig} from '../src/labeler';

import * as core from '@actions/core';

Expand All @@ -10,7 +10,11 @@ beforeAll(() => {
});
});

const matchConfig = [{any: ['*.txt']}];
// I have to double cast here as this is what the output from js-yaml looks like which then gets
// transformed in toMatchConfig
const matchConfig = [
{'changed-files': [{any: ['*.txt']}]}
] as unknown as MatchConfig[];

describe('checkGlobs', () => {
it('returns true when our pattern does match changed files', () => {
Expand Down
59 changes: 59 additions & 0 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const paginateMock = jest.spyOn(gh, 'paginate');
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');

const yamlFixtures = {
'branches.yml': fs.readFileSync('__tests__/fixtures/branches.yml'),
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml')
};

Expand Down Expand Up @@ -102,6 +103,64 @@ describe('run', () => {
expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(removeLabelMock).toHaveBeenCalledTimes(0);
});

it('adds labels based on the branch names that match the regexp pattern', async () => {
github.context.payload.pull_request!.head = {ref: 'test/testing-time'};
usingLabelerConfigYaml('branches.yml');
await run();

expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['test-branch']
});
});

it('adds multiple labels based on branch names that match different regexp patterns', async () => {
github.context.payload.pull_request!.head = {
ref: 'test/feature/123'
};
usingLabelerConfigYaml('branches.yml');
await run();

expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['test-branch', 'feature-branch']
});
});

it('it can support multiple branches by batching', async () => {
github.context.payload.pull_request!.head = {ref: 'fix/123'};
usingLabelerConfigYaml('branches.yml');
await run();

expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['bug-branch']
});
});

it('it can support multiple branches by providing an array', async () => {
github.context.payload.pull_request!.head = {ref: 'array/123'};
usingLabelerConfigYaml('branches.yml');
await run();

expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['array-branch']
});
});
});

function usingLabelerConfigYaml(fixtureName: keyof typeof yamlFixtures): void {
Expand Down