KINTO Tech Blog
Development

Reduce Leftover PRs! GitHub Actions Workflow Recommendations

Cover Image for Reduce Leftover PRs! GitHub Actions Workflow Recommendations

Hello!

I am Asahi from the backend team of the New Car Subscription Development Group of the KINTO ONE Development department. I work on system operation development in order to provide KINTO ONE services. In August 2023, we released a major system renewal. During my years of working in system development, I have worked with many different teams, growing together and gone through many cycles of trial and error. But today I would like to talk about a GitHub Actions workflow we created in my current team, as I am very happy with the result and how is able to speed up pull request (from here on, PR) reviews.

Overview of workflows
Details on processing below

Everyone puts off code reviews

Do you prefer coding or reviewing code? I prefer coding by far. I am fully aware that code reviews are an important process for ensuring system quality. Even so, do you ever prioritize coding whenever a deadline is near and put off code reviews? Even when we started implementing them in the system revamp project, there were many times when I had PRs that were left open without being reviewed, even though the code was finished. As a result, my team had many of the following issues.

  • We could not complete tasks, and it was hard to measure the team's progress
  • We could not start working on tasks that had dependencies, or they were affected by other tasks
  • Merging conflicts were likely to occur

In order to speed up creating PRs and prevent these issues, we introduced a GitHub Actions workflow which I will talk about here.

About GitHub Actions

Our company uses GitHub as a source management tool. GitHub Actions is an automation tool used with GitHub that lets you describe processes that you want to automate in a workflow, put them in a repository, and process them whenever you want. It is a function of GitHub that integrates well with GitHub events.

Automatic reviewer configuration workflow

PRs after executing workflows
Today, I will talk about using GitHub Actions workflows to automatically set random reviewers and send a Slack notification whenever a PR is created. Comments stating that the PR creator automatically assigned reviewers is put in the PR.

Details on workflow processing

Overview of workflows

  1. Workflows are executed when a PR is created.
  2. The workflow sends a request to AWS Lambda (from here on, Lambda)[1].
  3. Information on team members is defined in advance during Lambda processing. At that time, it has the "specifications leader" and "technology leader" attributes. Other than you, a specifications leader and a technology leader will be chosen at random to be reviewers. The reason why it’s two is because of our team rules (at least two people must review in order to merge a PR).
  4. Information on the two members picked through Lambda are automatically set to PR reviewers, and comments mentioning the reviewers are placed.
  5. The assigned reviewers are notified through their designated Slack channels.

Slack notifications Linking with Slack Webhook

Recommendations

Filter reviewer configurations to the minimum number of people

If you limit reviewers to the minimum number of people instead of including everyone, you won't think, "Even if I don't review it, someone else will look at it," and depend on others or put off reviews.

Assign team members as "specifications leaders" or "technology leaders"

There were concerns that if the number of reviewers was limited, the assigned members' strengths and weaknesses would cause differences in review quality. For that reason, each member was assigned as either a "specifications leader" or "technology leader" beforehand. Members who specialized in information on domains looked at mainly specifications, and members who specialized in technology or had just joined and were studying specifications looked mainly at the technology aspect.

Sharing team member information across repositories

In order to execute a process in multiple repositories, each repository must have the same workflow. If the information on the members is defined in each workflow, when a member's information is updated (e.g., when a new member joins), all workflows that were configured must be revised. For that reason, we implement the process of randomly selecting reviewers in Lambda and commonize each repository so they can reference each other. This way, we can update information on member just by revising Lambda processing.

Instant confirmation is possible with Slack notifications

The set reviewer can immediately confirm by using a Slack notification process in the workflow. We have email notifications from GitHub, but integrating all of our communication tools makes sure that nothing is overlooked.

Reducing work through automation

GitHub Actions has received a lot of attention as a CICD automation tool. Apart from what I covered today, there are other ways to automate work similarly to workflows. Although it was originally meant to speed up PR reviews, I have experienced the benefits of automation after using it myself. If you try this workflow process, you may hesitate to request a review based on the team member's status, or you may need to send additional messages on Slack. These are not major hassles. My team has used these workflows for over two years, and we have saved a considerable amount of labor. This tool is essential to us now.

Sample workflow code

