First published June 11, 2023

Automatically Create a Pull Request Against a Feature Branch with GitHub Actions

Keep up with code reviews programmatically using workflows.

Old school typewriter

Introduction

This blog post is the second in a short series I'm writing about the many things I learned in the course of building my first open source API library for the IoT startup I work for, Blues.

It was a great learning experience for me and a new, unique challenge because I needed to do the following things:

  • Make a copy of the openapi.yaml file from the Blues cloud's repository, Notehub, whenever the file was updated.
  • Open a new pull request against the Notehub JS repo with the copy of the openapi.yaml file.
  • Generate a fresh version of the Notehub JS API library based on the that file via the OpenAPI Generator CLI.
  • And publish the updated Notehub JS library to npm.

And I wanted to automate as many of these steps as possible through the use of GitHub Actions workflows.

Since I didn't know how often the Notehub's openapi.yaml file would be updated, I needed a way to notify myself when a new version of the Notehub's API file needed review in the Notehub JS repository. The best solution I could think of was to open a new pull request in the Notehub JS repo after copying the updated openapi.yaml file into a feature branch and tagging myself to review it.

Today, I'll walk through how to use a GitHub Actions workflow to create (or update) a pull request whenever a new feature branch is made in that repository.

Notehub JS

Before we get to the actual GitHub Actions workflow, let me give you just a little background on the Notehub JS project because it's a bit different than most.

This section helps explain the folder structure for the repo in case you want to explore it in GitHub, if you just want the solutions, feel free to jump down to the next section.

Notehub JS is a JavaScript-based library for interacting with the native Notehub API, and it's generated from the Notehub project's own openapi.yaml file, which follows the OpenAPI specification standards.

The OpenAPI Generator CLI is a tool that can use the openapi.yaml file to create an entire library complete with documentation, models, endpoints, and scripts to package it up for publishing as an npm module. The end library that I care about publishing to npm is a subfolder inside of the main Notehub JS repo. At the root of the project are the openapi.yaml file, the GitHub Actions workflows, and a few other config files.

Here's a simplified view of the Notehub JS repo's folder structure:

root/
├── .github/ 
| ├── workflows/
| | ├── create-pr.yml 
| ├── PULL_REQUEST_TEMPLATE.md
├── src/ <- this is the folder generated by the OpenAPI Generator CLI
| ├── dist/
| ├── docs/
| ├── src/ 
| | ├── api/ 
| | ├── model/
| | ├── index.js 
| openapi.yaml
| config.json
| package.json

As you can see in the diagram above, the openapi.yaml file that this library is generated from lives at the root of the repo, and the src/ folder is what actually holds all the Notehub API JavaScript code that powers the Notehub JS library.

This openapi.yaml file is what gets copied from the Notehub repo when changes are made to it. And changes are made to the file whenever the Notehub API is updated with new features and functionality, so making sure that the Notehub JS library keeps up with the new additions to the API it's based on is important.

Now that I've explained a bit more about the Notehub JS repo and why keeping it in sync with the Notehub API is important, we can get down to the business of automating PRs for this repo.

Looking for more details about Notehub JS?

Check out my previous blog post about how to use GitHub Actions to automatically publish new releases to npm - I do a fairly deep dive on Notehub JS there.

Create a standard PR template for the repo

When I was just a few years into my own web development career, I was introduced to GitHub PR templates, an easier way to keep pull requests uniform for a repository worked on by multiple developers. It made the task of creating decent PRs so much better.

There is not a team or repo I join now without adding a ./github/ directory folder and PULL_REQUEST_TEMPLATE.md file if it doesn't already exist.

For the Notehub JS repo, as it's mostly autogenerated, I included a couple of sections to fill in: Problem Context: a brief description of the updates in the PR, and Changes: what code changes were actually made in the PR. Simple enough for any dev to fill out.

PULL_REQUEST_TEMPLATE.md

# Problem Context

## Changes

That's all I wanted to add to the repo before focusing on the GitHub Actions workflow itself. We'll get to it next.

Set up a GitHub Actions workflow to automatically create pull requests

Need a refresher on GitHub Actions?

