diff --git a/CHANGELOG b/CHANGELOG index 8e054cec7c5118fad372c8df0678668764703d8f..b27291b6f1922f2854d875ed315fc19a3b2d959c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -30,6 +30,8 @@ v 7.8.0 - - Async load a branch information at the commit page - + - Allow configuring protection of the default branch upon first push (Marco Wessel) + - - - Add a commit calendar to the user profile (Hannes Rosenögger) - diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index a937f484877532f4e919d0bbfa8fb52496088db1..7458542fc73ca55e2f7e27c147d45a7cb5033a15 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -22,6 +22,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController def application_setting_params params.require(:application_setting).permit( :default_projects_limit, + :default_branch_protection, :signup_enabled, :signin_enabled, :gravatar_enabled, diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 0b3d430add0a387d9b420e548060bcb57a4e4cb3..6d4e220b16c0a52b544852c3f5eae55c96f5ac3f 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -4,6 +4,7 @@ # # id :integer not null, primary key # default_projects_limit :integer +# default_branch_protection :integer # signup_enabled :boolean # signin_enabled :boolean # gravatar_enabled :boolean @@ -26,6 +27,7 @@ class ApplicationSetting < ActiveRecord::Base def self.create_from_defaults create( default_projects_limit: Settings.gitlab['default_projects_limit'], + default_branch_protection: Settings.gitlab['default_branch_protection'], signup_enabled: Settings.gitlab['signup_enabled'], signin_enabled: Settings.gitlab['signin_enabled'], gravatar_enabled: Settings.gravatar['enabled'], diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 872b886c575a80f36d03b6937b6f954e37f828d9..c775f79ec291c88c2a194ab147b0a2078f026425 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -1,5 +1,7 @@ class GitPushService attr_accessor :project, :user, :push_data, :push_commits + include Gitlab::CurrentSettings + include Gitlab::Access # This method will be called after each git update # and only if the provided user and project is present in GitLab. @@ -29,8 +31,12 @@ class GitPushService if is_default_branch?(ref) # Initial push to the default branch. Take the full history of that branch as "newly pushed". @push_commits = project.repository.commits(newrev) - # Default branch is protected by default - project.protected_branches.create({ name: project.default_branch }) + + # Set protection on the default branch if configured + if (current_application_settings.default_branch_protection != PROTECTION_NONE) + developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false + project.protected_branches.create({ name: project.default_branch, developers_can_push: developers_can_push }) + end else # Use the pushed commits that aren't reachable by the default branch # as a heuristic. This may include more commits than are actually pushed, but diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 9423a207068aaef4df53333278a57d10fde7becf..bf0ee49d2f43c418e7b1337c9fe78d107645a1d3 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -25,6 +25,10 @@ = f.label :default_projects_limit, class: 'control-label' .col-sm-10 = f.number_field :default_projects_limit, class: 'form-control' + .form-group + = f.label :default_branch_protection, class: 'control-label' + .col-sm-10 + = f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control' .form-group = f.label :home_page_url, class: 'control-label' .col-sm-10 diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 4296e7553700ceb76e3aed677e5ae4c2a12eab56..24f39f5b3c1a7a96090d71810c7e1c0b615d5d19 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -87,6 +87,7 @@ Settings['issues_tracker'] ||= {} # Settings['gitlab'] ||= Settingslogic.new({}) Settings.gitlab['default_projects_limit'] ||= 10 +Settings.gitlab['default_branch_protection'] ||= 2 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? Settings.gitlab['default_theme'] = Gitlab::Theme::MARS if Settings.gitlab['default_theme'].nil? Settings.gitlab['host'] ||= 'localhost' diff --git a/db/migrate/20150125163100_add_default_branch_protection_setting.rb b/db/migrate/20150125163100_add_default_branch_protection_setting.rb new file mode 100644 index 0000000000000000000000000000000000000000..5020daf55f3df10ce2f8e79decd331ebdd168751 --- /dev/null +++ b/db/migrate/20150125163100_add_default_branch_protection_setting.rb @@ -0,0 +1,5 @@ +class AddDefaultBranchProtectionSetting < ActiveRecord::Migration + def change + add_column :application_settings, :default_branch_protection, :integer, :default => 2 + end +end diff --git a/db/schema.rb b/db/schema.rb index 3f9ceb84e5d7fe79ddc543f45cca362cc01c671e..0e4af3df7c256beb621c26f538f2d1aca378d1a1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150116234545) do +ActiveRecord::Schema.define(version: 20150125163100) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -25,6 +25,7 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.datetime "created_at" t.datetime "updated_at" t.string "home_page_url" + t.integer "default_branch_protection", default: 2 end create_table "broadcast_messages", force: true do |t| @@ -322,12 +323,12 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.string "import_url" t.integer "visibility_level", default: 0, null: false t.boolean "archived", default: false, null: false + t.string "avatar" t.string "import_status" t.float "repository_size", default: 0.0 t.integer "star_count", default: 0, null: false t.string "import_type" t.string "import_source" - t.string "avatar" end add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree @@ -425,6 +426,7 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.integer "notification_level", default: 1, null: false t.datetime "password_expires_at" t.integer "created_by_id" + t.datetime "last_credential_check_at" t.string "avatar" t.string "confirmation_token" t.datetime "confirmed_at" @@ -432,7 +434,6 @@ ActiveRecord::Schema.define(version: 20150116234545) do t.string "unconfirmed_email" t.boolean "hide_no_ssh_key", default: false t.string "website_url", default: "", null: false - t.datetime "last_credential_check_at" t.string "github_access_token" t.string "gitlab_access_token" end diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb index 411b2b9a3cc7e014ce20134ff91c9ba2e04a37b9..424541b4a04c259b5e5de0761f7f7d03fec61d28 100644 --- a/lib/gitlab/access.rb +++ b/lib/gitlab/access.rb @@ -11,6 +11,11 @@ module Gitlab MASTER = 40 OWNER = 50 + # Branch protection settings + PROTECTION_NONE = 0 + PROTECTION_DEV_CAN_PUSH = 1 + PROTECTION_FULL = 2 + class << self def values options.values @@ -43,6 +48,18 @@ module Gitlab master: MASTER, } end + + def protection_options + { + "Not protected, developers and masters can (force) push and delete the branch" => PROTECTION_NONE, + "Partially protected, developers can also push but prevent all force pushes and deletion" => PROTECTION_DEV_CAN_PUSH, + "Fully protected, only masters can push and prevent all force pushes and deletion" => PROTECTION_FULL, + } + end + + def protection_values + protection_options.values + end end def human_access diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 2c5660df37397df1d0963f57100a11fc8fb428a8..93e7edf508c1bf516568b78ff71e292b66ed487c 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -12,6 +12,7 @@ module Gitlab def fake_application_settings OpenStruct.new( default_projects_limit: Settings.gitlab['default_projects_limit'], + default_branch_protection: Settings.gitlab['default_branch_protection'], signup_enabled: Settings.gitlab['signup_enabled'], signin_enabled: Settings.gitlab['signin_enabled'], gravatar_enabled: Settings.gravatar['enabled'], diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 1723eba9ec339e2988305771cfb369f928d1e87e..cd6d03e6c1a6bd3688831470610421f09972e833 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -2,15 +2,16 @@ # # Table name: application_settings # -# id :integer not null, primary key -# default_projects_limit :integer -# signup_enabled :boolean -# signin_enabled :boolean -# gravatar_enabled :boolean -# sign_in_text :text -# created_at :datetime -# updated_at :datetime -# home_page_url :string(255) +# id :integer not null, primary key +# default_projects_limit :integer +# default_branch_protection :integer +# signup_enabled :boolean +# signin_enabled :boolean +# gravatar_enabled :boolean +# sign_in_text :text +# created_at :datetime +# updated_at :datetime +# home_page_url :string(255) # require 'spec_helper' diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 19b442573f4febf814d949b200e2eeec9c6d9ba9..3a75d65b5bc7459aed45e5edc8f6633687458609 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -106,7 +106,25 @@ describe GitPushService do it "when pushing a branch for the first time" do project.should_receive(:execute_hooks) project.default_branch.should == "master" - project.protected_branches.should_receive(:create).with({ name: "master" }) + project.protected_branches.should_receive(:create).with({ name: "master", developers_can_push: false }) + service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') + end + + it "when pushing a branch for the first time with default branch protection disabled" do + ApplicationSetting.any_instance.stub(default_branch_protection: 0) + + project.should_receive(:execute_hooks) + project.default_branch.should == "master" + project.protected_branches.should_not_receive(:create) + service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') + end + + it "when pushing a branch for the first time with default branch protection set to 'developers can push'" do + ApplicationSetting.any_instance.stub(default_branch_protection: 1) + + project.should_receive(:execute_hooks) + project.default_branch.should == "master" + project.protected_branches.should_receive(:create).with({ name: "master", developers_can_push: true }) service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') end