Here is a sample workflow (one that does not require Lambda). Feel free to customize and use it.

auto-assigning-reviewers.yml
name: "Auto Assigning Reviewers"

on:
  pull_request:
    types: [opened, ready_for_review, reopened]

jobs:
  assigning-reviwers:
    runs-on: ubuntu-latest
    if: |
      github.event.pull_request.draft == false
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
      - run: npm install @slack/webhook
      - uses: actions/github-script@v6
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const { IncomingWebhook } = require('@slack/webhook')

            // Define member information
            const MEMBER_INFO = [
              { slackName: "@MsSpecification",  speciality: 'spec' ,slackMemberId: "XXXXXX", githubName: "XXXXXX"},
              { slackName: "@MrSpec",  speciality: 'spec' ,slackMemberId: "XXXXXX", githubName: "XXXXXX"},
              { slackName: "@TheSpecSpecialist",  speciality: 'spec' ,slackMemberId: "XXXXXX", githubName: "XXXXXX"},
              { slackName: "@SkilledEngineer1",  speciality: 'skill' ,slackMemberId: "XXXXXX", githubName: "XXXXXX"},
              { slackName: "@Specialist2",  speciality: 'skill' ,slackMemberId: "XXXXXX", githubName: "XXXXXX"},
              { slackName: "@Newbie1",  speciality: 'skill' ,slackMemberId: "XXXXXX", githubName: "XXXXXX"},
            ]

            // Acquire PR creator
            const user = context.payload.sender.login;
            const author = MEMBER_INFO.find(member => member.githubName === user);

            // Select two random reviewers
            const skills = MEMBER_INFO
                            .filter(member => member.githubName !== author.githubName)
                            .filter(member => member.speciality === 'skill');

            const specs = MEMBER_INFO
                            .filter(member => member.githubName !== author.githubName)
                            .filter(member => member.speciality === 'spec');

            let getRandomNumber = (min,max) => Math.floor(Math.random() * (max - min + 1)) + min;
            const chosenSkillMember = skills[getRandomNumber(0, skills.length - 1)];
            const chosenSpecMember = specs[getRandomNumber(0, specs.length - 1)];

            const issue_number = context.issue.number
            const pull_number = context.payload.pull_request.number
            const { repo, owner } = context.repo

            // Set PR reviewers
            await github.rest.pulls.requestReviewers({
              owner,
              repo,
              pull_number,
              reviewers: [chosenSkillMember.githubName, chosenSpecMember.githubName]
            });

            // Set PR assignees
            github.rest.issues.addAssignees({
              owner,
              repo,
              issue_number,
              assignees: [user]
            });

            // Slack notification
            const title = context.payload.pull_request.title
            const html_url = context.payload.pull_request._links.html.href

            const message = `Hi! <@${chosenSkillMember.slackMemberId}> <@${chosenSpecMember.slackMemberId}> \n
            You were selected as PR reviewer of <@${author.slackId}> 🥳 \n
            <${html_url}|${title}>`

            // Specify the webhook URL of the Slack channel you want to notify
            const webhook = new IncomingWebhook('https://hooks.slack.com/xxxxxxxxx')

            await webhook.send({
              text: message,
            })

            // Comment on PR
            await github.rest.issues.createComment({
              owner,
              repo,
              issue_number,
              body: `@${chosenSkillMember.githubName},@${chosenSpecMember.githubName} was selected as reviewer 🚀`
            })

Conclusion

I spoke as if the idea was all mine, but I should thank my teammate Jeong-san for giving us this wonderful tool and ideas. Jeong-san always proposes convenient tools to us. An article by Super Jeong-san will be published tomorrow, so look forward to that. Have fun automating with GitHub Actions!

脚注
  1. AWS Lambda is a serverless AWS service that can execute processes defined as functions. ↩︎

Facebook

関連記事 | Related Posts

We are hiring!

【プラットフォームエンジニア】プラットフォームG/東京・大阪

プラットフォームグループについてAWS を中心とするインフラ上で稼働するアプリケーション運用改善のサポートを担当しています。

【スクラッチ開発エンジニア】プラットフォームG/東京・大阪

プラットフォームグループについてAWS を中心とするインフラ上で稼働するアプリケーション運用改善のサポートを担当しています。