If you want a quick primer on what GitHub Actions are, I recommend you check out a previous article I wrote about them here.

For this particular workflow, I was able to string together a few premade GitHub Actions to do just what I needed:

  • Create a new pull request whenever a new feature branch was pushed to the GitHub repository.
  • Use the PULL_REQUEST_TEMPLATE.md file to format the PR.
  • Notify me when a PR is there for review.

Here's what the final create-pr.yml file looks like inside of the ./github/workflows/ directory. I'll dissect it below.

create-pr.yml

name: Automatically create / update pull request

# run this workflow only on new feature branches, not when they're merged to main
on:
  push:
    branches-ignore:
      - "main"

jobs:
  create_pr_repo_sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Create pull request
        id: open-pr
        uses: repo-sync/pull-request@v2
        with:
          destination_branch: "main"
          pr_title: "feat: PLACEHOLDER TITLE"
          pr_template: ".github/PULL_REQUEST_TEMPLATE.md"
          pr_reviewer: "paigen11"
          pr_draft: true

Each workflow file needs a name, so I chose to name this one: Automatically create / update pull request.

This workflow should be triggered whenever a new branch is pushed to the repo but it should ignore the "main" branch. "main" is the main branch of this repo that gets published to npm and doesn't need a PR to be created for it.

on:
  push:
    branches-ignore:
      - "main"
  • on is how a workflow is triggered.
  • push is the event that triggers the workflow.
  • branches-ignore is how to exclude the workflow from running on certain branch patterns. This gives us more fine-grained control of when the workflow should run.

Then the jobs section runs inside of the workflow. This particular script only has one job, create_pr_repo_sync, but if there's multiple jobs, they'll run sequentially unless otherwise specified.

The create_pr_repo_sync job defines that it runs on the latest version of Ubuntu in runs-on.

Finally, I get to the steps.

The steps are as follows:

  1. Check out the code so the workflow can access it using the GitHub Action actions/checkout@v3.
  2. Create a pull request using the GitHub Action repo-sync/pull-request@v2
  3. Pass the PR action a custom pr_title, pr_template, and pr_reviewer. Set it to be created as a pr_draft (I like PRs to be drafts until I've looked them over and know they're ready for review), and open the PR branch against the destination_branch: "main".

In the pr_template section, I pass the path to the PR template file I made in the previous section, and for the pr_reviewer I add my own GitHub username so that I get an email notification when the new PR is created in GitHub.

Test out the workflow

If you want to test this functionality out, create a new local branch of the repo, make a change in the branch, and push it to GitHub. When that new branch registers, the GitHub Actions workflow will be triggered to run.

If you visit the Actions page in the GitHub repo, you should see the "Automatically create / update pull request" job running.

GitHub Actions workflow running in Notehub JS repo's Actions tab

And after the action finishes running, there should be an email sent to the folks tagged as the PR reviewers in the GitHub Action (me, in this case).

Notification email from GitHub to review the newly created PR

And with that, the workflow working has been confirmed, and the reviewers know it's time to take action in that repo.

Conclusion

When I built my first open source software library, I learned a lot. My software is a JavaScript library based on my company's API, Notehub, so every time the Notehub API gets updated, the JS library based off of it, needs to be updated too.

I needed a programmatic way to let myself know whenever new changes were made to the JS repo that needed to be reviewed.

The easiest way I could think to accomplish this was by automating the pull request creation so that when a new feature branch was pushed to the repo, it opened a PR and tagged myself as the reviewer.

Luckily, a GitHub Action existed for just such a scenario, allowing for designating a PR template, a PR reviewer, giving the PR a placeholder title, and a whole host of other configurations. The workflow made it quite straightforward, and gave me the peace of mind that whenever changes are made that I need to review, I get an email to look at what's changed.

Check back in a few weeks — I’ll be writing more about the useful things I learned while building this project in addition to other topics on JavaScript, React, IoT, or something else related to web development.

Thanks for reading. I hope learning to use GitHub Actions workflows to automate a new PR when a feature branch is pushed to a repository proves useful. Enjoy!

References & Further Resources

Want to be notified first when I publish new content? Subscribe to my newsletter.