Skip to content

Commit

Permalink
fix: Limit number of labels added to 100 (#497)
Browse files Browse the repository at this point in the history
* push to excess labels to avoid reaching the limit

* build dist

* never set more than 100 labels

* use splice instead of set

* ignore IDE folders

* install @octokit/plugin-retry

* always setLabels

* fix indentations

* fix specs

* add spec for excess labels

* prettier

* licensed cache

* revert to !!core.getInput('sync-labels')

* better warning for exceeded labels

* keep manually-added labels

* nest the dedupe logic

* rename `removeLabel` to `removeLabelFromList` to avoid confusion

* use Sets, and issue a call only if labels have actually changed

* remove IDE config folders from gitignore

* remove obsolete duplucation check

---------

Co-authored-by: Mark Massoud <mark@unrealcloud.io>
  • Loading branch information
markmssd and unrealclouder committed Jun 21, 2023
1 parent b5ff161 commit 7a202e6
Show file tree
Hide file tree
Showing 12 changed files with 1,933 additions and 77 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .licenses/npm/@octokit/openapi-types-17.2.0.dep.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions .licenses/npm/@octokit/plugin-retry.dep.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .licenses/npm/@octokit/types-9.2.3.dep.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions .licenses/npm/bottleneck.dep.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions __mocks__/@actions/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ export const context = {
const mockApi = {
rest: {
issues: {
addLabels: jest.fn(),
removeLabel: jest.fn()
setLabels: jest.fn()
},
pulls: {
get: jest.fn().mockResolvedValue({}),
Expand Down
79 changes: 59 additions & 20 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ jest.mock('@actions/core');
jest.mock('@actions/github');

const gh = github.getOctokit('_');
const addLabelsMock = jest.spyOn(gh.rest.issues, 'addLabels');
const removeLabelMock = jest.spyOn(gh.rest.issues, 'removeLabel');
const setLabelsMock = jest.spyOn(gh.rest.issues, 'setLabels');
const reposMock = jest.spyOn(gh.rest.repos, 'getContent');
const paginateMock = jest.spyOn(gh, 'paginate');
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');
const coreWarningMock = jest.spyOn(core, 'warning');

const yamlFixtures = {
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml')
Expand Down Expand Up @@ -41,12 +41,16 @@ describe('run', () => {
configureInput({});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {
labels: []
}
});

await run();

expect(removeLabelMock).toHaveBeenCalledTimes(0);
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
Expand All @@ -58,12 +62,16 @@ describe('run', () => {
configureInput({dot: true});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('.foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {
labels: []
}
});

await run();

expect(removeLabelMock).toHaveBeenCalledTimes(0);
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
Expand All @@ -75,11 +83,15 @@ describe('run', () => {
configureInput({});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('.foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {
labels: []
}
});

await run();

expect(removeLabelMock).toHaveBeenCalledTimes(0);
expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});

it('(with dot: true) does not add labels to PRs that do not match our glob patterns', async () => {
Expand All @@ -89,8 +101,7 @@ describe('run', () => {

await run();

expect(removeLabelMock).toHaveBeenCalledTimes(0);
expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});

it('(with sync-labels: true) it deletes preexisting PR labels that no longer match the glob pattern', async () => {
Expand All @@ -104,19 +115,18 @@ describe('run', () => {
mockGitHubResponseChangedFiles('foo.txt');
getPullMock.mockResolvedValue(<any>{
data: {
labels: [{name: 'touched-a-pdf-file'}]
labels: [{name: 'touched-a-pdf-file'}, {name: 'manually-added'}]
}
});

await run();

expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(removeLabelMock).toHaveBeenCalledTimes(1);
expect(removeLabelMock).toHaveBeenCalledWith({
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
name: 'touched-a-pdf-file'
labels: ['manually-added']
});
});

Expand All @@ -131,14 +141,43 @@ describe('run', () => {
mockGitHubResponseChangedFiles('foo.txt');
getPullMock.mockResolvedValue(<any>{
data: {
labels: [{name: 'touched-a-pdf-file'}]
labels: [{name: 'touched-a-pdf-file'}, {name: 'manually-added'}]
}
});

await run();

expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(removeLabelMock).toHaveBeenCalledTimes(0);
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});

it('(with sync-labels: false) it only logs the excess labels', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': false
});

usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');

const existingLabels = Array.from({length: 100}).map((_, idx) => ({
name: `existing-label-${idx}`
}));
getPullMock.mockResolvedValue(<any>{
data: {
labels: existingLabels
}
});

await run();

expect(setLabelsMock).toHaveBeenCalledTimes(0);

expect(coreWarningMock).toHaveBeenCalledTimes(1);
expect(coreWarningMock).toHaveBeenCalledWith(
'Maximum of 100 labels allowed. Excess labels: touched-a-pdf-file',
{title: 'Label limit for a PR exceeded'}
);
});
});

Expand Down

0 comments on commit 7a202e6

Please sign in to comment.