Commit a4ae95ad authored by Kamil Trzcinski's avatar Kamil Trzcinski

Improve EE compatibility

parent c264fc76
......@@ -72,14 +72,14 @@ class Admin::GroupsController < Admin::ApplicationController
:name,
:path,
:request_access_enabled,
:shared_runners_minutes_limit,
:visibility_level
]
end
def group_params_ee
[
:repository_size_limit
:repository_size_limit,
:shared_runners_minutes_limit
]
end
end
......@@ -4,6 +4,6 @@ class Groups::PipelineQuotaController < Groups::ApplicationController
layout 'group_settings'
def index
@projects = @group.projects.where(shared_runners_enabled: true).page(params[:page])
@projects = @group.projects.with_shared_runners.page(params[:page])
end
end
......@@ -2,6 +2,7 @@ module Ci
class Build < CommitStatus
include TokenAuthenticatable
include AfterCommitQueue
include EE::Build
belongs_to :runner
belongs_to :trigger_request
......@@ -103,12 +104,6 @@ module Ci
end
end
after_transition any => [:success, :failed, :canceled] do |build|
build.run_after_commit do
UpdateBuildMinutesService.new(project, nil).execute(self)
end
end
after_transition any => [:success] do |build|
build.run_after_commit do
BuildSuccessWorker.perform_async(id)
......@@ -539,10 +534,6 @@ module Ci
Gitlab::Ci::Build::Credentials::Factory.new(self).create!
end
def shared_runners_minutes_quota?
runner && runner.shared? && project.shared_runners_minutes_quota?
end
private
def update_artifacts_size
......
module EE
# Build EE mixin
#
# This module is intended to encapsulate EE-specific model logic
# and be included in the `Build` model
module Build
extend ActiveSupport::Concern
def shared_runners_minutes_quota?
runner && runner.shared? && project.shared_runners_minutes_quota?
end
end
end
module EE
# Namespace EE mixin
#
# This module is intended to encapsulate EE-specific model logic
# and be included in the `Namespace` model
module Namespace
extend ActiveSupport::Concern
included do
has_one :namespace_metrics, dependent: :destroy
delegate :shared_runners_minutes, :shared_runners_minutes_last_reset,
to: :namespace_metrics, allow_nil: true
end
def actual_shared_runners_minutes_limit
shared_runners_minutes_limit ||
current_application_settings.shared_runners_minutes
end
def shared_runners_minutes_limit_enabled?
shared_runners_enabled? &&
actual_shared_runners_minutes_limit.nonzero?
end
def shared_runners_minutes_used?
shared_runners_minutes_limit_enabled? &&
shared_runners_minutes.to_i >= actual_shared_runners_minutes_limit
end
end
end
module EE
# Project EE mixin
#
# This module is intended to encapsulate EE-specific model logic
# and be included in the `Project` model
module Project
extend ActiveSupport::Concern
included do
delegate :shared_runners_minutes, :shared_runners_minutes_last_reset,
to: :project_metrics, allow_nil: true
delegate :shared_runners_minutes_limit_enabled?, :actual_shared_runners_minutes_limit,
:shared_runners_minutes_used?, to: :namespace
has_one :project_metrics, dependent: :destroy
end
def shared_runners_minutes_quota?
!public? && shared_runners_enabled?
end
def shared_runners
if shared_runners_enabled? && !namespace.shared_runners_minutes_used?
Ci::Runner.shared
else
Ci::Runner.none
end
end
end
end
class Namespace < ActiveRecord::Base
acts_as_paranoid
include EE::Namespace
include CacheMarkdownField
include Sortable
include Gitlab::ShellAdapter
......@@ -10,8 +11,6 @@ class Namespace < ActiveRecord::Base
cache_markdown_field :description, pipeline: :description
has_many :projects, dependent: :destroy
has_one :namespace_metrics, dependent: :destroy
has_many :project_statistics
belongs_to :owner, class_name: "User"
......@@ -40,9 +39,6 @@ class Namespace < ActiveRecord::Base
before_destroy(prepend: true) { @old_repository_storage_paths = repository_storage_paths }
after_destroy :rm_dir
delegate :shared_runners_minutes, :shared_runners_minutes_last_reset,
to: :namespace_metrics, allow_nil: true
scope :root, -> { where('type IS NULL') }
scope :with_statistics, -> do
......@@ -189,21 +185,6 @@ class Namespace < ActiveRecord::Base
projects.where(shared_runners_enabled: true).any?
end
def actual_shared_runners_minutes_limit
shared_runners_minutes_limit ||
current_application_settings.shared_runners_minutes
end
def shared_runners_minutes_limit_enabled?
shared_runners_enabled? &&
actual_shared_runners_minutes_limit.nonzero?
end
def shared_runners_minutes_used?
shared_runners_minutes_limit_enabled? &&
shared_runners_minutes.to_i >= actual_shared_runners_minutes_limit
end
def full_name
@full_name ||=
if parent
......
......@@ -18,6 +18,7 @@ class Project < ActiveRecord::Base
include SelectForProjectAuthorization
include Routable
prepend EE::GeoAwareAvatar
include EE::Project
extend Gitlab::ConfigHelper
......@@ -29,12 +30,6 @@ class Project < ActiveRecord::Base
:merge_requests_enabled?, :issues_enabled?, to: :project_feature,
allow_nil: true
delegate :shared_runners_minutes, :shared_runners_minutes_last_reset,
to: :project_metrics, allow_nil: true
delegate :shared_runners_minutes_limit_enabled?, :actual_shared_runners_minutes_limit,
:shared_runners_minutes_used?, to: :namespace
default_value_for :archived, false
default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :container_registry_enabled, gitlab_config_features.container_registry
......@@ -82,8 +77,6 @@ class Project < ActiveRecord::Base
belongs_to :namespace
belongs_to :mirror_user, foreign_key: 'mirror_user_id', class_name: 'User'
has_one :project_metrics, dependent: :destroy
has_one :push_rule, dependent: :destroy
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event'
has_many :boards, dependent: :destroy
......@@ -253,6 +246,7 @@ class Project < ActiveRecord::Base
scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') }
scope :with_statistics, -> { includes(:statistics) }
scope :with_shared_runners_limit_enabled, -> { where(shared_runners_enabled: true).non_public_only }
# "enabled" here means "not disabled". It includes private features!
scope :with_feature_enabled, ->(feature) {
......@@ -1247,14 +1241,16 @@ class Project < ActiveRecord::Base
project_feature.update_attribute(:builds_access_level, ProjectFeature::ENABLED)
end
def shared_runners
shared_runners_enabled? ? Ci::Runner.shared : Ci::Runner.none
end unless defined?(:shared_runners)
def any_runners?(&block)
if runners.active.any?(&block)
return true
end
shared_runners_enabled? &&
!namespace.shared_runners_minutes_used? &&
Ci::Runner.shared.active.any?(&block)
shared_runners.active.any?(&block)
end
def valid_runners_token?(token)
......@@ -1569,10 +1565,6 @@ class Project < ActiveRecord::Base
end
end
def shared_runners_minutes_quota?
!public? && shared_runners_enabled?
end
private
# Check if a reference is being done cross-project
......
......@@ -5,8 +5,9 @@
%p
You have used all your shared runner minutes
= "(#{quota_used} of #{quota_limit})."
%br
For more information, go to the
= succeed "." do
= link_to namespace_project_runners_path(project.namespace, project) do
runners page
- if can?(current_user, :admin_build, @project)
%br
For more information, go to the
= succeed "." do
= link_to namespace_project_runners_path(project.namespace, project) do
runners page
......@@ -4,6 +4,7 @@ class BuildFinishedWorker
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
UpdateBuildMinutesService.new(build.project, nil).execute(build)
BuildCoverageWorker.new.perform(build.id)
BuildHooksWorker.new.perform(build.id)
end
......
......@@ -863,8 +863,8 @@ ActiveRecord::Schema.define(version: 20170106172224) do
add_index "namespaces", ["deleted_at"], name: "index_namespaces_on_deleted_at", using: :btree
add_index "namespaces", ["ldap_sync_last_successful_update_at"], name: "index_namespaces_on_ldap_sync_last_successful_update_at", using: :btree
add_index "namespaces", ["ldap_sync_last_update_at"], name: "index_namespaces_on_ldap_sync_last_update_at", using: :btree
add_index "namespaces", ["name"], name: "index_namespaces_on_name", unique: true, using: :btree
add_index "namespaces", ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
add_index "namespaces", ["name"], name: "index_namespaces_on_name", unique: true, using: :btree
add_index "namespaces", ["name"], name: "index_namespaces_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
add_index "namespaces", ["parent_id", "id"], name: "index_namespaces_on_parent_id_and_id", unique: true, using: :btree
......@@ -1522,8 +1522,8 @@ ActiveRecord::Schema.define(version: 20170106172224) do
add_foreign_key "project_authorizations", "projects", on_delete: :cascade
add_foreign_key "project_authorizations", "users", on_delete: :cascade
add_foreign_key "project_metrics", "projects", on_delete: :cascade
add_foreign_key "protected_branch_merge_access_levels", "namespaces", column: "group_id"
add_foreign_key "project_statistics", "projects", on_delete: :cascade
add_foreign_key "protected_branch_merge_access_levels", "namespaces", column: "group_id"
add_foreign_key "protected_branch_merge_access_levels", "protected_branches"
add_foreign_key "protected_branch_merge_access_levels", "users"
add_foreign_key "protected_branch_push_access_levels", "namespaces", column: "group_id"
......
......@@ -11,6 +11,7 @@ module Gitlab
included do
scope :public_only, -> { where(visibility_level: PUBLIC) }
scope :public_and_internal_only, -> { where(visibility_level: [PUBLIC, INTERNAL] ) }
scope :non_public_only, -> { where.not(visibility_level: PUBLIC) }
scope :public_to_user, -> (user) { user && !user.external ? public_and_internal_only : public_only }
end
......
This diff is collapsed.
require 'spec_helper'
describe Ci::Build, models: true do
let(:project) { create(:project) }
let(:pipeline) do
create(:ci_pipeline, project: project,
sha: project.commit.id,
ref: project.default_branch,
status: 'success')
end
let(:build) { create(:ci_build, pipeline: pipeline) }
describe '#shared_runners_minutes_quota?' do
subject { build.shared_runners_minutes_quota? }
context 'for shared runner' do
before do
build.runner = create(:ci_runner, :shared)
end
it do
expect(build.project).to receive(:shared_runners_minutes_quota?).
and_return(true)
is_expected.to be_truthy
end
end
context 'with specific runner' do
before do
build.runner = create(:ci_runner, :specific)
end
it { is_expected.to be_falsey }
end
context 'without runner' do
it { is_expected.to be_falsey }
end
end
context 'updates build minutes' do
let(:build) { create(:ci_build, :running, pipeline: pipeline) }
%w(success drop cancel).each do |event|
it "for event #{event}" do
expect(UpdateBuildMinutesService).
to receive(:new).and_call_original
build.public_send(event)
end
end
end
end
require 'spec_helper'
describe Namespace, models: true do
let!(:namespace) { create(:namespace) }
it { is_expected.to have_one(:namespace_metrics).dependent(:destroy) }
it { is_expected.to delegate_method(:shared_runners_minutes).to(:namespace_metrics) }
it { is_expected.to delegate_method(:shared_runners_minutes_last_reset).to(:namespace_metrics) }
describe '#shared_runners_enabled?' do
subject { namespace.shared_runners_enabled? }
context 'without projects' do
it { is_expected.to be_falsey }
end
context 'with project' do
context 'and disabled shared runners' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: false)
end
it { is_expected.to be_falsey }
end
context 'and enabled shared runners' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: true)
end
it { is_expected.to be_truthy }
end
end
end
describe '#actual_shared_runners_minutes_limit' do
subject { namespace.actual_shared_runners_minutes_limit }
context 'when no limit defined' do
it { is_expected.to be_zero }
end
context 'when application settings limit is set' do
before do
stub_application_setting(shared_runners_minutes: 1000)
end
it 'returns global limit' do
is_expected.to eq(1000)
end
context 'when namespace limit is set' do
before do
namespace.shared_runners_minutes_limit = 500
end
it 'returns namespace limit' do
is_expected.to eq(500)
end
end
end
end
describe '#shared_runners_minutes_limit_enabled?' do
subject { namespace.shared_runners_minutes_limit_enabled? }
context 'with project' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: true)
end
context 'when no limit defined' do
it { is_expected.to be_falsey }
end
context 'when limit is defined' do
before do
namespace.shared_runners_minutes_limit = 500
end
it { is_expected.to be_truthy }
end
end
context 'without project' do
it { is_expected.to be_falsey }
end
end
describe '#shared_runners_minutes_used?' do
subject { namespace.shared_runners_minutes_used? }
context 'with project' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: true)
end
context 'when limit is defined' do
context 'when limit is used' do
let(:namespace) { create(:namespace, :with_used_build_minutes_limit) }
it { is_expected.to be_truthy }
end
context 'when limit not yet used' do
let(:namespace) { create(:namespace, :with_not_used_build_minutes_limit) }
it { is_expected.to be_falsey }
end
context 'when minutes are not yet set' do
it { is_expected.to be_falsey }
end
end
context 'without limit' do
let(:namespace) { create(:namespace, :with_build_minutes_limit) }
it { is_expected.to be_falsey }
end
end
context 'without project' do
it { is_expected.to be_falsey }
end
end
end
require 'spec_helper'
describe Project, models: true do
describe 'associations' do
it { is_expected.to have_one(:project_metrics).dependent(:destroy) }
it { is_expected.to delegate_method(:shared_runners_minutes).to(:project_metrics) }
it { is_expected.to delegate_method(:shared_runners_minutes_last_reset).to(:project_metrics) }
it { is_expected.to delegate_method(:actual_shared_runners_minutes_limit).to(:namespace) }
it { is_expected.to delegate_method(:shared_runners_minutes_limit_enabled?).to(:namespace) }
it { is_expected.to delegate_method(:shared_runners_minutes_used?).to(:namespace) }
end
describe '#any_runners_limit' do
let(:project) { create(:empty_project, shared_runners_enabled: shared_runners_enabled) }
let(:specific_runner) { create(:ci_runner) }
let(:shared_runner) { create(:ci_runner, :shared) }
context 'for shared runners enabled' do
let(:shared_runners_enabled) { true }
before do
shared_runner
end
it 'has a shared runner' do
expect(project.any_runners?).to be_truthy
end
it 'checks the presence of shared runner' do
expect(project.any_runners? { |runner| runner == shared_runner }).to be_truthy
end
context 'with used build minutes' do
let(:namespace) { create(:namespace, :with_used_build_minutes_limit) }
let(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: shared_runners_enabled)
end
it 'does not have a shared runner' do
expect(project.any_runners?).to be_falsey
end
end
end
end
describe '#shared_runners_minutes_quota?' do
let(:project) { create(:empty_project) }
subject { project.shared_runners_minutes_quota? }
context 'with shared runners enabled' do
before do
project.shared_runners_enabled = true
end
context 'for public project' do
before do
project.visibility_level = Project::PUBLIC
end
it { is_expected.to be_falsey }
end
context 'for internal project' do
before do
project.visibility_level = Project::INTERNAL
end
it { is_expected.to be_truthy }
end
context 'for private project' do
before do
project.visibility_level = Project::INTERNAL
end
it { is_expected.to be_truthy }
end
end
context 'without shared runners' do
before do
project.shared_runners_enabled = false
end
it { is_expected.to be_falsey }
end
end
end
......@@ -4,7 +4,6 @@ describe Namespace, models: true do
let!(:namespace) { create(:namespace) }
it { is_expected.to have_many :projects }
it { is_expected.to have_one(:namespace_metrics).dependent(:destroy) }
it { is_expected.to have_many :project_statistics }
it { is_expected.to validate_presence_of(:name) }
......@@ -18,9 +17,6 @@ describe Namespace, models: true do
it { is_expected.to validate_presence_of(:owner) }
it { is_expected.to delegate_method(:shared_runners_minutes).to(:namespace_metrics) }
it { is_expected.to delegate_method(:shared_runners_minutes_last_reset).to(:namespace_metrics) }
describe "Respond to" do
it { is_expected.to respond_to(:human_name) }
it { is_expected.to respond_to(:to_param) }
......@@ -190,132 +186,6 @@ describe Namespace, models: true do
it { expect(nested_group.full_path).to eq("#{group.path}/#{nested_group.path}") }
end
describe '#shared_runners_enabled?' do
subject { namespace.shared_runners_enabled? }
context 'without projects' do
it { is_expected.to be_falsey }
end
context 'with project' do
context 'and disabled shared runners' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: false)
end
it { is_expected.to be_falsey }
end
context 'and enabled shared runners' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: true)
end
it { is_expected.to be_truthy }
end
end
end
describe '#actual_shared_runners_minutes_limit' do
subject { namespace.actual_shared_runners_minutes_limit }
context 'when no limit defined' do
it { is_expected.to be_zero }
end
context 'when application settings limit is set' do
before do
stub_application_setting(shared_runners_minutes: 1000)
end
it 'returns global limit' do
is_expected.to eq(1000)
end
context 'when namespace limit is set' do
before do
namespace.shared_runners_minutes_limit = 500
end
it 'returns namespace limit' do
is_expected.to eq(500)
end
end
end
end
describe '#shared_runners_minutes_limit_enabled?' do
subject { namespace.shared_runners_minutes_limit_enabled? }
context 'with project' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: true)
end
context 'when no limit defined' do
it { is_expected.to be_falsey }
end
context 'when limit is defined' do
before do
namespace.shared_runners_minutes_limit = 500
end
it { is_expected.to be_truthy }
end
end
context 'without project' do
it { is_expected.to be_falsey }
end
end
describe '#shared_runners_minutes_used?' do
subject { namespace.shared_runners_minutes_used? }
context 'with project' do
let!(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: true)
end
context 'when limit is defined' do
context 'when limit is used' do
let(:namespace) { create(:namespace, :with_used_build_minutes_limit) }
it { is_expected.to be_truthy }
end
context 'when limit not yet used' do
let(:namespace) { create(:namespace, :with_not_used_build_minutes_limit) }
it { is_expected.to be_falsey }
end
context 'when minutes are not yet set' do
it { is_expected.to be_falsey }
end
end
context 'without limit' do
let(:namespace) { create(:namespace, :with_build_minutes_limit) }
it { is_expected.to be_falsey }
end
end
context 'without project' do
it { is_expected.to be_falsey }
end
end
describe '#full_name' do
let(:group) { create(:group) }
let(:nested_group) { create(:group, parent: group) }
......
......@@ -5,7 +5,6 @@ describe Project, models: true do
it { is_expected.to belong_to(:group) }
it { is_expected.to belong_to(:namespace) }
it { is_expected.to belong_to(:creator).class_name('User') }
it { is_expected.to have_one(:project_metrics).dependent(:destroy) }
it { is_expected.to have_many(:users) }
it { is_expected.to have_many(:services) }
it { is_expected.to have_many(:events).dependent(:destroy) }
......@@ -75,13 +74,6 @@ describe Project, models: true do
it { is_expected.to have_many(:forks).through(:forked_project_links) }
it { is_expected.to have_many(:approver_groups).dependent(:destroy) }
it { is_expected.to delegate_method(:shared_runners_minutes).to(:project_metrics) }
it { is_expected.to delegate_method(:shared_runners_minutes_last_reset).to(:project_metrics) }
it { is_expected.to delegate_method(:actual_shared_runners_minutes_limit).to(:namespace) }
it { is_expected.to delegate_method(:shared_runners_minutes_limit_enabled?).to(:namespace) }
it { is_expected.to delegate_method(:shared_runners_minutes_used?).to(:namespace) }
context 'after initialized' do
it "has a project_feature" do
project = FactoryGirl.build(:project)
......@@ -1114,30 +1106,15 @@ describe Project, models: true do
context 'for shared runners enabled' do
let(:shared_runners_enabled) { true }
before do
shared_runner
end
it 'has a shared runner' do
shared_runner
expect(project.any_runners?).to be_truthy
end
it 'checks the presence of shared runner' do
shared_runner
expect(project.any_runners? { |runner| runner == shared_runner }).to be_truthy
end
context 'with used build minutes' do
let(:namespace) { create(:namespace, :with_used_build_minutes_limit) }
let(:project) do
create(:empty_project,
namespace: namespace,
shared_runners_enabled: shared_runners_enabled)
end
it 'does not have a shared runner' do
expect(project.any_runners?).to be_falsey
end
end
end
end
......@@ -2119,50 +2096,6 @@ describe Project, models: true do
end
end
describe '#shared_runners_minutes_quota?' do
let(:project) { create(:empty_project) }
subject { project.shared_runners_minutes_quota? }
context 'with shared runners enabled' do
before do
project.shared_runners_enabled = true
end
context 'for public project' do
before do
project.visibility_level = Project::PUBLIC
end
it { is_expected.to be_falsey }
end
context 'for internal project' do
before do
project.visibility_level = Project::INTERNAL
end
it { is_expected.to be_truthy }
end
context 'for private project' do
before do
project.visibility_level = Project::INTERNAL
end
it { is_expected.to be_truthy }
end
end
context 'without shared runners' do
before do
project.shared_runners_enabled = false
end
it { is_expected.to be_falsey }
end
end
describe '#update_project_statistics' do
let(:project) { create(:empty_project) }
......
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