Screenshot from Control Freak for Bitbucket Server rejecting a foxtrot.
bit-booster monster

Control Freak
for Bitbucket Server

Documentation
 
June 2018

Table of Contents

Introduction

Control Freak for Bitbucket Server allows Bitbucket admins to define and encourage consistent git policy across all projects and repositories within their Bitbucket Server and Bitbucket Datacenter installations.

Advantages

  • Global Git policy configured in one place
  • Branching Model binds rules to branch groups
  • Improved performance
  • Compatible with Fork-Based Workflows

The add-on accomplishes this through independent rule groups. Admins can define JIRA policy, branch naming policy, rebase policy, commit authorship policy, etc. The add-on also includes rules to help prevent common nuisances in git repos such as foxtrot merges or accidental multi-rewrite pushes.

A master ruleset is defined once through the global config screen. By default the policy is enabled for all normal non-empty repos, but per-project and per-repo kill switches are available. A subset of the rules can also be overridden per-project or per-repo.

Problem

Bitbucket comes with many powerful configuration options and add-ons to help enforce repository policy (e.g., branch permissions, hooks, merge checks). But setting these up for each newly created repository is repetitive and error-prone, and not everyone with the "Create New Repository" permissions is always aware of their organization's preferred setup.

Control Freak for Bitbucket Server solves this problem by allowing admins to define a global default that is applied to all repositories. Projects and repos where the global settings are inappropriate can opt-out or override to suit their own needs. This results in more repositories that comply with the organization's preferred setup, thanks to this "opt-out" approach rather than Bitbucket's out-of-the-box "opt-in" approach.

Installation Requirements

  1. Install this add-on using Bitbucket's "Manage Add-Ons" page, or from our Atlassian Marketplace page: https://marketplace.atlassian.com/plugins/com.bit-booster.bb.hooks
  2. You must be using version 5.0.0 of Bitbucket Server or newer.
  3. Optional: to enable the online components of the JIRA Git Policy, your JIRA administrator must connect JIRA to your Bitbucket Server instance via the “Application Link” feature of JIRA.
     
    (Note: if you have more than one JIRA instance connected to your Bitbucket, this add-on will only use the application link marked as “primary”. This is a temporary limitation we plan to address by Q4 2018).

Enabling Your Global Git Policy

The very top of the global config screen includes the enable/disable control:

Enabled For:
Regular
Repos
Regular
Forks
Personal
Repos
Personal
Forks
Empty
Repos

By default Control Freak for Bitbucket Server is enabled for regular repositories and regular forks, and disabled for all other types. Note: repositories can also be moved between the personal and project areas of Bitbucket. After a move, the configured policy will apply to all new commits, but older commits are grandfathered. The repository types are:

  • Regular Repos - These are regular repositories created using the "new repository" function within a project.
  • Regular Forks - These are forked repositories created using the "fork repository" function where a project is chosen as the target location for the new fork.
  • Personal Repos - These are repositories created using the "new repository" function within a user's personal area in Bitbucket.
  • Personal Forks - These are forked repositories created using the "fork repository" function where a user's personal area is chosen as the target location for the new fork.
  • Empty Repos - Any repository without any commits is considered an empty repository. Disabling the global policy for empty repositories helps admins importing repos from other sources (e.g., Github or after a svn2git conversion), since the git policy is likely to complain about many of the imported commits. After an initial import the policy is enabled for all subsequent commits, since the repository is no longer considered empty.

Authorship Policy

