JetBrains Space Help

Set Up Branch and Merge Restrictions

While project roles give you the ability to manage write an read permissions in repositories, that alone may not be enough to ensure code quality and efficient collaboration.

Branch protection settings let you safeguard important branches from inadvertent actions and undesirable changes without imposing excessive restrictions on the entire repository.

By creating security rules for a specific branch, you can:

  • Prevent accidental branch deletion.

  • Restrict who can push or force push to the branch.

  • Restrict who can merge changes into the branch.

  • Enable Quality Gates to ensure that only successfully tested, reviewed and approved changes find their way into the branch.

For example, you can prohibit direct pushes to main and require that all changes be submitted via merge requests, pass certain automated checks and have enough approvals from a specified group of members before they can be merged into main.

To set up a branch protection rule:

  1. Open the Repository Settings page.

  2. Go to the Protected Branches tab.

  3. Existing rules (if any) are listed on this page.

    • To edit an existing rule, click edit.png next to it.

    • To create a new rule, click New rule.

  4. Refer to the descriptions below to configure the restrictions and press Save when done.

Specify the branches

Specify branches which should be affected by restrictions in this rule. You can add one specific branch, several branches at a time, all branches, or any branch that matches a naming pattern. Use the following syntax:

  • Enter +:<branch name> to include a branch (e.g. +:refs/heads/main).

  • Enter -:<branch name> to exclude a branch (e.g. -:refs/heads/main).

  • Use * as a wildcard. For example, +:* will include all branches.

  • To specify branches which names contain a specific string, enclose that string in asterisks. For example, to include all branches containing prod (e.g. production, prod-1, etc.), enter: +:*prod*.

branchProtectionRule.png

Regulated Actions

Specify members, roles, or applications that should be allowed to perform the following actions:

  • Create a new branch (from the protected branches specified in this rule).

  • Push to the protected branches.

  • Force push to the protected branches.

  • Delete the protected branches.

regulatedActions.png

If you're going to enable the Quality Gates (described below) and require committers to submit their changes via merge requests, remove All committers from the Push and Force push fields and add only those who are allowed to bypass the restrictions.

Quality Gates for Merge Requests

To ensure that only verified and approved commits are merged into a protected branch, you can set up a number of requirements and conditions that should be met before merging.

With the quality gates enabled, a committer should first push their changes to another branch and create a merge request for their commit, specifying the protected branch as a target. The commit can be merged only if and when it satisfies the quality gates requirements specified here — e.g. after it passes selected automated checks it triggered and/or gets sufficient number of approvals from specified members.

Turn the switch On to configure and enable these settings.

qualityGatesOn.png

Members Required to Pass Quality Gates

Specify members who will be allowed to execute a merge into a protected branch once all conditions are met. If you add a role (e.g. Project Admin), all members which have that role will get the right to merge.

Make sure you have the Push and Force push actions restricted in the Regulated Actions section above. Otherwise, all project members will be able to push directly to the protected branch, bypassing the quality gates conditions.

Requirements:

  • Approvals

    Allow to merge changes only if they are reviewed and approved by specified members.

    • Require approval from code owners: changes made to the files owned by specific members will have to be approved by these members to allow the merge. File ownership should be defined in the CODEOWNERS file in advance. For information on how to set up the CODEOWNERS file, please read Code Owners.

    • Choose members whose approval is required and specify how many out of the selected members must approve the changes to allow the merge (e.g. any 2 members out of 5 selected).

  • Jobs

    If you have any Automation jobs set up to run on commits in your repository, they will be listed here. You can select all or any of them as a quality gates condition.

    All selected jobs, if triggered by the commit, must complete successfully to pass the gates.

  • External checks

    If your repository receives build statues from an external CI service (such as TeamCity, Jenkins), you can require one or more status checks to pass on a commit before allowing it to be merged.

    Each service connected to your repository will be listed here along with the checks they run. Select services that must complete successfully to pass the quality gates.

  • Safe Merge

    Safe Merge executes predefined Automation jobs or external checks (currently, TeamCity only) upon a virtual merge commit it creates, and merges permanently only if the checks are successful.

    Read more about Safe Merge below.

Safe Merge

As opposed to pre-merge quality checks described above which run on feature branch commits, Safe Merge lets you execute quality checks on the merge commit, but without necessarily completing the merge. It checks a temporary merge commit it creates and allows you to merge only if the checks are successful. Think of it as a little time machine that lets you have a glimpse at the future build status, as if the feature branch has been already merged.

