coreos/tailor

Name: tailor

Owner: CoreOS

Description: GitHub bot that validates patches before they can be merged

Created: 2017-08-01 23:25:44.0

Updated: 2018-05-02 03:43:39.0

Pushed: 2018-05-01 01:56:58.0

Homepage:

Size: 157

Language: Rust

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

Tailor

Tailor pull requests to your liking.

Tailor is a GitHub bot which can be used to validate that pull requests comply with a set of rules. It can be used for example to ensure that commit messages are properly formatted, that commits are properly structured, or that pull requests have particular labels.

Usage
Repository Configuration

Each repository contains its own rules and configuration. This makes it easy to version the configuration alongside the code. The configuration is stored in /.github/tailor.yaml and has the following structure:

is is the list of rules that are applied to each of the pull requests to
e repository.
s:

# The name is used as an identifier and can be used in the admin commands.
name:        commit title

# The description is printed in the status messages to inform the submitter
# of what is wrong with their pull request.
description: all commit titles are less than or equal to 50 characters

# The expression describes the rule itself. Refer to the language
# documentation for an overview of the available functionality.
expression:  .commits all(.title length < 51)

Each of the rules are run on the entire pull request (the root context). They are run independently and cannot influence one another. Often times, it is useful to use .commits all to run an expression on each of the commits in the pull request, requiring all of them to comply. This is detailed further in the Expressions section. The rule expression must result in a boolean value, true indicating a success and false a failure.

Expressions

Expressions are made up of a series of infix operators detailed below. Almost all operators have an input value (on the left) and most have an argument value (on the right). Expressions are evaluated from left to right, which the result of the previous operator feeding into the next. Parenthesis can be used to evaluate a contained expression before its surroundings.

The only operator which doesn't take an input is the context operator (.). The result of this operation is the current context. It can be further limited by using a specifier (e.g. .commits) if the context is a dictionary. Since the context operator is the only operator which doesn't take an input, all expressions must begin with it.

It might be helpful to break down a few examples.

This expression returns true if there are exactly ten commits in the pull request: .commits length = 10. Parenthesis around every operation could be added for clarity: (((.commits) length) = 10)

This expression returns true if every commit title is no more than fifty characters: .commits all(.title length < 51). This expression makes use of the all operator, which is used for manipulating lists. For every commit, the expression .title length < 51 is evaluated with the context set to the commit in question. This inner expression then uses a context specifier (.title) to get the commit title and uses length to get the length of the title and compares to see if there are more than fifty characters. If every one of the inner expressions evaluates to true, all also results in true.

There are a handful of other operators, detailed below.

Operators Comparison

| Operator | Input | Argument | Result | Description | |:——–:|:———:|:———-:|:——-:|:—————————————————————-| | = | Any value | Any value | Boolean | true if the values are equal | | < | Numeral | Numeral | Boolean | true if the input is less than the argument | | > | Numeral | Numeral | Boolean | true if the input is greater than the argument |

Logical

| Operator | Input | Argument | Result | Description | |:——–:|:———:|:———-:|:——-:|:—————————————————————-| | and | Boolean | Boolean | Boolean | true if both the input and argument are true | | or | Boolean | Boolean | Boolean | true if either the input or argument are true | | xor | Boolean | Boolean | Boolean | true if one of the input or argument are true | | not | Boolean | | Boolean | true if the input is false |

List Manipulation

Each of the list manipulation operators (except length), accepts an expression as an argument and this expression is evaluated for each of the elements in the list. The context for each expression is set to the corresponding element from the input list. As mentioned above, every expression must begin with a context operator.

| Operator | Input | Argument | Result | Description | |:——–:|:———:|:———-:|:——-:|:—————————————————————-| | all | List | Expression | Boolean | true if all of the expression results are true | | any | List | Expression | Boolean | true if any of the expression results are true | | filter | List | Expression | List | List of each of the elements who's expression results in true | | map | List | Expression | List | List the result of each elements expression | | length | List | | Numeral | The number of elements in the list |

String Manipulation

| Operator | Input | Argument | Result | Description | |:——–:|:———:|:———-:|:——-:|:—————————————————————-| | test | String | String | Boolean | true if the argument (a regular expression) matches the input | | lines | String | | List | Splits a string by newlines into a list of strings |

Miscellaneous

| Operator | Input | Argument | Result | Description | |:——–:|:———:|:———-:|:——-:|:—————————————————————-| | . | | | Value | The current context |

Values

There are a few different types of values that can be used in Tailor:

Root Context

The root context is the initial input (a dictionary) into the rule expression. It is always a dictionary of values, derived from the pull request, and is of the following structure. Dictionaries are denoted by indentation, lists are denoted with brackets, and all leaf members are strings.


ser
.login
itle
ody
ommits[]
.sha
.author
  .name
  .email
  .date
  .github_login
.committer
  .name
  .email
  .date
  .github_login
.title
.description
omments[]
.user
  .login
.body
.created_at
ase
.sha
.label
.user
  .login
ead
.sha
.label
.user
  .login
Admin Commands

In some cases, it may be necessary to grant an exemption to the rules. Repository admins can specify exemptions by commenting on the pull request with tailor disable <rule name> to disable a particular rule or tailor disable all to disable all rules. Exemptions can be removed by deleting the comment.

Setup
Building

After cloning the repository, Tailor can be built and run with cargo run. The logging verbosity can be increased by adding up to three -v flags to the invocation (cargo run -- -vvv).

Configuring GitHub

Tailor is designed to be used as a webhook. Each GitHub repository will need to be configured with a new webhook with the payload URL http://url-of-tailor-instance/hook, the content type set to application/json, and just the “Pull request” event. The token that is given to Tailor will only need to have the repo scope so that it may set statuses and access collaborators.


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.