How to Add Estimated Review Time and Context Labels to Pull Requests
Tags: tutorial, programming, productivity, devops
Published: 2023-03-19 21:09:48

The pull request (PR) review process, if not set up well in your team, can create a lot of bottlenecks in getting your code merged into the main branch and into production. By adding more context and information automatically to your PRs, you save yourself and your team work.

Take the scenario of fixing a typo in documentation. If there’s a backlog of PRs that need attention, such a PR may take two days — or longer — just to be approved. This is where [continuous merge](https://linearb.io/blog/what-is-continuous-merge/) (CM) with gitStream comes in.

[gitStream](https://github.com/marketplace/gitstream-by-linearb) is a tool that allows you to add context and automation to your PRs, classifying PRs based on their complexity. 

This ensures that a review won't stay in the queue for long as it can be quickly assigned to the right person, immediately approved or have the appropriate action identified easily.

This hands-on article demonstrates how to add gitStream CM to your repository. 

In this article, you’ll learn:

1. How to Configure your Repository
2. How to Create Pull Requests (PRs) 
3. How to Add the CM Feature to Your PRs

## Quick gitStream Setup Guide
If you’re keen to get all the benefits of gitStream and continuous merge right away, all you need to do is follow these simple steps. If you want to understand how gitStream works, how you can customize it and more options, it will follow right after.

1. Choose Install for free on [gitStream's GitHub marketplace page](https://github.com/marketplace/gitstream-by-linearb)
2. Add 2 files to your repo:

```
a) .cm/gitstream.cm
b) .github/workflows/gitstream.yml
```
3. Open a pull request
4. Set gitStream as a required check

## A Comprehensive Guide to gitStream & Continuous Merge
[Filter functions](https://docs.gitstream.cm/filter-functions/) and [context variables](https://docs.gitstream.cm/context-variables/) are used to effect [automated actions](https://docs.gitstream.cm/automation-actions/), such as adding labels (add-label@v1), assigning reviewers (add-reviewers@v1), and approving requests (approve@v1), among others. 

Everything is included in a .cm configuration file named gitstream.cm. 

All instructions to gitStream CM are detailed in the docs found at docs.gitstream.cm. gitStream also uses GitHub Actions to do its work, so you’ll need to add the gitstream.yml file to your GitHub Actions directory at .github/workflows/.

The main components to fulfill gitStream’s CM are:

- The configuration files: gitstream.cm and gitstream.yml.
- The filter functions: Code that tries to check and/or select certain data types from the input for checks during a PR creation.
- The context variables: The inputs fed to the filter functions.
- The automation actions.

**Note:** Some steps use Python only for demonstration purposes. It’s not required knowledge.

### Prerequisites
To follow this tutorial, ensure you have the following:

- Hands-on knowledge of Git and GitHub workings. You must know activities such as creating a repository, PRs, commits, and pushes. 
- A GitHub account.
- Git installed in your working environment.

You can find and review the final project code [here](https://github.com/marketplace/gitstream-by-linearb).

### Step 1 - Set Up gitStream on Your Repo
Create an empty repo and give it a name, then install gitStream to it from the marketplace. 

After installation, you can either: 1) Clone the repository to your environment; or 2) Create a folder and point it to the repository. This tutorial uses the second option.

Create a folder called gitStreamDemo. In this folder, create two directories, .github/workflows and .cm, using the commands in a terminal window below:

```
mkdir -p .github/workflows

mkdir .cm
```
In the .github/workflows folder, create a file called gitstream.yml and add the following YAML script:

```
name: gitStream workflow automation

on:

workflow_dispatch:

  inputs:

    client_payload:

      description: The Client payload

      required: true

    full_repository:

      description: the repository name include the owner in `owner/repo_name` format

      required: true

    head_ref:

      description: the head sha

      required: true

    base_ref:

      description: the base ref 

      required: true

    installation_id:

      description: the installation id

      required: false

    resolver_url:

      description: the resolver url to pass results to

      required: true

    resolver_token:

      description: Optional resolver token for resolver service

      required: false

      default: ''

jobs:

  gitStream:

    timeout-minutes: 5

    # uncomment this condition, if you dont want any automation on dependabot PRs

    # if: github.actor != 'dependabot[bot]'

    runs-on: ubuntu-latest

    name: gitStream workflow automation

    steps:

      - name: Evaluate Rules

        uses: linear-b/gitstream-github-action@v1

        id: rules-engine

        with:

          full_repository: ${{ github.event.inputs.full_repository }}

          head_ref: ${{ github.event.inputs.head_ref }}

          base_ref: ${{ github.event.inputs.base_ref }}

          client_payload: ${{ github.event.inputs.client_payload }}

          installation_id: ${{ github.event.inputs.installation_id }}

          resolver_url: ${{ github.event.inputs.resolver_url }}

          resolver_token: ${{ github.event.inputs.resolver_token }}
```
Next, create a file called gitstream.cm in the .cm folder and add the following code:

```
manifest:

  version: 1.0

automations:

  show_estimated_time_to_review:

    if:

      - true

    run:

      - action : add-label@v1

      args:

       label: "{{ calc.etr }} min review"

       color: {{ '00ff00' if (calc.etr >= 20) else ('7B3F00' if (calc.etr >= 5) else '0044ff') }}

  safe_changes:

    if:

      - {{ is.doc_formatting or is.doc_update }}

    run:

      - action: add-label@v1

       args:

       label: 'documentation changes: PR approved'

       color: {{'71797e'}}

      - action: approve@v1

  domain_review:

    if:

      - {{ is.domain_change }}

    run:

      - action: add-reviewers@v1

      args:

       reviewers: [<listofreviewers>]

      - action: add-label@v1

      args:

       label: 'domain reviewer assigned'

       color: {{'71797e'}}

  set_default_comment:

    if:

      - true

    run:

      - action: add-comment@v1

      args:

       comment: "Hello there. Thank you for creating a pull request with us. A reviewer will soon get in touch."

calc:

  etr: {{ branch | estimatedReviewTime }}

is:

  domain_change: {{ files | match(regex=r/domain\//) | some }}

  doc_formatting: {{ source.diff.files | isFormattingChange }}

  doc_update: {{ files | allDocs }}
```
In the file, you’ll see the following four automation actions:

- show_estimated_time_to_review: This automation calculates the estimated time a review to a PR may take.
- safe_changes: This shows if changes to non-critical components done in a PR are safe, such as document changes. The PR is automatically approved.
- domain_review: This automation runs to show if a change was made to the domain layer.
- set_default_comment: This is fired every time a PR is opened and raises an acknowledgment comment to the user that a PR has been created.

At the end of the document, there’s a section containing filter functions for the automation actions. The actions are run after certain conditions specified in the filter functions or keys are met.

### Step 2 - Calculating the Time to Review
In the first automation, check the value of the etr variable and decide which label to assign to the PR. For more information on [how ETR is calculated, check out this blog](https://linearb.io/blog/why-estimated-review-time-improves-pull-requests-and-reduces-cycle-time/).

Create a file called main.py in the root of your folder. Then, create three folders using the command below:

```
mkdir views domain data
```
Add the following to the main.py file:

```
def show_message(name1, name2):

  print(f'Hello, {name}. Welcome to the gitStream world')

if __name__ == '__main__':

  print_hi('Mike')
```
Copy the main.py file as is and paste it to the other three folders. Rename them to match the folders’ names (domain.py) for the domain folder.

For the dummy documentation file, create a README.md file in the root of your folder and add the following markdown script.

```
# gitStreamDemo
```
A demo showing how to set up gitStream on your first repo

Now, run these commands to initialize the repository, stage the files for committing, and make a commit, in that order:

```
git init

git add .

git commit -am “initialization”
```
Next, point the folder to your repository using the command below:

```
git remote add origin https://github.com/<your-username>/<your-repo-name>
```
Finally, push it:

```
git push -u origin main
```

### Step 3 - Creating the Repository
As you may have noticed, there’s a sample bug in the code. In any programming language, you must call the function using its exact name. But in this case, print_hi was called instead of show_message. As a team member or an open-source contributor, you can fix this by opening a PR.

First, create a branch called fix-function-call and checkout into the branch using the commands below:

```
git branch fix-function-call

git checkout fix-function-call
```
Next, replace the name print_hi with show_message in all the .py files, then commit and push the changes.

```
git commit -am “changed function name”

git push --set-upstream origin fix-function-call
```
Now, open your repository in GitHub. You’ll see the following card:

![Compare and pull request button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3o63n00agai85y2wk2g.png)

Click on **Compare & pull request**. On the next page, click the **Create pull request** button.

Once the gitStream automation has finished running, you’ll see the **domain reviewer assigned** tag. Additionally, a comment has been created.

![Domain reviewer assigned tag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zer9hfludbe5q8mp6tdd.png)

Add this Dijkstra’s Shortest Path Algorithm [script](https://github.com/Agusioma/dijkstra-in-python/blob/main/dijkstra.py) just below the show_message function in each of the .py files again. These scripts calculate the shortest path for a node in a graph.

Commit the changes and then push the code.

```
git commit -am “updates”

git push
```

![PR Approved](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14i8lkhpa27qnt7pbtsr.png)

### Creating a Safe Change
For the final automation, you’ll add text to the README.md file created earlier. Create a new branch and checkout to it. You do so because you’ll need a new PR to demonstrate this automation.

```
git checkout main

git branch update_docs

git checkout update_docs
```
Then, add this sentence to the README.md file:

```
Continuous Merging is very beneficial to the Open-Source Community.
```
Commit and push.

```
git commit -am “updated the docs”

git push --set-upstream origin update_docs
```
When the checks are done, you’ll see a different label with the PR already approved.

![PR Approved](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4i9qzrt6mmyzrck5i30v.png)

## Help Developers Make the Most of Their Time...
Reviewing and merging PRs are crucial in contributing to software development and enhancing team productivity. However, being unable to classify PRs by complexity can lead to long wait times or much back-and-forth in the review process.

CM remedies this issue by classifying PRs based on the complexity, automating some actions including tagging the appropriate reviewers, assigning them PRs, and approving PRs among others to reduce the backlog.

Check out [gitStream](https://github.com/apps/gitstream-cm/installations/new) to add CM to your existing repos.

![Learn more about gitStream today!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nyx931osafkg8j4189ge.png)