Why use Safe Merge

Safe Merge adds an extra layer of protection to your main (protected) branch, ensuring that it passes automated quality checks after a feature branch has been merged into it and that a merge commit doesn't result in failed builds.

While pre-merge checks (jobs and external checks) prevent unverified commits to be merged into main, they alone can't guarantee a fail-proof merge because of the following:

  • Pre-merge checks only run on the feature-branch head commits prior to merge, and they don't take into account the current state of main.

  • Meanwhile, the main branch could have deviated significantly and can now contain changes that will cause a semantic conflict with your feature branch after the merge, compromising the build.

That is especially true in the fast-paced dev environment, when several developers are working on a project simultaneously, and long-lived feature branches are part of a normal workflow.

With Safe Merge you address this problem by running integration checks on the requested merge without actually merging potentially harmful changes into main. To accomplish that, Safe Merge creates a temporary merge commit, combining the most recent main and feature branch revisions, then tests this commit with predefined automation jobs or TeamCity checks. If everything is okay, you are allowed to permanently merge your feature branch into the main.

Set up and enable Safe Merge

To set up Safe Merge, you need to create a configuration file in your repository with references to jobs and/or TeamCity checks that should be executed upon merge.

You can optionally set it up in such a way that quality checks will be triggered only if specific files in feature branch have been changed before the merge.

  1. Decide what Automation jobs and/or TeamCity quality checks will be triggered by Safe Merge. Read Quality Gates best practices: What automated checks to use and when for more info.

  2. If your Safe Merge configuration is going to trigger TeamCity quality checks, you need to integrate your Space project with TeamCity to receive commit (build) statuses from the TeamCity's Commit Status Publisher.

  3. Create a .json configuration file in your repository:

    • Navigate to the Safe Merge section of your Branch protection rule settings.

    • Turn the Safe Merge ON and click Create:

      safeMergeOnCreate.png
    • You can edit the file name and location within your repository. Just make sure to keep the .json format. Click Create:

      safeMergeConfigCreate.png

      A blank config file with code examples on the side panel will be displayed.

    • Create your Safe Merge configuration. Here is the most basic configuration which triggers only one Automation job:

      safeMergeConfigBasicExample.png

      Use sample code on the side panel and refer to the configuration example and syntax description to create your own configuration.

    • When you're done, click Save and Commit your configuration file. The file will be pushed and linked to the protected branch defined in your branch protection rule.

    Alternatively, you can create a Safe Merge configuration file from your IDE:

    • Create a .json file with a distinctive name and push it to the protected branch of your repository.

    • Navigate to the Safe Merge section of your Branch protection rule settings .

    • Turn the Safe Merge ON and click Select:

      safeMergeOnSelect.png
    • Select the configuration file you've created and click Save.

    • Your configuration file will be linked to the protected branch and displayed in the Safe Merge settings section:

      safeMergeConfigLinked.png

Safe Merge configuration example and syntax description

Refer to the following example and syntax description to create your configuration.

Example. The file contains an array of objects, where each object is a reference to a predefined Automation job or TeamCity check (build configuration). In this example, there are two Automation jobs and one TeamCity build configuration. One of the jobs also includes the paths to changed files as a condition for triggering that job.

{ "version": "1.0", "retry-policy": { "num-retries": 3, "reuse-merge": true }, "builds": [ { "job": { "name": "UI Tests" } }, { "job": { "name": "Performance Tests" }, "changed-files": [ "/platform/**", "/deployments/**" ] }, { "teamcity": { "configuration": "Integration Tests", "url": "https://myteamcityserver.net", "token": "${teamcity-safe-merge}", "ssl-keystore": "TeamCityServer client" } } ] }

Parameter

Description

"version":

Safe Merge version number. Should be "1.0"

"retry-policy":

Optional. Sometimes builds fail due to flaky tests. To rerun failed builds, you can set retry policy using the "num-retries" and "reuse-merge" parameters (see below).

"num-retries":

