@shine2lay/test-npm v0.0.4
π€ 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
Usage
- 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 - (Optional) You can also create a default configuration for an organisation by
creating a repo called
.githuband adding your file there. See Organisation wide defaults for details.
β NOTE: You can also deploy to your own server.
Configuration
Mergeable is highly configurable.
Define your recipes by creating a .github/mergeable.yml file in your repository.
Basics
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
Events are specified in the when tag like this:
- when: pull_request.openedMultiple events for a recipe are declared comma delimited like this:
- when: pull_request.opened, issues.openedEvents 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
validatorandactiondeclares it's own supported events. Read the validator and action sections to find out which events are supported respectively.
Validators
approvals
- 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 # Optional boolean. When true, the file .github/CODEOWNER is read and owners made required reviewers
assignees: true # Optional boolean. When true, PR assignees are made required reviewers.
pending_reviewer: true # Optional boolean. When true, all the requested reviewer's approval is required
message: 'Custom message...'
block:
changes_requested: true #If true, block all approvals when one of the reviewers gave 'changes_requested' review
message: 'Custom message...'β NOTE:
ownerssub-option only works in public repos right now, we have plans to enable it for private repos in the future.
Supported events:
'pull_request.*', 'pull_request_review.*'assignee
- 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 optionalSupported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'dependent
dependent validates that the files specified are all part of a pull request (added or modified).
- do: dependent
files: ['package.json', 'yarn.lock'] # list of files that are dependent on one another and must all be part of the changes in a PR.
message: 'Custom message...' # this is optional, a default message is used when not specified.Alternatively, to validate dependent files only when a specific file is part of the pull request, use the changed option:
- do: dependent
changed:
file: package.json
files: ['package-lock.json', 'yarn.lock']
message: 'Custom message...' # this is optional, a default message is used when not specified.The above will validate that both the files package-lock.json and yarn.lock is part of the modified or added files if and only if package.json is part of the PR.
Size
size validates that the size of changes in the pull request conform to a
specified limit. We can pass in three options: total, additions or deletions. Each of this take in a count and message.
- do: size
lines:
total:
count: 500
message: Change is very large. Should be under 500 lines of additions and deletions.
additions:
count: 250
message: Change is very large. Should be under 250 lines of additions
deletions:
count: 500
message: Change is very large. Should be under 250 lines of deletions.max is an alias for total, so the below configuration is still valid.
- do: size
lines:
max:
count: 500
message: Change is very large. Should be under 500 lines of additions and deletions.It also supports an ignore setting to allow excluding certain files from the
total size (e.g. for ignoring automatically generated files that increase the
size a lot).
This option supports glob patterns, so you can provide either the path to a specific file or ignore whole patterns:
- do: size
ignore: ['package-lock.json', 'src/tests/__snapshots__/**', 'docs/*.md']
lines:
total:
count: 500
message: Change is very large. Should be under 500 lines of additions and deletionsNote that the glob functionality is powered by the minimatch library. Please see their documentation for details on how glob patterns are handled and possible discrepancies with glob handling in other tools.
The size validator currently excludes from the size count any files that were
completely deleted in the PR.
Supported events
'pull_request.*', 'pull_request_review.*'description
- 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'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
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'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
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...' # optionalSupported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'label
- do: label
no_empty:
enabled: false # Cannot be empty when true.
message: 'Custom message...'
must_include:
regex: 'type|chore|wont'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
message: 'Custom message...'
must_exclude:
regex: 'DO NOT MERGE'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
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 optionalSupported events:
'pull_request.*', 'pull_request_review.*', 'issues.*'Change Set
- do: changeset # validate against the files in the PR
no_empty:
enabled: false # Cannot be empty when true.
message: 'Custom message...'
must_include:
regex: 'yarn.lock'
message: 'Custom message...'
must_exclude:
regex: 'package.json'
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...'
min:
count: 2 # min number of files in a PR
message: 'Custom message...'
max:
count: 2 # max number of files in a PR
message: 'Custom message...'
# all of the message sub-option is optionalSupported events:
'pull_request.*', 'pull_request_review.*'milestone
- do: milestone
no_empty:
enabled: true # Cannot be empty when true.
message: 'Custom message...'
must_include:
regex: 'type|chore|wont'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
message: 'Custom message...'
must_exclude:
regex: 'DO NOT MERGE'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
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.*'project
- do: project
must_include:
regex: 'type|chore|wont'
message: 'Custom message...'β 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.*'stale
- 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 Β»
title
- 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'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
message: 'Custom message...'
must_exclude:
regex: 'DO NOT MERGE|WIP'
regex_flag: 'none' # Optional. Specify the flag for Regex. default is 'i', to disable default use 'none'
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 optionalcommit
- do: commit
message:
regex: '^(feat|docs|chore|fix|refactor|test|style|perf)(\(\w+\))?:.+$'
message: 'Custom message' # Semantic release conventions must be followed
skip_merge: true # Optional, Default is true. Will skip commit with message that includes 'Merge'
oldest_only: false # Optional, Default is false. Only check the regex against the oldest commit
single_commit_only: false # Optional, Default is false. only process this validator if there is one commitSupported events:
'pull_request.*', 'pull_request_review.*'Advanced Logic
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'AND and OR can also be used at the validator level:
- do: or
validate:
- 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'
- do: label
must_include:
regex: 'test plan: no'
message: 'If no test plan is necessary, please include test plan: no label'similarly, AND and OR can also be nested at the validator level:
- do: or
validate:
- do: and
validate:
- do: description
must_include:
regex: 'Test plan'
message: 'Test plan must be included'
- do: title
must_exclude:
regex: 'WIP'
message: 'PR should not be in WIP'
- do: label
must_include:
regex: 'test plan: no'
message: 'If no test plan is necessary, please include test plan: no label'To reuse certain parts of the config, you can utilize anchor points that yaml provides (link), like this
- do: title
must_include: ®ex_semantic
regex: '^(build|chore|ci|docs|feat|fix|improvement|perf|refactor|revert|style|test)(\([a-z0-9_-]+\))?: [^\s].+$'
regex_flag: 'none'
- do: commit
message: *regex_semanticActions
Actions are listed for execution at the pass, fail and error tags for a recipe based on the results of the validation.
comment
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.*'assign
- do: assign
assignees: [ 'shine2lay', 'jusx' ] # only array acceptedSupported events:
'pull_request.*', 'issues.*'Labels
Creates comments in issues and/or pull requests depending on the event specified in the when tag.
- do: labels
# if label doesn't exist, it'll be created
labels: [ 'Triage' ] # Only arrays are acceptedSupported events:
'schedule.repository', 'pull_request.*', 'issues.*'checks
Note: Some default cases do exists for pass, fail and error cases but if you provide these cases, the defaults will be overwritten
- do: checks # default pass case
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 returned 'pass'! \n Here are some stats of the run: \n {{validationCount}} validations were ran"You can pass in Handlebars template to show the details result of the run.
- do: checks # default fail case
status: 'failure' # Can be: success, failure, neutral, cancelled, timed_out, or action_required
payload:
title: 'Mergeable Run have been Completed!'
summary: |
### Status: {{toUpperCase validationStatus}}
Here are some stats of the run:
{{validationCount}} validations were ran.
{{passCount}} PASSED
{{failCount}} FAILED
text: "{{#each validationSuites}}\n
#### {{{statusIcon status}}} Validator: {{toUpperCase name}}\n
{{#each validations }} * {{{statusIcon status}}} ***{{{ description }}}***\n
Input : {{{details.input}}}\n
Settings : {{{displaySettings details.settings}}}\n
{{/each}}\n
{{/each}}"Supported events:
'pull_request.*', 'pull_request_review.*'request_review
Creates comments in issues and/or pull requests depending on the event specified in the when tag.
- do: request_review
reviewers: ['name1', 'name2']This is only enforced for reviewers who has not been requested already
Note: The reviewers must be collaborator, otherwise, github api will throw error
Supported events:
'pull_request.*'close
Close an Issue or Pull Request
- do: closeSupported events:
'pull_request.*', 'issues.*'Examples
Pull Requests
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.
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.
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 and package-lock.json)
version: 2
mergeable:
- when: pull_request.*
validate:
- do: dependent
changed:
file: 'package.json' # also supports globs expressions
required: ['package-lock.json', 'yarn.lock'] # alias: `files` for backward compatibilityMilestone: 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.
version: 2
mergeable:
- when: pull_request.*
validate:
- do: milestone
must_include:
regex: Release 1Size: Ensure that PRs don't exceed a certain size in terms of lines changed
(excluding file patterns specified with ignore).
version: 2
mergeable:
- when: pull_request.*
validate:
- do: size
ignore: ['ignore_me.js', 'ignore_this_directory/*', '**/ignore_this_prefix*.js']
lines:
max:
count: 500
message: Change is very large. Should be under 500 lines of addtions and deletions.version: 2
mergeable:
- when: pull_request.*
validate:
- do: project
must_include:
regex: MVPRead the configuration options for more options.
Issues
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.
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.
Staleness
Detect issues and pull requests that are n days old (stale) and notify authors and collaborators by creating a comment.
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?Organisation-wide defaults
You can specify a default configuration to be applied across your GitHub organisation. This can help reduce how many configuration files you need to maintain and make it easier to get started with Mergeable.
To add a default configuration:
- Create a repository called
.githubin your organisation. - Create a file with the path
.github/mergeable.ymlin this repository.
The final path of the file (including the repo name) should be <YOUR_ORG>/.github/.github/mergeable.yml
Mergeable will now use this file as the default when it cannot find one in a given repository or PR. It determines the file to use in the following order:
- A
mergeable.ymlinside the PR. - A
mergeable.ymlinside the repository the PR is for. - A
mergeable.ymlat<YOUR_ORG>/.github/.github/mergeable.yml.
Note: Mergeable will only ever use a single file. It does not merge files.
Why the weird default file path?
The Probots library that Mergeable uses automatically searches for config files
in a repo named .github within the organisation.
The double nesting of the <YOUR_ORG>/.github/.github/mergeable.yml default
file is unfortunately necessary. The GitHub app permissions model only lets you
specify a single path for your probot to access, so it must be the same as in
regular repositories.
Roadmap
- Additional actions like
labelandassign - Potentially, integration with external tools like pivotal tracker, slack and trello.
- More likely coveralls or sonarqube.
Support
Found a bug? Have a question? Or just want to chat?
Contributions
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.
Authors
- 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