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
andproject-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 namedmain-3
andmain-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 totrue
or via the Project Settings UI under the “Advanced” section
- You can verify this via the API response by observing the boolean
- 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": [],
}