Skip to content
πŸ€– All the missing GitHub automation πŸ™‚ πŸ™Œ
JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci
.github
__fixtures__
__tests__
docs
lib Merge branch 'master' into seperate-pr-size-types Sep 5, 2019
.env.template
.gitignore
LICENSE
_config.yml
index.js
mergeable.png
package.json
screenshot.gif

README.md


Mergeable

Mergeable

Free Install

πŸ€– Mergeable helps automate your team's GitHub workflow without a single line of code.

Some examples of what you can do:


πŸ“– Contents: Usage β—¦ Configuration β—¦ Roadmap β—¦ Support β—¦ Contributions β—¦ Authors


Usage

  1. Install the Mergeable GitHub App.
  2. Create your recipe(s). Here are some examples.
  3. Commit and push the recipes to your repository at .github/mergeable.yml

☝ 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.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 and action declares 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.
    message: 'Custom message...'

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 optional

Supported 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 deletions

Note 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'
       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.*'

label

  - 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.*'

milestone

- 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.*'

project

- 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.*'

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'
     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

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'

Note : AND and OR are not validators

Actions

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.*'

checks

- 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 returned 'pass'! \n Here are some stats of the run: \n {{validationCount}} validations were ran`

Supported events:

'pull_request.*', 'pull_request_review.*'

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.

πŸ”– 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 and package-lock.json)

πŸ”– See Recipe

version: 2
mergeable:
  - when: pull_request.*
    validate:
      - do: dependent
        changed:
          file: 'package.json'
          files: ['package-lock.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


Size: Ensure that PRs don't exceed a certain size in terms of lines changed (excluding file patterns specified with ignore).

πŸ”– See Recipe

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.



Read 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.

πŸ”– 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.

Staleness

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?

Roadmap

  • Additional actions like label and assign
  • 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:

☝️ NOTE: For development and testing. You'll want to read about how to run it locally.

Authors


AGPL, Copyright (c) 2019 Justin Law & Shine Lee

You can’t perform that action at this time.