Commit eae6778a authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'feature/2293-branch-name-push-rule' into 'master'

Create a push rule to check branch name

Closes #2293

See merge request !1896
parents e530453d 2fb820e1
...@@ -25,6 +25,6 @@ class Projects::PushRulesController < Projects::ApplicationController ...@@ -25,6 +25,6 @@ class Projects::PushRulesController < Projects::ApplicationController
# Only allow a trusted parameter "white list" through. # Only allow a trusted parameter "white list" through.
def push_rule_params def push_rule_params
params.require(:push_rule).permit(:deny_delete_tag, :delete_branch_regex, params.require(:push_rule).permit(:deny_delete_tag, :delete_branch_regex,
:commit_message_regex, :force_push_regex, :author_email_regex, :member_check, :file_name_regex, :max_file_size, :prevent_secrets) :commit_message_regex, :branch_name_regex, :force_push_regex, :author_email_regex, :member_check, :file_name_regex, :max_file_size, :prevent_secrets)
end end
end end
...@@ -8,6 +8,7 @@ class PushRule < ActiveRecord::Base ...@@ -8,6 +8,7 @@ class PushRule < ActiveRecord::Base
def commit_validation? def commit_validation?
commit_message_regex.present? || commit_message_regex.present? ||
branch_name_regex.present? ||
author_email_regex.present? || author_email_regex.present? ||
member_check || member_check ||
file_name_regex.present? || file_name_regex.present? ||
...@@ -19,6 +20,10 @@ class PushRule < ActiveRecord::Base ...@@ -19,6 +20,10 @@ class PushRule < ActiveRecord::Base
data_match?(message, commit_message_regex) data_match?(message, commit_message_regex)
end end
def branch_name_allowed?(branch)
data_match?(branch, branch_name_regex)
end
def author_email_allowed?(email) def author_email_allowed?(email)
data_match?(email, author_email_regex) data_match?(email, author_email_regex)
end end
......
...@@ -35,6 +35,15 @@ ...@@ -35,6 +35,15 @@
If this field is empty it allows any commit message. If this field is empty it allows any commit message.
For example you can require that an issue number is always mentioned in the commit message. For example you can require that an issue number is always mentioned in the commit message.
.form-group
= f.label :branch_name_regex, "Branch name", class: 'label-light'
= f.text_field :branch_name_regex, class: "form-control", placeholder: 'Example: (feature|hotfix)\/*'
.help-block
All branch names must match this
= link_to 'Ruby regular expression', 'http://www.ruby-doc.org/core-2.1.1/Regexp.html'
to be pushed.
If this field is empty it allows any branch name.
.form-group .form-group
= f.label :author_email_regex, "Commit author's email", class: 'label-light' = f.label :author_email_regex, "Commit author's email", class: 'label-light'
= f.text_field :author_email_regex, class: "form-control", placeholder: 'Example: @my-company.com$' = f.text_field :author_email_regex, class: "form-control", placeholder: 'Example: @my-company.com$'
......
---
title: Create a push rule to check the branch name
merge_request: 1896
author: Riccardo Padovani
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddPushRuleBranchName < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
add_column :push_rules, :branch_name_regex, :string
end
def down
remove_column :push_rules, :branch_name_regex
end
end
...@@ -1228,6 +1228,7 @@ ActiveRecord::Schema.define(version: 20170523091700) do ...@@ -1228,6 +1228,7 @@ ActiveRecord::Schema.define(version: 20170523091700) do
t.string "force_push_regex" t.string "force_push_regex"
t.string "delete_branch_regex" t.string "delete_branch_regex"
t.string "commit_message_regex" t.string "commit_message_regex"
t.string "branch_name_regex"
t.boolean "deny_delete_tag" t.boolean "deny_delete_tag"
t.integer "project_id" t.integer "project_id"
t.datetime "created_at" t.datetime "created_at"
......
...@@ -1263,6 +1263,7 @@ Parameters: ...@@ -1263,6 +1263,7 @@ Parameters:
"id": 1, "id": 1,
"project_id": 3, "project_id": 3,
"commit_message_regex": "Fixes \d +\", "commit_message_regex": "Fixes \d +\",
"branch_name_regex": "",
"deny_delete_tag": false, "deny_delete_tag": false,
"created_at": "2012-10-12T17:04:47Z", "created_at": "2012-10-12T17:04:47Z",
"member_check": false, "member_check": false,
...@@ -1290,6 +1291,7 @@ Parameters: ...@@ -1290,6 +1291,7 @@ Parameters:
| `member_check` | boolean | no | Restrict commits by author (email) to existing GitLab users | | `member_check` | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets | | `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets |
| `commit_message_regex` | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` | | `commit_message_regex` | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
| `branch_name_regex` | string | no | All branch names must match this, e.g. `(feature|hotfix)\/*` |
| `author_email_regex` | string | no | All commit author emails must match this, e.g. `@my-company.com$` | | `author_email_regex` | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
| `file_name_regex` | string | no | All commited filenames must **not** match this, e.g. `(jar|exe)$` | | `file_name_regex` | string | no | All commited filenames must **not** match this, e.g. `(jar|exe)$` |
| `max_file_size` | integer | no | Maximum file size (MB) | | `max_file_size` | integer | no | Maximum file size (MB) |
...@@ -1311,6 +1313,7 @@ Parameters: ...@@ -1311,6 +1313,7 @@ Parameters:
| `member_check` | boolean | no | Restrict commits by author (email) to existing GitLab users | | `member_check` | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets | | `prevent_secrets` | boolean | no | GitLab will reject any files that are likely to contain secrets |
| `commit_message_regex` | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` | | `commit_message_regex` | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
| `branch_name_regex` | string | no | All branch names must match this, e.g. `(feature|hotfix)\/*` |
| `author_email_regex` | string | no | All commit author emails must match this, e.g. `@my-company.com$` | | `author_email_regex` | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
| `file_name_regex` | string | no | All commited filenames must **not** match this, e.g. `(jar|exe)$` | | `file_name_regex` | string | no | All commited filenames must **not** match this, e.g. `(jar|exe)$` |
| `max_file_size` | integer | no | Maximum file size (MB) | | `max_file_size` | integer | no | Maximum file size (MB) |
......
doc/push_rules/push_rules.png

349 KB | W: | H:

doc/push_rules/push_rules.png

121 KB | W: | H:

doc/push_rules/push_rules.png
doc/push_rules/push_rules.png
doc/push_rules/push_rules.png
doc/push_rules/push_rules.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -65,7 +65,7 @@ module API ...@@ -65,7 +65,7 @@ module API
class ProjectPushRule < Grape::Entity class ProjectPushRule < Grape::Entity
expose :id, :project_id, :created_at expose :id, :project_id, :created_at
expose :commit_message_regex, :deny_delete_tag expose :commit_message_regex, :branch_name_regex, :deny_delete_tag
expose :member_check, :prevent_secrets, :author_email_regex expose :member_check, :prevent_secrets, :author_email_regex
expose :file_name_regex, :max_file_size expose :file_name_regex, :max_file_size
end end
......
...@@ -13,11 +13,12 @@ module API ...@@ -13,11 +13,12 @@ module API
optional :member_check, type: Boolean, desc: 'Restrict commits by author (email) to existing GitLab users' optional :member_check, type: Boolean, desc: 'Restrict commits by author (email) to existing GitLab users'
optional :prevent_secrets, type: Boolean, desc: 'GitLab will reject any files that are likely to contain secrets' optional :prevent_secrets, type: Boolean, desc: 'GitLab will reject any files that are likely to contain secrets'
optional :commit_message_regex, type: String, desc: 'All commit messages must match this' optional :commit_message_regex, type: String, desc: 'All commit messages must match this'
optional :branch_name_regex, type: String, desc: 'All branches names must match this'
optional :author_email_regex, type: String, desc: 'All commit author emails must match this' optional :author_email_regex, type: String, desc: 'All commit author emails must match this'
optional :file_name_regex, type: String, desc: 'All commited filenames must not match this' optional :file_name_regex, type: String, desc: 'All commited filenames must not match this'
optional :max_file_size, type: Integer, desc: 'Maximum file size (MB)' optional :max_file_size, type: Integer, desc: 'Maximum file size (MB)'
at_least_one_of :deny_delete_tag, :member_check, :prevent_secrets, at_least_one_of :deny_delete_tag, :member_check, :prevent_secrets,
:commit_message_regex, :author_email_regex, :commit_message_regex, :branch_name_regex, :author_email_regex,
:file_name_regex, :max_file_size :file_name_regex, :max_file_size
end end
end end
......
...@@ -174,6 +174,10 @@ module Gitlab ...@@ -174,6 +174,10 @@ module Gitlab
return "Commit message does not follow the pattern '#{push_rule.commit_message_regex}'" return "Commit message does not follow the pattern '#{push_rule.commit_message_regex}'"
end end
if @branch_name && !push_rule.branch_name_allowed?(@branch_name)
return "Branch name does not follow the pattern '#{push_rule.branch_name_regex}'"
end
unless push_rule.author_email_allowed?(commit.committer_email) unless push_rule.author_email_allowed?(commit.committer_email)
return "Committer's email '#{commit.committer_email}' does not follow the pattern '#{push_rule.author_email_regex}'" return "Committer's email '#{commit.committer_email}' does not follow the pattern '#{push_rule.author_email_regex}'"
end end
......
...@@ -41,6 +41,7 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -41,6 +41,7 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
post api("/projects/#{project.id}/push_rule", user), post api("/projects/#{project.id}/push_rule", user),
deny_delete_tag: true, member_check: true, prevent_secrets: true, deny_delete_tag: true, member_check: true, prevent_secrets: true,
commit_message_regex: 'JIRA\-\d+', commit_message_regex: 'JIRA\-\d+',
branch_name_regex: '(feature|hotfix)\/*',
author_email_regex: '[a-zA-Z0-9]+@gitlab.com', author_email_regex: '[a-zA-Z0-9]+@gitlab.com',
file_name_regex: '[a-zA-Z0-9]+.key', file_name_regex: '[a-zA-Z0-9]+.key',
max_file_size: 5 max_file_size: 5
...@@ -51,6 +52,7 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do ...@@ -51,6 +52,7 @@ describe API::ProjectPushRule, 'ProjectPushRule', api: true do
expect(json_response['member_check']).to eq(true) expect(json_response['member_check']).to eq(true)
expect(json_response['prevent_secrets']).to eq(true) expect(json_response['prevent_secrets']).to eq(true)
expect(json_response['commit_message_regex']).to eq('JIRA\-\d+') expect(json_response['commit_message_regex']).to eq('JIRA\-\d+')
expect(json_response['branch_name_regex']).to eq('(feature|hotfix)\/*')
expect(json_response['author_email_regex']).to eq('[a-zA-Z0-9]+@gitlab.com') expect(json_response['author_email_regex']).to eq('[a-zA-Z0-9]+@gitlab.com')
expect(json_response['file_name_regex']).to eq('[a-zA-Z0-9]+.key') expect(json_response['file_name_regex']).to eq('[a-zA-Z0-9]+.key')
expect(json_response['max_file_size']).to eq(5) expect(json_response['max_file_size']).to eq(5)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment