π€ Mergeable helps automate your team's GitHub workflow without a single line of code.
Some examples of what you can do:
- Ensure pull requests follow conventions and prevent merging when it is not followed.
- Notify author of failed guidelines when opening an issue.
- Schedule detection for obsolete (stale) issues and pull requests and notify author and collaborators.
- And more
π Contents: Usage β¦ Configuration β¦ Roadmap β¦ Support β¦ Contributions β¦ Authors
- Install the Mergeable GitHub App.
- Create your recipe(s). Here are some examples.
- Commit and push the recipes to your repository at
.github/mergeable.yml
β NOTE: You can also deploy to your own server.
Mergeable is highly configurable.
Define your recipes by creating a .github/mergeable.yml
file in your repository.
The configuration consists of any number of recipes. Recipes are created by tying events with a set of validators and actions together:
version: 2
mergeable:
- when: {{event}}, {{event}} # can be one or more
validate:
# list of validators. Specify one or more.
- do: {{validator}}
{{option}}: # name of an option supported by the validator.
{{sub-option}}: {{value}} # an option will have one or more sub-options.
pass: # list of actions to be executed if all validation passes. Specify one or more. Omit this tag if no actions are needed.
- do: {{action}}
fail: # list of actions to be executed when at least one validation fails. Specify one or more. Omit this tag if no actions are needed.
- do: {{action}}
error: # list of actions to be executed when at least one validator throws an error. Specify one or more. Omit this tag if no actions are needed.
- do: {{action}}
Take a look at some example recipes.
β NOTE: Earlier versions used a different set of convention. It will be supported in the foreseeable future but will eventually be phased out.
Events are specified in the when
tag like this:
- when: pull_request.opened
Multiple events for a recipe are declared comma delimited like this:
- when: pull_request.opened, issues.opened
Events supported for pull requests are as follows:
pull_request.opened
, pull_request.edited
, pull_request_review.submitted
, pull_request_review.edited
, pull_request_review.dismissed
, pull_request.labeled
, pull_request.unlabeled
, pull_request.milestoned
, pull_request.demilestoned
, pull_request.assigned
, pull_request.unassigned
, pull_request.synchronize
,
And for issues:
issues.opened
, issues.edited
, issues.labeled
, issues.unlabeled
, issues.milestoned
, issues.demilestoned
, issues.assigned
, issues.unassigned
, issues.synchronize
β NOTE: More details about events can be found on the GitHub events page.
For convenience, wildcards can be used: pull_request.*
, issues.*
, pull_request_review.*
β NOTE: Each
validator
andaction
declares it's own supported events. Read the validator and action sections to find out which events are supported respectively.
- do: approvals
min:
count: 2 # Number of minimum reviewers. In this case 2.
message: 'Custom message...'
required:
reviewers: [ user1, user2 ] # list of github usernames required to review
owners: true # accepts boolean. When true, the file .github/CODEOWNER is read and owners made required reviewers
message: 'Custom message...'
Supported events:
'pull_request.*', 'pull_request_review.*'
- do: assignee
max:
count: 2 # There should not be more than 2 assignees
message: 'test string' # this is optional
min:
count: 2 # min number of assignees
message: 'test string' # this is optional
Supported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'
- do: dependent
files: ['package.json', 'yarn.lock'] # list of files that are dependent to one another and must all be together part of the added or modified file list in a PR.
message: 'Custom message...' # this is optional, a default message is used when not specified.
Supported events:
'pull_request.*', 'pull_request_review.*'
- do: description
no_empty:
enabled: false # Cannot be empty when true.
message: 'Custom message...' # this is optional, a default message is used when not specified.
must_include:
regex: '### Goals|### Changes'
message: >
Please describe the goals (why) and changes (what) of the PR.
# message is is optional, a default message is used when not specified.
must_exclude:
regex: 'DO NOT MERGE'
message: 'Custom message...' # optional
begins_with:
match: '### Goals' # or array of strings
message: 'Some message...' #optional
ends_with:
match: 'Any last sentence' # array of strings
message: 'Come message...' # optional
Supported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'
- do: label
no_empty:
enabled: false # Cannot be empty when true.
message: 'Custom message...'
must_include:
regex: 'type|chore|wont'
message: 'Custom message...'
must_exclude:
regex: 'DO NOT MERGE'
message: 'Custom message...'
begins_with:
match: 'A String' # or array of strings
message: 'Some message...'
ends_with:
match: 'A String' # or array of strings
message: 'Come message...'
# all of the message sub-option is optional
Supported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'
- do: milestone
no_empty:
enabled: true # Cannot be empty when true.
message: 'Custom message...'
must_include:
regex: 'type|chore|wont'
message: 'Custom message...'
must_exclude:
regex: 'DO NOT MERGE'
message: 'Custom message...'
begins_with:
match: 'A String' # array of strings
message: 'Some message...'
ends_with:
match: 'A String' # array list of strings
message: 'Come message...'
# all of the message sub-option is optional
β NOTE: When a closing keyword is used in the description of a pull request. The annotated issue will be validated against the conditions as well.
Supported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'
- do: project
no_empty:
enabled: true # Cannot be empty when true.
message: 'Custom message...'
must_include:
regex: 'type|chore|wont'
message: 'Custom message...'
must_exclude:
regex: 'DO NOT MERGE'
message: 'Custom message...'
begins_with:
match: 'A String' # array of strings
message: 'Some message...'
ends_with:
match: 'A String' # array of strings
message: 'Come message...'
# all of the message sub-option is optional
β NOTE: When a closing keyword is used in the description of a pull request. The annotated issue will be validated against the conditions as well.
Supported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'
- do: stale
days: 20 # number of days ago.
type: pull_request, issues # what items to search for.
Supported events:
'schedule.repository'
β NOTE: This is a special use case. The schedule event runs on an interval. When used with
stale
, it will search for issues and/or pull request that are n days old. See a full example Β»
- do: title
no_empty:
enabled: true # Cannot be empty when true. A bit redundant in this case since GitHub don't really allow it. :-)
message: 'Custom message...'
must_include:
regex: 'doc|feat|fix|chore'
message: 'Custom message...'
must_exclude:
regex: 'DO NOT MERGE|WIP'
message: 'Custom message...'
begins_with:
match: ['doc','feat','fix','chore']
message: 'Some message...'
ends_with:
match: 'A String' # or array of strings
message: 'Come message...'
# all of the message sub-option is optional
Validators can be grouped together with AND
and OR
operators:
- do: description
and:
- must_include:
regex: 'Test Plan'
message: 'Test plan must be included'
- must_include:
regex: 'Goal'
message: 'Please include the goal of the PR'
AND
and OR
operators can also be nested
- do: label
or:
- and:
- must_include:
regex: 'release notes: yes'
message: 'Please include release note: yes'
- must_include:
regex: '^lang\/'
message: 'Please include a language label'
- must_include:
regex: 'release notes: no'
message: 'Please include release note: no'
Note : AND
and OR
are not validators
Actions are listed for execution at the pass
, fail
and error
tags for a recipe based on the results of the validation.
Creates comments in issues and/or pull requests depending on the event specified in the when
tag.
- do: comment
payload:
body: >
Your very long comment can go here.
Supported events:
'schedule.repository', 'pull_request.*', 'issues.*'
- do: checks,
status: 'success' # Can be: success, failure, neutral, cancelled, timed_out, or action_required
payload:
title: 'Mergeable Run have been Completed!'
summary: `All the validators have return 'pass'! \n Here are some stats of the run: \n {{validationCount}} validations were ran`
Supported events:
'pull_request.*', 'pull_request_review.*'
Validate pull requests for mergeability based on content and structure of your PR (title, labels, milestone, project, description, approvals, etc). Here are a few examples:
Work In Progress: Prevent accidental merging of Pull Requests that are work in progress by labeling it WIP
or prefixing the title with the abbreviation.
π See Recipe
version: 2
mergeable:
- when: pull_request.*
validate:
- do: title
must_exclude:
regex: ^\[WIP\]
- do: label
must_exclude:
regex: 'wip'
Description: Ensure all Pull Requests have a description so that reviewers have context.
π See Recipe
version: 2
mergeable:
- when: pull_request.*
validate:
- do: description
no_empty:
enabled: true
message: Description matter and should not be empty. Provide detail with **what** was changed, **why** it was changed, and **how** it was changed.
Dependent Files: Certain files are related and you want to ensure that they are updated as part of the PR (i.e. if package.json
is updated, so should yarn.lock
)
π See Recipe
version: 2
mergeable:
- when: pull_request.*
validate:
- do: dependent
files: ['package.json', 'yarn.lock']
Milestone: Ensure that all Pull Requests have a milestone associated. Mergeable will also detect when you are closing an issue that is associated with the specified milestone.
π See Recipe
version: 2
mergeable:
- when: pull_request.*
validate:
- do: milestone
must_include:
regex: Release 1
Read the configuration options for more options.
Automatically create a comment when a new issue is openened
to remind the author when the title does not follow conventions or is missing a label.
π See Recipe
version: 2
mergeable:
- when: issues.opened
validate:
- do: title
begins_with:
match: ['AUTH', 'SOCIAL', 'CORE']
- do: label
must_include:
regex: bug|enhancement
fail:
- do: comment
payload:
body: >
The following problems were found with this issue:
- Title must begin with `AUTH`, `SOCIAL` or `CORE`
- The issue should either be labeled `bug` or `enhancement`
Read the configuration options for more options.
Detect issues and pull requests that are n
days old (stale) and notify authors and collaborators by creating a comment.
π See Recipe
version: 2
mergeable:
- when: schedule.repository
validate:
- do: stale
days: 20
type: pull_request, issues
pass:
- do: comment
payload:
body: This is old. Is it still relevant?
- Additional actions like
label
andassign
- Potentially, integration with external tools like pivotal tracker, slack and trello.
- More likely coveralls or sonarqube.
- Able to prevent merging based on the size of pull request.
Found a bug? Have a question? Or just want to chat?
We need your help:
- Have an π‘idea for a new feature? Please create a new issue and tell us!
- Fix a bug, implement a new validator or action and open a pull request!
βοΈ NOTE: For development and testing. You'll want to read about how to run it locally.
- Originally created by @jusx π follow him on Twitter.
- Co-authored by @shine2lay
- Logo by @minap0lis π follow her on Instagram.
AGPL, Copyright (c) 2019 Justin Law & Shine Lee