[Product Launch] Override Only Build PRs Setting

Context:

The “Only build pull requests” project setting enables users to only trigger validation on CircleCI when a pull request is present on non-default branches.

This setting can be too restrictive for certain scenarios, such as when trying to use CircleCI with GitHub’s merge queue functionality. Original feedback in this Canny post.

Starting April 18, 2023, the CircleCI API can be used to override the “Only build pull requests” setting. This enables you to specify certain branches (via regular expression) that trigger validation on every commit, while maintaining the “Only build pull requests” setting on all other non-default branches.

Input:

  • Comma-separated list of regular expressions or full branch names to match
    • These branches will build all commits, while all other branches will continue to only build when a pull request is present
    • The default branch (ie. main) must be included in the comma-separated list in order to maintain the behavior of always building all commits to the default branch
  • Notes:
    • vcs-type, org-slug and project-slug values that are used as input to the CircleCI API can be seen in the URL when viewing a project in the CircleCI UI
    • Any user that has access to change project settings can use this override
    • A valid API token is required to make these API calls, see “add an API token” if this is your first time using the CircleCI API
    • To match literal characters with regex significance, they must be escaped. For example, to match a branch named main-(2123), the parenthesis must be double-escaped with a backslash: main-\\(2123\\)
    • Regex character classes must be double escaped. For example, main-\\d+ will match branches named main-3 and main-32. To match a branch composed of characters in the Greek UTF-8 block, specify \\p{IsGreek}.
    • Any call to the API to update the settings will replace the current settings, not add to the existing settings

Example #1:

Assumes that the “Only build pull requests” setting is already enabled. Override the “Only build pull requests” setting for the following branch and branch patterns: main, release.*, enterprise-.*

curl -X PUT --header "Circle-Token: <token>" 
--header "Accept: application/json" 
--header "Content-Type: application/json" 
--data '{"feature_flags":{"pr-only-branch-overrides": "main, release.*, enterprise-.*"}}' 
'https://circleci.com/api/v1.1/project/vcs-type/org-slug/project-slug/settings'

Note: Replace <token> with your CircleCI API token

Result: If the response looks like the following:

""%

Any branch that starts with release, such as release2 or release-to-prod, and any branch that starts with enterprise-, such as enterprise-2.0, will now trigger validation on all commits. Additionally, the default branch, main, will continue to build all commits.

All other branches in this project will only build when they have an open pull request.

Example #2:

Enable “Only build pull requests” setting via the CircleCI API and override the setting for the following branch and branch patterns: main, release.*, enterprise-.*

curl -X PUT --header "Circle-Token: <token>" 
--header "Accept: application/json" 
--header "Content-Type: application/json" 
--data '{"feature_flags":{"build-prs-only":true, "pr-only-branch-overrides": "main, release.*, enterprise-.*"}}' 
'https://circleci.com/api/v1.1/project/vcs-type/org-slug/project-slug/settings'

Result: Any branch that starts with release, such as release2 or release-to-prod, and any branch that starts with enterprise-, such as enterprise-2.0, will trigger validation on all commits. Additionally, the default branch, main, will continue to build all commits.

All other branches in this project will now only build when they have an open pull request.

Example #3:

Enable “Only build pull requests” setting via the CircleCI API and override the setting for the following branch and branch patterns: main, \\(\\d+\\)-release.*

Note: Replace <token> with your CircleCI API token

curl -X PUT --header "Circle-Token: <token>" 
      --header "Accept: application/json" 
      --header "Content-Type: application/json" 
      --data '{"feature_flags":{"build-prs-only":true, "pr-only-branch-overrides": "main, \(\\d+\)-release.*"}}' 
'https://circleci.com/api/v1.1/project/vcs-type/org-slug/project-slug/settings'

Result: Will build any branch that starts with one or more digits enclosed in parenthesis followed by the string -release suffixed with zero or more characters. For example:

Branches (123)-release2 , (7)-release-to-prod, and (334)-release will all trigger validation on all commits. Additionally, the default branch, main, will continue to build all commits.

Limits:

  • pr-only-branch-overrides will only have an effect if the “Only build pull requests” setting is turned on
    • You can verify this via the API response by observing the boolean build-prs-only? is set to true or via the Project Settings UI under the “Advanced” section
  • There is a maximum of 100 branch regular expressions per project and a limit of 1,000 characters per regular expression
  • Branch names cannot include a “comma” (“,”). The API will not reject this as input, it will simply assume that the comma splits the input into two branch names
  • There is not a way to retrieve the value of a single project setting - to see the currently set values, retrieve all of the settings for a given project
  • As of writing this post, this functionality only works for CircleCI organizations that use GitHub as their VCS

