Revy Semantics

A Revy configuration file goes through a series of syntactic checks.

Syntactic checks

Unused rule

Each rule specified in the rules section must be used in a protection gate. The following file is not valid since dummyRule is not used in any protection gate.

apiVersion: reviewpad.com/v0.0.4

labels:
  fastTrack:
    description: fast track mode
    color: 76dbbe

rules:
  changesOneFile:
    kind: patch
    description: Patch has more one file
    spec: $fileCount == 1

  dummyRule:
    kind: patch
    description: Simple dummy rule
    spec: 1 == 1

protectionGates:
  - name: fastTrack
    description: Fast track of pull requests
    patchRules:
      - rule: changesOneFile
    actions:
      - $addLabel("fastTrack")

Reference to undefined rule

Each rule referenced in a protection gate must be defined in the rules section. The following file is not valid as changesOneFile is not defined.

apiVersion: reviewpad.com/v0.0.4

labels:
  fastTrack:
    description: fast track mode
    color: 76dbbe

rules:

protectionGates:
  - name: fastTrack
    description: Fast track of pull requests
    patchRules:
      - rule: changesOneFile
    actions:
      - $addLabel("fastTrack")

Interpreter

If a Revy configuration file is syntactically valid, then it will be passed to the interpreter.

This interpreter receives the file and an environment as input and if no error is found during the interpretation, it outputs an Aladino program to be executed.

Environment

The environment used by the interpreter is specified in the reviewpad/action:

  1. GitHub repository (e.g. google/guava);
  2. Pull request number (e.g. for https://github.com/google/guava/pull/5929 it would be 5929);
  3. Access token. By default, it uses automatic token authentication. For more information read https://docs.github.com/en/actions/security-guides/automatic-token-authentication.

Design decisions

The task of the interpreter is to traverse the protection gate list to find which (if any) protection gate is enabled in the environment.

The gates that are enabled and subsequently which program will be executed respect the following rules:

  1. A protection gate is enabled if and only if any of its protection rules evaluates to true.
  2. The order in which the protection gates are specified determines the evaluation order.
  3. The final program is built by iterating over all protection gates in the specified list.
  4. Only one protection gate with alwaysRun: false is enabled per execution.
  5. The evaluation of protection gates is lazy, i.e. as soon as a protection gate is activated, all the others are disregarded unless they have alwaysRun: true.

For example, consider the following pseudo Revy file:

apiVersion: reviewpad.com/v0.0.3

rules:
 rule_1
 rule_2

protectionGates:
  - name: gate1
    description: Gate 1
    patchRules:
      - rule: rule_1
    actions:
      - action_1

  - name: gate2
    description: Gate 2
    patchRules:
      - rule: rule_1
      - rule: rule_2
    actions:
      - action_2

The interpreter starts by evaluating the rules of gate1 and only if all the rules are false it will go evaluate the rules of gate2. At the moment, there is no caching between rules.

If rule_1 is true, then gate1 would be active. As a consequence gate_2 would never be evaluated and therefore rule_2.

The specification of the rules only contains read-only actions.

Program generation

As we mentioned, the interpreter will produce an Aladino program that will be executed.
This program is simply a sequence of actions.

We will use an example to illustrate how this program is generated. Assume that we have the following protection gate:

  - name: gateX
    description: Active gate
    patchRules:
      - rule: rule_1
        extraActions:
          - rule_1_action_1
          - rule_1_action_2
      - rule: rule_2
        extraActions:
          - rule_2_action_1
      - rule: rule_3
      - rule: rule_4
        extraActions:
          - rule_4_action_1
    actions:
      - gen_action_1
      - gen_action_2

Assume that rule_1, rule_3 and rule_4 evaluate to true and rule_2 to false.

It follows that gateX is active. The final program is generated by concatenating the general actions of the gate with the extra actions of each enabled rule.

In this case this would be:

gen_action_1
gen_action_2
rule_1_action_1
rule_1_action_2
rule_4_action_1

Note: The order in which both protection gates and rules are specified matters. This is similar to any programming language where the order of statements matters.


Did this page help you?