Skip to content

Commit 62f007c

Browse files
hemerocbbugh
andauthored
feat: Add boolean option for payload filter (#593)
* Add boolean filter for payload (no tests) * Add tests * Update changelog * Remove boolean filter option from validator and allow it only on filters. Co-authored-by: Brian Bugh <438465+bbugh@users.noreply.github.com>
1 parent 455a516 commit 62f007c

File tree

9 files changed

+197
-2
lines changed

9 files changed

+197
-2
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const BooleanMatch = require('../../../../../lib/filters/options_processor/options/boolean')
2+
3+
const filterContext = undefined
4+
5+
const filter = {
6+
name: 'payload',
7+
supportedOptions: [
8+
'boolean',
9+
'must_exclude',
10+
'must_include']
11+
}
12+
13+
const verify = (match, input, result) => {
14+
const rule = { boolean: { match } }
15+
const res = BooleanMatch.process(filterContext, filter, input, rule)
16+
expect(res.status).toBe(result)
17+
return res
18+
}
19+
20+
test('return pass if input is a string that meets the criteria', () => {
21+
verify(true, 'true', 'pass')
22+
verify(false, 'false', 'pass')
23+
})
24+
25+
test('return pass if input is a boolean that meets the criteria', () => {
26+
verify(true, true, 'pass')
27+
verify(false, false, 'pass')
28+
})
29+
30+
test('return fail if input does not meet the criteria', () => {
31+
verify(true, false, 'fail')
32+
verify(false, 'true', 'fail')
33+
})
34+
35+
test('return error if inputs are not in expected format', async () => {
36+
const rule = { boolean: { match: true } }
37+
const input = ['true']
38+
try {
39+
const config = BooleanMatch.process(filterContext, filter, input, rule)
40+
expect(config).toBeUndefined()
41+
} catch (e) {
42+
expect(e.message).toBe('Input type invalid, expected strings "true" or "false", or boolean literal `true` or `false` as input')
43+
}
44+
})

__tests__/unit/filters/payload.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,37 @@ test('that proper errors are returned if a key is required but not provided in m
247247
const filter = await payload.processFilter(context, settings)
248248
expect(filter.status).toBe('error')
249249
})
250+
251+
test('that boolean checks succeed', async () => {
252+
const payload = new Payload()
253+
254+
const settings = {
255+
do: 'payload',
256+
pull_request: {
257+
draft: {
258+
boolean: {
259+
match: true
260+
}
261+
}
262+
}
263+
}
264+
265+
const context = {
266+
payload: {
267+
repository: {
268+
full_name: 'test-repo'
269+
},
270+
pull_request: {
271+
draft: true
272+
}
273+
}
274+
}
275+
276+
let filter = await payload.processFilter(context, settings)
277+
expect(filter.status).toBe('pass')
278+
279+
context.payload.pull_request.draft = false
280+
281+
filter = await payload.processFilter(context, settings)
282+
expect(filter.status).toBe('fail')
283+
})

docs/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
CHANGELOG
22
=====================================
3+
| October 12, 2021 : feat: Add boolean option for payload filter `#583 <https://github.com/mergeability/mergeable/pull/583>`_
34
| September 27, 2021 : fix: use node version 14.17.6 for the release action `#591 <https://github.com/mergeability/mergeable/pull/591>`_
45
| September 25, 2021 : feat: Support for objects in arrays in the payload filter `#589 <https://github.com/mergeability/mergeable/pull/589>`_
56
| September 20, 2021 : fix: Check that getRouter is defined before attempting to access it `#587 <https://github.com/mergeability/mergeable/pull/587>`_

docs/configuration.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ These Options are used with validators.
138138
Options List
139139

140140
.. toctree::
141+
options/boolean.rst
141142
options/begins_with.rst
142143
options/ends_with.rst
143144
options/jira.rst

docs/filters/payload.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Payload
22
^^^^^^^^^^^^^^
33

4-
Check against any available fields within the payload, each event can have different field, please refer to `github API documentation for <https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads>`_ for available fields.
4+
Check against any available fields within the payload, each event can have different field, please refer to `github API documentation<https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads>`_ for available fields.
55

66
An example to check if a pull_request_review event has `state` of `changes_requested`
77

