SizeUp is a library for estimating how difficult a diff will be to review.
npm install sizeup-core
The most common usage of this library is via one of these wrappers:
- sizeup-action, which provides a GitHub Action to use this library to evaluate pull requests
- sizeup-cli, which provides a CLI to use this library to evaluate a diff locally, prior to opening a pull request
To use the library directly, you need to first retrieve a diff, and the pass it
to SizeUp.evaluate
(optionally also providing a custom configuration file):
import { SizeUp } from "sizeup-core"
const diff = (
await octokit
.rest
.pulls
.get({
"lerebear",
"sizeup",
pull_number: 1,
// This is the easiest way to request a diff directly, but since Octokit
// doesn't provide the correct result type when we use the `mediaType`
// option, we must cast the result to a string later on
mediaType: {format: 'diff'},
})
).data as unknown as string
const score = SizeUp.evaluate(diff)
console.log(score.toString())
The final log statement in that snippet will output a serialized Score
:
{
// The expression (written in prefix notation) used to score the diff
"formula": "- - + additions deletions comments whitespace",
// The values that were substituted for each variable in the formula
"variableSubstitutions": [
[
"additions",
11
],
[
"deletions",
3
],
[
"comments",
6
],
[
"whitespace",
1
]
],
// The score the diff received when evaluated according to the formula
"value": 7,
// The category the diff was assigned based on its score
"category": "xs"
}
The public API for this library consists of the single, static SizeUp.evaluate
method:
export class SizeUp {
/**
* Evaluates a diff for reviewability.
*
* @param diff A .diff formatted string containing the code to evaluate
* @param configPath Path to a YAML configuration file containing options for how to evaluate the
* pull request. The YAML file should conform to the JSON schema in src/config/schema.json.
*/
static evaluate(diff: string, configPath?: string): Score
}
This section describes how to configure this library.
As shown above, SizeUp.evaluate
accepts a YAML configuration file that can be used to customize the evaluation process. Here's an example:
categories:
- name: xs
lte: 10
- name: s
lte: 30
- name: m
lte: 100
- name: l
lte: 500
- name: xl
ignoredFilePatterns:
- CODEOWNERS
- SERVICEOWNERS
testFilePatterns:
- "*_test.rb"
scoring:
formula: "- - + additions deletions comments whitespace"
The default configuration that is used when no configuration file is provided can be found in src/config/default.yaml
.
The full specification for the configuration file is provided by the JSON schema at src/config/schema.json
.
sizeup
is designed to allow users to experiment with different ways to evaluate a diff. You can do this my writing a custom scoring formula that you provide to the libary via the score.formula
key in the configuration file.
The elements of a formula are described in more detail in each of the following sections:
Each formula is written in prefix notation, which means that instead of writing a mathematical operator in between its operands (infix notation), you write it before its operands. For example:
Traditional (infix notation) expression | Equivalent prefix notation expression |
---|---|
1 + 2 |
+ 1 2 |
(2 + 3) / 10 |
/ + 2 3 10 |
Operators are used to evaluate numerical or logical sub-expressions in a formula. This tool supports the following operators:
Symbol | Meaning | Example |
---|---|---|
+ |
addition | + 1 2 evaluates to 3 |
- |
subtraction | - 2 1 evaluates to 1 |
* |
multiplication | * 1 2 evaluates to 2 |
\ |
division | / 4 2 evaluates to 2 |
^ |
exponentiation | ^ 2 3 evaluates to 8 |
? |
conditional evaluation | ? 0 2 4 evaluates to 4 because 0 is considered false 1 |
> |
greater than | > 1 2 evaluates to false |
< |
less than | < 1 2 evaluates to true |
>= |
greater than or equal to | >= 1 2 evaluates to false |
<= |
less than or equal to | <= 1 1 evaluates to true |
== |
equals | == 1 1 evaluates to true |
!= |
not equal | != 1 1 evaluates to false |
& |
logical and | & 0 1 evaluates to false 1 |
| |
logical or | | 0 1 evaluates to true 1 |
! |
logical not | ! 1 evaluates to false 1 |
Each operand can be one of three things:
Features describe aspects of a diff that can be computed from it automatically. This tool support the following features:
Feature | Description |
---|---|
additions |
The number of lines that were added in a diff |
comments |
The number of additions in a diff that match the syntax of a comment in a supported programming language. |
deletions |
The number of lines that were deleted in a diff |
single-words |
The number of additions in a diff that are made up of a single word on its own line |
tests |
The number of additions in a diff that were made in files that match a pattern from the testFilePatterns configuration value. |
whitespace |
The number of additions in a diff that were pure whitespace |
If you have an idea for a new feature, please suggest an enhancement.
Aliases, which are configured under the scoring.aliases
key, allow you to define a shorthand for a longer expression:
scoring:
formula: "- changes non-functional-changes"
aliases:
changes: "+ additions deletions"
non-functional-changes: "+ comments whitespace"
This section contains notes for how to develop this library.
We use a JSON schema to define the configuration options that this library supports. We then use the json-schema-to-typescript
package to generate the TypeScript Configuration
interface that we use in code.
json-schema-to-typescript
uses outdated type definitions which are incompatible with the latest version of minimatch
that we use in this package. This creates build errors if json-schema-to-typescript
is added as a dependency of this package.
To work around those issues, we use the following workflow to regenerate the Configuration
interface after we've made a change to the schema:
- Temporarily install
json-schema-to-typescript
:
npm install --save-dev json-schema-to-typescript
- Regenerate the
Configuration
interface using this command:
npm run generate:config
- Remove
json-schema-to-typescript
so that we can again build this package without errors.
npm uninstall json-schema-to-typescript