Authorship policy inspects the "Author" and "Committer" metadata for each incoming commit, and accepts or rejects the commit based on the selected rules. The user's email address and display name (as recorded in the commit metadata) must match exactly the values stored in Bitbucket to satisfy these rules. By default all three of these rules are disabled.
Authorship Policy:

  • Author must be a valid Bitbucket User - If enabled, all new commits arriving via push (or via merge if coming from a fork) must contain author values that match existing records inside Bitbucket's user database.
    remote: -----
    remote: Commit eafef78364395ce7 rejected: bad author metadata.
    remote: Author "Admin <admin@bit-booster.com>" does not exactly match
    remote: a Bitbucket user record. The closest match is:
    remote:
    remote:     "Administrator <admin@example.com>"
    remote:
    remote: To see the bad commit's metadata:
    remote:
    remote:     git show -s --pretty=fuller eafef78364395ce78a097134e8f8d6
    remote:
    remote: Please have a Bitbucket admin edit the corresponding user record
    remote: so it matches your settings. Alternatively, adjust your own config
    remote: and adjust the problematic commit(s).
    remote: Like so:
    remote:
    remote:     git config --global user.name "Administrator"
    remote:     git config --global user.email admin@example.com
    remote:     git commit --amend --reset-author
    remote:
    remote: Adjusting author metadata in older commits is difficult.
    remote: Detailed instructions here:  https://bit-booster.com/author.html
    remote: -----
    
  • Committer must be a valid Bitbucket User - If enabled, all new commits arriving via push (or via merge if coming from a fork) must contain committer values that match existing records inside Bitbucket's user database. We recommend enabling this rule.
    remote: -----
    remote: Commit 3188d70b921955e5 rejected: bad committer metadata.
    remote: Committer "G. Sylvie Davies <sylvie@bit-booster.com>" is not known to Bitbucket.
    remote: To see the bad commit's metadata:
    remote:
    remote:     git show -s --pretty=fuller 3188d70b921955e560800eab04128b
    remote:
    remote: Please have a Bitbucket admin create or adjust a Bitbucket user record
    remote: to match your settings. Alternatively, adjust your own config and amend
    remote: the problematic commit(s) so they match a known user.
    remote: For example:
    remote:
    remote:     git config --global user.name "Known User"
    remote:     git config --global user.email known.user@example.com
    remote:     git rebase --force-rebase
    remote:
    remote: Note: the rebase will drop unpushed merges. Usually that's fine.
    remote: -----
    
  • Committer must be current logged-in user - If enabled, all new commits arriving via push (or via merge if coming from a fork) must contain a committer value that exactly matches the email address and display name of the current logged-in Bitbucket user performing the operation.
    remote: Commit 3188d70b921955e5 rejected: bad committer metadata.
    remote: "G. Sylvie Davies <sylvie@bit-booster.com>" does not match your.
    remote: credentials. You are logged in as:. "Administrator <admin@example.com>".
    remote: To see the bad commit's metadata:
    remote:
    remote:     git show -s --pretty=fuller 3188d70b921955e560800eab04128b
    remote:
    remote: Have "G. Sylvie Davies <sylvie@bit-booster.com>" push their own commits.
    remote: Or use the following git commands to adjust the committer metadata:
    remote:
    remote:     git config --global user.name "Administrator"
    remote:     git config --global user.email admin@example.com
    remote:     git rebase --force-rebase
    remote:
    remote: Note: the rebase will drop unpushed merges. Usually that's fine.
    

Branch Naming Policy

New Branch Names
Must Match:


