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

feat: add label filter to reduce scope of action #14

Merged
merged 7 commits into from
Feb 4, 2020
Merged
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,20 @@ Add the PR creator as assignee to the pull request.
addAssignees: author
```

### Filter by label
The action will only run if the PR meets the specified filters

```yaml
filterLabels:
# Run
include:
- my_label
- another_label
# Not run
exclude:
- wip

```

## :memo: Licence
MIT
70 changes: 70 additions & 0 deletions __tests__/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('handlePullRequest', () => {
number: '1',
pull_request: {
number: 1,
labels: [],
title: 'test',
user: {
login: 'pr-creator',
Expand Down Expand Up @@ -822,4 +823,73 @@ describe('handlePullRequest', () => {
/group3-reviewer/
)
})

test('skips pull requests that do not have any of the filterLabels.include labels', async () => {
const spy = jest.spyOn(core, 'info')

const client = new github.GitHub('token')
const config = {
filterLabels: { include: ['test_label'] },
} as any

context.payload.pull_request.labels = [{ name: 'some_label' }]

await handler.handlePullRequest(client, context, config)

expect(spy.mock.calls[0][0]).toEqual(
'Skips the process to add reviewers/assignees since PR is not tagged with any of the filterLabels.include'
)
})

test('skips pull requests that have any of the filterLabels.exclude labels', async () => {
const spy = jest.spyOn(core, 'info')

const client = new github.GitHub('token')
const config = {
filterLabels: { include: ['test_label'], exclude: ['wip'] },
} as any

context.payload.pull_request.labels = [
{ name: 'test_label' },
{ name: 'wip' },
]

await handler.handlePullRequest(client, context, config)

expect(spy.mock.calls[0][0]).toEqual(
'Skips the process to add reviewers/assignees since PR is tagged with any of the filterLabels.exclude'
)
})

test('adds reviewers to the pull request when it has any of the configured labels', async () => {
const config = {
addAssignees: false,
addReviewers: true,
filterLabels: { include: ['some_label', 'another_label'] },
numberOfReviewers: 0,
reviewers: ['reviewer1', 'reviewer2', 'reviewer3', 'pr-creator'],
} as any

const client = new github.GitHub('token')

context.payload.pull_request.labels = [{ name: 'some_label' }]

client.pulls = {
createReviewRequest: jest.fn().mockImplementation(async () => {}),
} as any

const addAssigneesSpy = jest.spyOn(client.issues, 'addAssignees')
const createReviewRequestSpy = jest.spyOn(
client.pulls,
'createReviewRequest'
)

await handler.handlePullRequest(client, context, config)

expect(addAssigneesSpy).not.toBeCalled()
expect(createReviewRequestSpy.mock.calls[0][0].reviewers).toHaveLength(3)
expect(createReviewRequestSpy.mock.calls[0][0].reviewers[0]).toMatch(
/reviewer/
)
})
})
27 changes: 27 additions & 0 deletions src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export interface Config {
addAssignees: boolean | string
reviewers: string[]
assignees: string[]
filterLabels?: {
include?: string[]
exclude?: string[]
}
numberOfAssignees: number
numberOfReviewers: number
skipKeywords: string[]
Expand Down Expand Up @@ -36,6 +40,7 @@ export async function handlePullRequest(
assigneeGroups,
addReviewers,
addAssignees,
filterLabels,
} = config

if (skipKeywords && utils.includesSkipKeywords(title, skipKeywords)) {
Expand Down Expand Up @@ -66,6 +71,28 @@ export async function handlePullRequest(
const owner = user.login
const pr = new PullRequest(client, context)

if (filterLabels !== undefined) {
if (filterLabels.include !== undefined && filterLabels.include.length > 0) {
const hasLabels = pr.hasAnyLabel(filterLabels.include)
if (!hasLabels) {
core.info(
'Skips the process to add reviewers/assignees since PR is not tagged with any of the filterLabels.include'
)
return
}
}

if (filterLabels.exclude !== undefined && filterLabels.exclude.length > 0) {
const hasLabels = pr.hasAnyLabel(filterLabels.exclude)
if (hasLabels) {
core.info(
'Skips the process to add reviewers/assignees since PR is tagged with any of the filterLabels.exclude'
)
return
}
}
}

if (addReviewers) {
try {
const reviewers = utils.chooseReviewers(owner, config)
Expand Down
8 changes: 8 additions & 0 deletions src/pull_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,12 @@ export class PullRequest {
})
core.debug(JSON.stringify(result))
}

hasAnyLabel(labels: string[]): boolean {
if (!this.context.payload.pull_request) {
return false
}
const { labels: pullRequestLabels = [] } = this.context.payload.pull_request
return pullRequestLabels.some(label => labels.includes(label.name))
}
}