@@ -13,6 +13,15 @@ An example to check if a pull_request_review event has `state` of `changes_reque
1313
must_include:
1414
regex: 'changes_requested'
1515

16+
To check if a `pull_request` event is not a `draft`
17+
18+
::
19+
20+
- do: payload
21+
pull_request:
22+
draft:
23+
boolean:
24+
match: false
1625

1726
An example to check if a pull_request event has a `label` named `foo`
1827

@@ -30,6 +39,8 @@ Each field must be checked using one of the following options
3039

3140
::
3241

42+
boolean:
43+
match: true/false
3344
must_include:
3445
regex: 'This text must be included'
3546
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'

docs/options/boolean.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
Boolean
2+
^^^^^^^
3+
4+
``boolean`` can be used to validate if the input is exactly `true` or `false`. This does not pass truthy values.
5+
6+
For example, if the `pull_request.draft` value is `false`:
7+
8+
::
9+
10+
{
11+
"action": "opened",
12+
"number": 2,
13+
"pull_request": {
14+
"draft": false
15+
16+
This will pass validation, because the value of `draft` exactly matches `false`:
17+
18+
::
19+
20+
- do: payload
21+
pull_request:
22+
draft:
23+
boolean:
24+
match: false
25+
message: 'Custom message...' # this is optional, a default message is used when not specified.
26+
27+
28+
.. list-table:: Supported Params
29+
:widths: 25 50 25 25
30+
:header-rows: 1
31+
32+
* - Param
33+
- Description
34+
- Required
35+
- Default Message
36+
* - match
37+
- Bool value to check for
38+
- Yes
39+
-
40+
* - message
41+
- Message to show if the validation fails
42+
- No
43+
- The [INPUT NAME] must be [match]
44+
45+
Supported Filters:
46+
::
47+
48+
'payload'

docs/recipes.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,29 @@ Add 2 checks to the PR
200200
- do: title
201201
begins_with:
202202
match: [ 'some prefix' ]
203+
204+
205+
Only run rules if PR is not a draft
206+
"""""""""""""""""""""""
207+
Checks that the PR's draft state is false before running actions.
208+
209+
::
210+
211+
version: 2
212+
mergeable:
213+
- when: pull_request.*, pull_request_review.*
214+
name: 'Draft check'
215+
validate:
216+
- do: payload
217+
pull_request:
218+
draft:
219+
boolean:
220+
match: false
221+
pass:
222+
- do: comment
223+
payload:
224+
body: This PR is NOT a draft!
225+
fail:
226+
- do: comment
227+
payload:
228+
body: This PR is STILL a draft!
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const MATCH_NOT_FOUND_ERROR = 'Failed to run the test because \'match\' is not provided for \'boolean\' option. Please check README for more information about configuration'
2+
const UNKNOWN_INPUT_TYPE_ERROR = 'Input type invalid, expected strings "true" or "false", or boolean literal `true` or `false` as input'
3+
4+
class BooleanMatch {
5+
static process (context, filter, input, rule) {
6+
const match = rule.boolean.match
7+
8+
if (match == null) {
9+
throw new Error(MATCH_NOT_FOUND_ERROR)
10+
}
11+
12+
if (input !== 'true' && input !== 'false' && typeof input !== 'boolean') {
13+
throw new Error(UNKNOWN_INPUT_TYPE_ERROR)
14+
}
15+
16+
let description = rule.boolean.message
17+
if (!description) description = `The ${filter.name} must be ${match}`
18+
19+
const DEFAULT_SUCCESS_MESSAGE = `The ${filter.name} is ${match}`
20+
21+
const isMergeable = input.toString() === match.toString()
22+
23+
return {
24+
status: isMergeable ? 'pass' : 'fail',
25+
description: isMergeable ? DEFAULT_SUCCESS_MESSAGE : description
26+
}
27+
}
28+
}
29+
30+
module.exports = BooleanMatch

lib/filters/payload.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const constructError = require('./options_processor/options/lib/constructError')
44
const _ = require('lodash')
55
const { forEach } = require('p-iteration')
66

7-
const options = ['must_include', 'must_exclude']
7+
const options = ['boolean', 'must_include', 'must_exclude']
88

99
async function recursveThruFields (filterObj, currentPath, output, payload, field) {
1010
await forEach(Object.keys(field), async key => {

0 commit comments

Comments
 (0)