Only Building Pull Requests on CircleCI  -  How Greed Hinders Efficiency
Published: 2024-04-11 20:07:30

At a surface level, it should make sense why you would only want to run CI builds on pull requests. If you're like me, you're constantly force pushing [WIP](https://en.wikipedia.org/wiki/Work_in_process) commits to a git remote either because you're switching between machines or you just want piece of mind knowing it's okay if your laptop bites the dust. If we strive for [atomic commits](https://dev.to/samuelfaure/how-atomic-git-commits-dramatically-increased-my-productivity-and-will-increase-yours-too-4a84), there are few reasons why we should be burning Earth's resources on linting and testing our work prior to opening a PR.

CircleCI provides an easy way to only run builds on PRs. You can navigate to **Project Settings** > **Advanced** and toggle "Only build pull requests".

## That was easy. What's the gotcha?
So far the UX for setting up your CircleCI project has been pretty straight forward. You toggled a setting on. You pushed a feature branch up. As you hoped, it doesn't build until you open a PR. It _rebuilds_ when you push updates to the branch. You even convinced someone to stamp the PR 😉. Life is great.

You press merge, drag the ticket to the QA column and pat yourself on the back. There's just one problem. The PR was merged in to the **dev** branch and CircleCI didn't run a build (the one that's supposed to … deploy the changes). At this point, you should say to yourself "_I must've missed something_". Let's read the fine print of this "Only build pull requests" setting:

![For your default branch and tags, we well always build all commits](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0iz6fecv8c9xdanaltvk.png)

That seems useful! The default branch is usually **main** or **prod**. But what about **dev**, **uat**, **staging**,  or any branch you want to automatically deploy using CircleCI? There's likely more git refs you want to run builds on other than "default branch and tags".

## Greed is the root of all evil
Your likely next step is to mash the keyboard on google until you find someone else with the same problem. To your disgust, you find multiple accounts ([2016](https://discuss.circleci.com/t/allow-branch-whitelist-to-override-only-build-pull-requests/6392) [2018](https://circleci.canny.io/cloud-feature-requests/p/allow-branch-whitelist-to-override-only-build-pull-requests)) of this limitation and varying solutions that mostly rely on manually hitting the CircleCI API to achieve the desired behavior of triggering builds both on pull requests and deploy branches.

This seems like a very simple feature that **_many_** users desire. Why would CircleCI, a company valued at $1.7 billion in 2021, not invest the man-hours for such an easy feature?

![Scrooge counting his money](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wh7kou8nou9zdccvdk6q.gif)

The alternative to only running builds on PRs is, you guessed it, run builds on _every_ commit. I'm speculating, but I'd wager that this feature was discussed internally as it kept popping up in community posts. I like to think that it went down like this:

> **Dev Team:** This is a really easy ticket and a feature we would want as a user. Can we just knock it out?
> **Product Manager:** Let me run it up the flagpole.
> **Finance:** So, it would be really useful but incentivize users to run less builds by orders of magnitude?
> **Product Manager:** Yes.
> **Finance:** Yeah no chance.

## A wild solution appears
Fast forward to April 2023. A CircleCI employee creates a forum [post](https://discuss.circleci.com/t/product-launch-override-only-build-prs-setting/47807) outlining a new field exposed through the API for tweaking project settings. This field, called **pr-only-branch-overrides**, is exactly what we've needed for nearly a _decade_!

As outlined in the post, you can do a simple, one-time curl to set the list of branches to run builds on:

```bash
curl -X PUT -H "Circle-Token: <token>" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"feature_flags":{"pr-only-branch-overrides": "prod, dev, staging"}}' \
  "https://circleci.com/api/v1.1/project/<vcs_type>/<org_slug>/<repo_name>/settings"
```

Despite the endpoint existing since April, documentation only hit open preview as of [December](https://discuss.circleci.com/t/project-settings-api-v2-endpoints-now-in-open-preview/49999) which you have to dig for.

As of this writing, it's been a year since the endpoint was introduced. Why isn't it configurable from the UI? Why did we get the endpoint at all? I could take a guess...

> **2016 Hobby user:** We need this feature!
> **CircleCI:** \*\*crickets\*\*
> **2018 Hobby user:** If we don't get this feature, I'm just going to use Github actions!
> **CircleCI:** \*\*crickets\*\*
> **2023 Cash-Cow Client:** If we don't get this feature, we're moving elsewhere.
> **CircleCI:** Here's an endpoint!

## Conclusion
I enjoy the product that CircleCI offers, but this is not a good look and I've lost a fair amount of trust (all [breaches](https://circleci.com/blog/jan-4-2023-incident-report/) aside). I would've hoped that competition in the CI/CD space would push _all_ services forward, but alas, money talks.