remote: -----
remote: Push rejected branch name: "abc".
remote: New branches must comply with the repository's branching model.
remote: Allowed names: bugfix/*, feature/*, hotfix/*, release/*
remote: -----
remote: -----
remote: Push rejected branch name: "abc".
remote: New branch names must contain a JIRA ticket.
remote: -----
remote: -----
remote: Push rejected new branch: "ABC-1"
remote: Your Bitbucket instance does not have an application link to a JIRA instance.
remote: Please configure your Bitbucket instance.
remote: (Or disable the JIRA branch check of this global hook.)
remote: -----
remote: -----
remote: New branch names must contain a JIRA ticket, but Bitbucket
remote: cannot access JIRA to see if "[ABC-1]" exists.
remote: Your Bitbucket account is missing OAUTH credentials into JIRA.
remote:
remote: Use this URL to set that up:
remote: http://localhost:7990/bitbucket/plugins/servlet/applinks/oauth/login-dance/authorize
remote: -----
remote: -----
remote: Push rejected new branch: "ABC-1".
remote: ticket "ABC-1" does not exist in JIRA.
remote: -----
remote: -----
remote: Push rejected branch name: "ABC-1"
remote: New branches must satisfy the configured branch regex.
remote: Failed Regex: (.*xyz)
remote: -----

Tag Pushing Policy

Allow Tag Pushes:

remote: -----
remote: PUSHED TAG DELETES ARE NOT PERMITTED!
remote: Sorry, you cannot delete tag "signed_tag" via git push.
remote: Please delete tags using Bitbucket's web UI instead.
remote:
remote: To reset your tags to match Bitbucket's (if 'origin' is Bitbucket):
remote:
remote: git fetch --prune origin "+refs/tags/*:refs/tags/*"
remote: -----
remote: -----
remote: PUSHED TAG CREATES/EDITS ARE NOT PERMITTED!
remote: Sorry, you cannot create tag "1.2.3" via git push.
remote: Please create tags using Bitbucket's web UI instead.
remote:
remote: To reset your tags to match Bitbucket's (if 'origin' is Bitbucket):
remote:
remote: git fetch --prune origin "+refs/tags/*:refs/tags/*"
remote: -----

Foxtrot Policy

Block Foxtrot Merges On:       
   
remote: -----
remote: Commit rejected. Foxtrot merges not allowed on "master".
remote:
remote: Commit 7a5fea716c2048f contains a foxtrot merge.
remote: A rebase will repair the problem:
remote:
remote:   git rebase origin/master
remote:
remote: Alternatively, redo the merge in the opposite direction.
remote: -----

Branch Pushing Policy (a.k.a. Protected Branches)

Block Branch Deletes On:       
Block History Rewrites On:
Block "force pushes" 
       
Always Require Pull-Requests:       
Block Multi-Rewrites:
Avoid push.default=matching disasters 
     
remote: -----
remote: Push rejected.
remote: You are not allowed to delete branch "master".
remote: -----
remote: -----
remote: Push rejected.
remote: History rewrites not allowed on "release/ABC-1".
remote: -----
remote: -----
remote: Push rejected. Direct pushes not allowed on "release/ABC-1".
remote: This branch can only be modified through pull requests.
remote: -----
remote: -----
remote: Push rejected. Multiple history rewrites
remote: in a single push not allowed.
remote:
remote: Is your "push.default" config is set to "matching"?
remote: Try setting it to "simple" instead.
remote:
remote: Trying to mirror a repo? In that case, disable
remote: "Control Freak for Bitbucket Server" for this repository.
remote: (Repository Settings -> Control Freak)
remote: -----

Rebase Policy

Require Fast-Forwardable Merges Into:
Merges-between selected not blocked  
       
Require Squashed Merges Into:
Merges-between selected not blocked  
       
Merge issues

There is 1 issue preventing you from merging this pull request.

  • Control Freak for Bitbucket Server: [master] only permits fast-forward merges - you must rebase or squash [TKT-123]
Merge issues

There is 1 issue preventing you from merging this pull request.

  • Control Freak for Bitbucket Server: [master] only permits merges from squashed branches, but [TKT-123] has 2 commits

JIRA Policy

Apply JIRA Policy Against:       
   

1. JIRA Commit Message Rules (Offline Checks)

Commit Messages Must:
Look for JIRA References:
Only Check JIRAs In Brackets:
"[TKT-8, TKT-9] UTF-8 bugs in TKT-5" 

2. JIRA Reference Rules (Online Checks)

JIRA References Must:


Invalid statuses:
JIRA Project Key Blacklist:
Ignore these JIRA imposters  
remote: -----
remote: Commit 347f2a9089f5b39a rejected.
remote: It does not reference a JIRA ticket in its commit message.
remote: Note: JIRA references must be in the first line of the commit message.
remote:       Also, they must be in brackets, e.g., [TKT-123].
remote:
remote: To see the commit message:
remote:
remote:   git show -s 347f2a9089f5b39a
remote:
remote: To edit the commit message:
remote:
remote:   git rebase --interactive
remote:
remote: (Mark the commits to edit with 'reword' in the dialog).
remote: -----
remote: -----
remote: Commit messages on "master" must reference valid JIRA tickets,
remote: but Bitbucket cannot access JIRA to see if "[ABC-1]" exists.
remote: Your Bitbucket account is missing OAUTH credentials into JIRA.
remote:
remote: Use this URL to set that up:
remote: http://localhost:7990/bitbucket/plugins/servlet/applinks/oauth/login-dance/authorize
remote: -----
remote: -----
remote: Commit rejected.
remote: Commits on "master" must satisfy JIRA policy.
remote: The following JIRA tickets do not exist on your JIRA server:
remote:
remote:   [ABC-1].
remote:
remote: Please remove references to those tickets from your commit messages.
remote: -----
remote: -----
remote: Push rejected. Commits to "master" must satisfy JIRA policy.
remote: The following JIRA tickets have invalid statuses for receiving commits:
remote:
remote:   [ABC-1] - Done.
remote:
remote: Either remove references to those tickets from your commit messages,
remote: or adjust the tickets in JIRA so they satisfy the status check.
remote: -----
remote: -----
remote: Push rejected. Commits to "master" must satisfy JIRA policy.
remote: Some referenced JIRA tickets failed the JQL validation check.
remote:
remote: JQL:   "TYPE != task"
remote:
remote: Failing JIRA tickets:
remote:
remote:   [ABC-1].
remote:
remote: Either remove references to those tickets from your commit messages,
remote: or adjust the tickets in JIRA so they satisfy the JQL validation.
remote: -----

remote: -----
remote: Push rejected.
remote: Commits to "master" must satisfy JIRA policy.
remote: Commit 0001b282b756e1d1 was authored by [sylvie@bit-booster.com],
remote: but "TKT-1" is currently assigned to [unassigned].
remote: -----