Skip to content

Commit

Permalink
feat: Add team option to author filter (#696)
Browse files Browse the repository at this point in the history
Co-authored-by: Shine Lee <aungshine@gmail.com>
  • Loading branch information
robinmayerhofer and shine2lay authored Feb 20, 2023
1 parent a1d02ab commit 903d5e8
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 10 deletions.
85 changes: 77 additions & 8 deletions __tests__/unit/filters/author.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
const Author = require('../../../lib/filters/author')
const Helper = require('../../../__fixtures__/unit/helper')
const Teams = require('../../../lib/validators/options_processor/teams')

const authorName = 'mergeabletestauthorname'
const otherAuthorName = 'someone-else'

test('should fail with unexpected author', async () => {
const author = new Author()
const settings = {
do: 'author',
must_include: {
regex: 'someone-else'
regex: otherAuthorName
}
}
const filter = await author.processFilter(createMockContext('mergeable'), settings)
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('fail')
})

Expand All @@ -18,10 +22,10 @@ test('should pass with expected author', async () => {
const settings = {
do: 'author',
must_include: {
regex: 'mergeable'
regex: authorName
}
}
const filter = await author.processFilter(createMockContext('mergeable'), settings)
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('pass')
})

Expand All @@ -30,10 +34,10 @@ test('should fail with excluded author', async () => {
const settings = {
do: 'author',
must_exclude: {
regex: 'mergeable'
regex: authorName
}
}
const filter = await author.processFilter(createMockContext('mergeable'), settings)
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('fail')
})

Expand All @@ -42,13 +46,78 @@ test('should pass with excluded author', async () => {
const settings = {
do: 'author',
must_exclude: {
regex: 'someone-else'
regex: otherAuthorName
}
}
const filter = await author.processFilter(createMockContext('mergeable'), settings)
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('pass')
})

test('should pass with expected author from correct team', async () => {
const author = new Author()
const settings = {
do: 'author',
must_include: {
regex: authorName
},
team: 'org/team-slug'
}
Teams.extractTeamMemberships = jest.fn().mockReturnValue([authorName])
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('pass')
})

test('should fail with expected author from incorrect team', async () => {
const author = new Author()
const settings = {
do: 'author',
must_include: {
regex: authorName
},
team: 'org/team-slug'
}
Teams.extractTeamMemberships = jest.fn().mockReturnValue([])
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('fail')
})

test('should fail with unexpected author from correct team', async () => {
const author = new Author()
const settings = {
do: 'author',
must_include: {
regex: otherAuthorName
},
team: 'org/team-slug'
}
Teams.extractTeamMemberships = jest.fn().mockReturnValue([authorName])
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('fail')
})

test('should pass when the author is a member of the team', async () => {
const author = new Author()
const settings = {
do: 'author',
team: 'org/team-slug'
}
Teams.extractTeamMemberships = jest.fn().mockReturnValue([authorName])
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('pass')
})

test('should fail when the author is not a member of the team', async () => {
const author = new Author()
const authorName = 'mergeable'
const settings = {
do: 'author',
team: 'org/team-slug'
}
Teams.extractTeamMemberships = jest.fn().mockReturnValue([otherAuthorName])
const filter = await author.processFilter(createMockContext(authorName), settings)
expect(filter.status).toBe('fail')
})

const createMockContext = (author) => {
return Helper.mockContext({ author })
}
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
CHANGELOG
=====================================
| February 03, 2023: feat: Add team option to author filter `#696 <https://github.com/mergeability/mergeable/pull/696>`_
| February 3, 2023: chore: Update node version for release workflow `#699 <https://github.com/mergeability/mergeable/pull/699>`_
| February 3, 2023: feat: Add Not operator `#695 <https://github.com/mergeability/mergeable/pull/695>`_
| September 28, 2022: feat: Add last comment validator `#668 <https://github.com/mergeability/mergeable/pull/668>`_
Expand Down
6 changes: 5 additions & 1 deletion docs/filters/author.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ Author
- do: author
must_include:
regex: 'user-1'
message: 'Custom message...'
message: 'Custom include message...'
must_exclude:
regex: 'user-2'
message: 'Custom exclude message...'
team: 'org/team-slug' # verify that the author is in the team
# all of the message sub-option is optional

you can use ``and`` and ``or`` options to create more complex filters
Expand Down
3 changes: 2 additions & 1 deletion lib/filters/author.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class Author extends Filter {
regex: 'string',
regex_flag: 'string',
message: 'string'
}
},
team: 'string'
}
}

Expand Down
21 changes: 21 additions & 0 deletions lib/filters/options_processor/options/team.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const Teams = require('../../../validators/options_processor/teams')

class TeamProcessor {
static async process (context, filter, input, rule) {
const userName = input
const teamName = rule.team

const SUCCESS_MESSAGE = `'${userName}' is part of the '${teamName}' team'`
const FAILURE_MESSAGE = `'${userName}' is not part of the '${teamName}' team'`

const teamMemberships = await Teams.extractTeamMemberships(context, [teamName], [userName])
const isMember = teamMemberships.includes(userName)

return {
status: isMember ? 'pass' : 'fail',
description: isMember ? SUCCESS_MESSAGE : FAILURE_MESSAGE
}
}
}

module.exports = TeamProcessor

0 comments on commit 903d5e8

Please sign in to comment.