Specify the total number of retries in case a build fails (doesn't pass quality checks). The default value is 0.

"reuse-merge":

Specify if the same temporary merge commit should be used on retry (true), or a new temporary merge commit should be created on each retry (false).

"builds":

List references to Automation jobs or TeamCity build configurations as array objects.

"job": { "name": }

Specify the name of the job in your project that should be triggered by Safe Merge and run on merge commit.

"teamcity":

Specify the TeamCity build configuration that should be triggered by Safe Merge and run on merge commit. Specify all required parameters (configuration, url, token, ssl-keystore).

"configuration":

Name of the TeamCity build configuration.

"url":

URL of your TeamCity server.

"token":

Key of the secret used for authenticating TeamCity. To look up the secret:

  1. On the project sidebar, click Settings.

  2. Go to the Secrets and Parameters tab.

The token created on the TeamCity side should have the following permissions:

  • Run build

  • Stop / remove from queue any personal build

  • Stop build / remove from queue

  • View build configuration settings

  • View build runtime parameters and data

"ssl-keystore":

Optional. If your TeamCity configuration uses ssl certificate, specify the name of the certificate keystore. To look it up, go to Administration -> SSL Keystores. Read SSL Keystores for details.

"changed-files":

Optional. A job or TeamCity check will run only if the specified filed have been changed.

Each line specifies a pattern that matches a file or directory.

Example 1:

"changed-files": [ "/tests/**", "/clients/client.kts" ]

Matches files inside the directory tests and its subdirectories and the file client.kts in the directory clients.

Example 2:

"changed-files": [ "*", "!/deployments/**", "!/apps/app.kts" ]

Matches all files, except for:

  • files inside the directory deployments and its subdirectories

  • file app.kts located in the directory apps

The pattern format and syntax is identical to the one used in gitignore files. See detailed syntax description.

Using Safe Merge

After configuring and enabling Safe Merge you and your team can start using it.

The Merge button on the Merge Request page will be replaced with Safe Merge. Hitting this button will create a temporary merge commit and execute quality checks specified in your Safe Merge configuration file. If the checks are successful, you'll be prompted to complete the merge.

If you just want to test your future merge and don't intend to complete it, you can press Dry Run. In this case you won't be prompted to complete the merge even if it passes all the checks.

safeMergeButton.png

Quality Gates best practices: What automated checks to use and when

Quality Gates let you set up the most effective merging requirements policy for your specific project without compromising the safety of its code base and without slowing down the development process.

While your actual setup will depend on your project specifics, such as what automated checks and tests are used and what development workflow is adapted by your team, you can use the following rules as a general guidance:

  • In small projects with few participants, you can do without Safe Merge, limiting the Quality Gates requirements to a reviewer approval and pre-merge jobs or TeamCity checks that will run on feature branch heads.

  • For active projects with a large number of developers, high daily volume of commits, and long-lived feature branches, Safe Merge is the best solution. You can set it up in addition to or instead of feature branch (pre-merge) checks, depending on your build configuration and the size of the checks you're running.

  • To speed up development, it's best to run only light checks on a feature branch, leaving all the heavy integration checks for Safe Merge that will only run once. With this approach you will avoid running extensive time-consuming checks on every minor fix-up commit, effectively shortening the life of your merge request.

Example of a protected branch configuration

Let's consider a common scenario where your repository has a lot of contributors and a main branch reserved for production. To keep the main branch healthy, you don't want any changes pushed to it, unless they are reviewed and approved by at least one experienced developer. Since you have Space automation set up to run test jobs on commits, you also want all commits to pass automated status checks before they can be submitted to main.

Here is how you should configure your branch protection settings:

  1. Open the Repository Settings page and go to the Protected Branches tab:

    repositorySettingsProtectedBranches.png
  2. Click New rule to open the form.

  3. Specify main as your protected branch.

    protectedBranchExamplePattern.png
  4. Allow no one to Push and Force push to main, but allow all committers to create new branches from main.

    You obviously don't want main accidentally deleted, hence allow this action to no one.

    protectedBranchExampleActions.png
  5. Turn on the Quality Gates settings.

  6. You want to allow every committer to merge changes to main after they pass all the requirements:

    protectedBranchExampleMerge.png
  7. You don't want any changes merged unless they've been reviewed and approved by at least one of these three members:

    protectedBranchExampleApprovals.png
  8. At last, you want all commits to successfully pass automated checks before they can be merged to main, so you select the jobs listed here as a requirement:

    protectedBranchExampleJobs.png
  9. Don't forget to Save your configuration. You can always view and edit it on the Repository Settings page under the Protected Branches tab:

    protectedBranchExampleView.png
Last modified: 25 November 2022