Example of retrieving Project Settings for a given project within an organization

curl -X GET --header "Circle-Token: <token>" 
--header "Accept: application/json" 
--header "Content-Type: application/json" 
'https://circleci.com/api/v1.1/project/vcs-type/org-slug/project-slug/settings'

Note: Replace <token> with your CircleCI API token

Response:

Note: this response includes information that may be considered sensitive. "pr-only-branch-overrides": will show which branch regexes are set-up.

{
"irc_server": null,
"slack_integration_channel": null,
"irc_keyword": null,
"slack_integration_team_id": null,
"vcs-type": "github",
"aws": { "keypair": null },
"slack_webhook_url": null,
"slack_integration_team": null,
"username": "foo-user",
"branches":
{
"circleci-project-setup":
{
"running_builds": [],
"recent_builds":
[
{
"status": "success",
"outcome": "success",
"build_num": 1,
"vcs_revision": "f2aa5c44b9db87f76b5cec3827b5f973f80a2ff2",
"pushed_at": "2022-05-02T23:26:20.608Z",
"added_at": "2022-05-02T23:26:25.446Z",
"is_workflow_job": true,
"is_2_0_job": true,
},
],
"is_using_workflows": true,
"pusher_logins": ["foo-user"],
"last_success":
{
"status": "success",
"outcome": "success",
"build_num": 1,
"vcs_revision": "f2aa5c44b9db87f76b5cec3827b5f973f80a2ff2",
"pushed_at": "2022-05-02T23:26:20.608Z",
"added_at": "2022-05-02T23:26:25.446Z",
"is_workflow_job": true,
"is_2_0_job": true,
},
"last_non_success":
{},
"latest_workflows":
{
"say-hello-workflow":
{
"id": "231434a4-19da-46cd-b88f-91a92234ac00",
"status": "canceled",
"created_at": "2022-05-20T15:11:08.201Z",
},
},
"latest_completed_workflows":
{
"say-hello-workflow":
{
"id": "231434a4-19da-46cd-b88f-91a92234ac00",
"status": "canceled",
"created_at": "2022-05-20T15:11:08.201Z",
},
},
},
},
"jira": null,
"slack_integration_notify_prefs": null,
"slack_integration_webhook_url": null,
"slack_subdomain": null,
"following": true,
"slack_notify_prefs": null,
"irc_password": null,
"vcs_url": "https://github.com/foo-user/helloworld",
"default_branch": "main",
"irc_username": null,
"language": null,
"slack_channel_override": null,
"slack_api_token": null,
"has_usable_key": true,
"irc_notify_prefs": null,
"slack_channel": null,
"feature_flags":
{
"setup-workflows": false,
"set-github-status": false,

"build-prs-only": true,

"forks-receive-secret-env-vars": false,
"build-fork-prs": false,
"autocancel-builds": false,

"pr-only-branch-overrides": "main, release.*, enterprise-.*"

},
"slack_integration_channel_id": null,
"irc_channel": null,
"oss": false,
"reponame": "helloworld",
"slack_integration_access_token": null,
"ssh_keys": [],
}
7 Likes

This is great. Also very useful for situations using a gitflow type workflow where there’s a default branch and then that’s merged into trunk (e.g., develop and main).

1 Like

Thanks @sebastian-lerner for this tips, it works but there’s a side effect.

I enabled Only build pull requests on our develop and master branches.
I also have Auto-cancel redundant workflows enabled.
My default branch is develop.

I have a deploy pipeline.
In my deploy pipeline, at the end, I add a git-tag which auto-cancel current pipeline because Auto-cancel redundant workflows is enabled.

Is it possible to also configure default branches on this option Auto-cancel redundant workflows
as Only build pull requests ?

@laurentyv good question…I unfortunately do not know off the top of my head, can you open a support ticket at support.circleci.com?

@sebastian-lerner can you confirm that the only way to control this setting is via the HTTP API? There is no setting in the UI or in the .circleci/config.yml file to do it?

Correct, at this time, the override enumerated in this post is only supported via the API. The “Only Bulid PRs” feature is available via the UI in Project Settings

It’s been a while I haven’t used Circle CI, and this would be a common feature that we can find in other CICD Tools.
Anyways, Can I use this override to filter by tags (using regex)?

@jheison-rodriguez I believe this will only work for branch names.

Yes, I confirm that only applies to branches names