Commit 21133fee authored by Aleksei Lipniagov's avatar Aleksei Lipniagov

Merge branch 'refactor-shared-runners-seconds-2' into 'master'

Change namespace factory to set new CI minutes tracking

See merge request gitlab-org/gitlab!71403
parents c20990cf addc2a0d
......@@ -41,7 +41,9 @@ module Ci
def total_minutes_used
strong_memoize(:total_minutes_used) do
namespace.shared_runners_seconds.to_i / 60
# TODO: use namespace.new_monthly_ci_minutes_enabled? to switch to
# ::Ci::Minutes::NamespaceMonthlyUsage.find_or_create_current(namespace.id).amount_used.to_i
namespace.namespace_statistics&.shared_runners_seconds.to_i / 60
end
end
......@@ -104,7 +106,6 @@ module Ci
purchased_minutes > 0
end
# === private to model ===
def total_minutes_remaining
[current_balance, 0].max
end
......
......@@ -79,7 +79,7 @@ module EE
.or(where.not(last_ci_minutes_usage_notification_level: nil))
end
delegate :shared_runners_seconds, :shared_runners_seconds_last_reset, to: :namespace_statistics, allow_nil: true
delegate :shared_runners_seconds_last_reset, to: :namespace_statistics, allow_nil: true
delegate :additional_purchased_storage_size, :additional_purchased_storage_size=,
:additional_purchased_storage_ends_on, :additional_purchased_storage_ends_on=,
......
......@@ -2,22 +2,40 @@
FactoryBot.modify do
factory :namespace do
trait :with_build_minutes do
namespace_statistics factory: :namespace_statistics, shared_runners_seconds: 400.minutes.to_i
end
trait :with_ci_minutes do
transient do
ci_minutes_limit { 500 }
ci_minutes_used { 400 }
end
trait :with_build_minutes_limit do
shared_runners_minutes_limit { 500 }
after(:build) do |namespace, evaluator|
namespace.shared_runners_minutes_limit = evaluator.ci_minutes_limit
end
after(:create) do |namespace, evaluator|
if evaluator.ci_minutes_used
create(:ci_namespace_monthly_usage, namespace: namespace, amount_used: evaluator.ci_minutes_used)
create(:namespace_statistics, namespace: namespace, shared_runners_seconds: evaluator.ci_minutes_used.minutes)
end
end
end
trait :with_not_used_build_minutes_limit do
namespace_statistics factory: :namespace_statistics, shared_runners_seconds: 300.minutes.to_i
shared_runners_minutes_limit { 500 }
after(:create) do |namespace, evaluator|
create(:ci_namespace_monthly_usage, namespace: namespace, amount_used: 300)
end
end
trait :with_used_build_minutes_limit do
namespace_statistics factory: :namespace_statistics, shared_runners_seconds: 1000.minutes.to_i
shared_runners_minutes_limit { 500 }
after(:create) do |namespace, evaluator|
create(:ci_namespace_monthly_usage, namespace: namespace, amount_used: 1000)
end
end
end
end
......
......@@ -6,7 +6,7 @@ RSpec.describe 'CI shared runner settings' do
include StubENV
let(:admin) { create(:admin) }
let(:group) { create(:group, :with_build_minutes) }
let(:group) { create(:group, :with_ci_minutes, ci_minutes_limit: nil) }
let!(:project) { create(:project, namespace: group, shared_runners_enabled: true) }
before do
......
......@@ -35,7 +35,7 @@ RSpec.describe 'CI shared runner limits' do
before do
group.update!(shared_runners_minutes_limit: minutes_limit)
allow_any_instance_of(EE::Namespace).to receive(:shared_runners_seconds).and_return(minutes_used.minutes)
allow_any_instance_of(::Ci::Minutes::Quota).to receive(:total_minutes_used).and_return(minutes_used)
end
it 'displays a warning message on pipelines page' do
......@@ -126,7 +126,7 @@ RSpec.describe 'CI shared runner limits' do
before do
group.update!(shared_runners_minutes_limit: minutes_limit)
allow_any_instance_of(EE::Namespace).to receive(:shared_runners_seconds).and_return(minutes_used.minutes)
allow_any_instance_of(::Ci::Minutes::Quota).to receive(:total_minutes_used).and_return(minutes_used)
end
it 'displays a warning message on group information page' do
......
......@@ -61,7 +61,7 @@ RSpec.describe 'Groups > Usage Quotas' do
end
context 'with no quota' do
let(:group) { create(:group, :with_build_minutes) }
let(:group) { create(:group, :with_ci_minutes, ci_minutes_limit: nil) }
include_examples 'linked in group settings dropdown'
......@@ -96,7 +96,7 @@ RSpec.describe 'Groups > Usage Quotas' do
end
context 'when successfully purchasing CI Minutes' do
let(:group) { create(:group, :with_build_minutes) }
let(:group) { create(:group, :with_ci_minutes) }
let!(:project) { create(:project, namespace: group, shared_runners_enabled: true) }
it 'does show a banner' do
......
......@@ -2,27 +2,18 @@
require 'spec_helper'
RSpec.describe EE::NamespacesHelper do
let!(:admin) { create(:admin) }
let!(:admin_project_creation_level) { nil }
let!(:admin_group) do
create(:group,
:private,
project_creation_level: admin_project_creation_level)
end
let!(:user) { create(:user) }
let!(:user_project_creation_level) { nil }
let!(:user_group) do
create(:group,
:private,
project_creation_level: user_project_creation_level)
end
before do
admin_group.add_owner(admin)
user_group.add_owner(user)
let(:user_group) do
create(:namespace, :with_ci_minutes,
project_creation_level: user_project_creation_level,
owner: user,
ci_minutes_used: ci_minutes_used)
end
let(:ci_minutes_used) { 100 }
describe '#ci_minutes_progress_bar' do
it 'shows a green bar if percent is 0' do
expect(helper.ci_minutes_progress_bar(0)).to match(/success.*0%/)
......@@ -58,7 +49,7 @@ RSpec.describe EE::NamespacesHelper do
context "when ci minutes quota is not enabled" do
before do
allow(user_group).to receive(:shared_runners_minutes_limit_enabled?).and_return(false)
allow(quota).to receive(:namespace_unlimited_minutes?).and_return(true)
end
context 'and the namespace is eligible for unlimited' do
......@@ -68,13 +59,7 @@ RSpec.describe EE::NamespacesHelper do
end
it 'returns Unlimited for the limit section' do
expect(helper.ci_minutes_report(report)).to match(%r{0 / Unlimited})
end
it 'returns the proper value for the used section' do
allow(user_group).to receive(:shared_runners_seconds).and_return(100 * 60)
expect(helper.ci_minutes_report(report)).to match(%r{100 / Unlimited})
expect(helper.ci_minutes_report(report)).to match(%r{\b100 / Unlimited})
end
end
......@@ -84,7 +69,7 @@ RSpec.describe EE::NamespacesHelper do
end
it 'returns Not supported for the limit section' do
expect(helper.ci_minutes_report(report)).to match(%r{0 / Not supported})
expect(helper.ci_minutes_report(report)).to match(%r{\b100 / Not supported})
end
end
end
......@@ -92,13 +77,12 @@ RSpec.describe EE::NamespacesHelper do
context "when it's limited" do
before do
allow(user_group).to receive(:any_project_with_shared_runners_enabled?).and_return(true)
allow(user_group).to receive(:shared_runners_seconds).and_return(100 * 60)
user_group.update!(shared_runners_minutes_limit: 500)
end
it 'returns the proper values for used and limit sections' do
expect(helper.ci_minutes_report(report)).to match(%r{100 / 500})
expect(helper.ci_minutes_report(report)).to match(%r{\b100 / 500\b})
end
end
end
......@@ -107,17 +91,30 @@ RSpec.describe EE::NamespacesHelper do
let(:report) { Ci::Minutes::QuotaPresenter.new(quota).purchased_minutes_report }
context 'when extra minutes are assigned' do
it 'returns the proper values for used and limit sections' do
allow(user_group).to receive(:shared_runners_seconds).and_return(50 * 60)
before do
user_group.update!(extra_shared_runners_minutes_limit: 100)
end
context 'when minutes used is higher than monthly minutes limit' do
let(:ci_minutes_used) { 550 }
it 'returns the proper values for used and limit sections' do
expect(helper.ci_minutes_report(report)).to match(%r{\b50 / 100\b})
end
end
expect(helper.ci_minutes_report(report)).to match(%r{50 / 100})
context 'when minutes used is lower than monthly minutes limit' do
let(:ci_minutes_used) { 400 }
it 'returns the proper values for used and limit sections' do
expect(helper.ci_minutes_report(report)).to match(%r{\b0 / 100\b})
end
end
end
context 'when extra minutes are not assigned' do
it 'returns the proper values for used and limit sections' do
expect(helper.ci_minutes_report(report)).to match(%r{0 / 0})
expect(helper.ci_minutes_report(report)).to match(%r{\b0 / 0\b})
end
end
end
......
......@@ -24,7 +24,7 @@ RSpec.describe Ci::Minutes::Notification do
end
context 'when minutes are not yet set' do
let(:group) { create(:group, :with_build_minutes_limit) }
let(:group) { create(:group, :with_ci_minutes, ci_minutes_limit: nil) }
it { is_expected.to be_falsey }
end
......@@ -38,9 +38,7 @@ RSpec.describe Ci::Minutes::Notification do
end
context 'when at the warning level' do
before do
allow(group).to receive(:shared_runners_seconds).and_return(16.minutes)
end
let(:group) { create(:group, :with_ci_minutes, ci_minutes_used: 16) }
describe '#show?' do
it 'has warning notification' do
......@@ -70,9 +68,7 @@ RSpec.describe Ci::Minutes::Notification do
end
context 'when at the danger level' do
before do
allow(group).to receive(:shared_runners_seconds).and_return(19.minutes)
end
let(:group) { create(:group, :with_ci_minutes, ci_minutes_used: 19) }
describe '#show?' do
it 'has danger notification' do
......@@ -102,9 +98,7 @@ RSpec.describe Ci::Minutes::Notification do
end
context 'when right at the limit for notification' do
before do
allow(group).to receive(:shared_runners_seconds).and_return(14.minutes)
end
let(:group) { create(:group, :with_ci_minutes, ci_minutes_used: 14) }
describe '#show?' do
it 'has warning notification' do
......
......@@ -80,11 +80,11 @@ RSpec.describe Ci::Minutes::Quota do
end
with_them do
let(:namespace) { create(:namespace, :with_ci_minutes, ci_minutes_limit: monthly_limit, ci_minutes_used: minutes_used) }
before do
allow(quota).to receive(:enabled?).and_return(limit_enabled)
namespace.shared_runners_minutes_limit = monthly_limit
namespace.extra_shared_runners_minutes_limit = purchased_limit
namespace.namespace_statistics.shared_runners_seconds = minutes_used.minutes
end
it { is_expected.to eq(result) }
......@@ -116,18 +116,16 @@ RSpec.describe Ci::Minutes::Quota do
describe '#total_minutes_used' do
subject { quota.total_minutes_used }
where(:expected_seconds, :expected_minutes) do
where(:minutes_used, :expected_minutes) do
nil | 0
0 | 0
59 | 0
60 | 1
122 | 2
0.9 | 0
1.1 | 1
2.1 | 2
end
with_them do
before do
allow(namespace).to receive(:shared_runners_seconds).and_return(expected_seconds)
end
let(:namespace) { create(:namespace, :with_ci_minutes, ci_minutes_used: minutes_used) }
it { is_expected.to eq(expected_minutes) }
end
......@@ -146,9 +144,9 @@ RSpec.describe Ci::Minutes::Quota do
end
with_them do
let(:namespace) { create(:namespace, :with_ci_minutes, ci_minutes_used: total_minutes_used, ci_minutes_limit: monthly_minutes) }
before do
allow(namespace).to receive(:shared_runners_seconds).and_return(total_minutes_used * 60)
allow(namespace).to receive(:shared_runners_minutes_limit).and_return(monthly_minutes)
allow(namespace).to receive(:extra_shared_runners_minutes_limit).and_return(purchased_minutes)
end
......@@ -161,11 +159,7 @@ RSpec.describe Ci::Minutes::Quota do
context 'when quota is enabled' do
let(:total_minutes) { 1000 }
before do
allow(namespace).to receive(:shared_runners_minutes_limit).and_return(total_minutes)
allow(namespace).to receive(:shared_runners_seconds).and_return(total_minutes_used * 60)
end
let(:namespace) { create(:namespace, :with_ci_minutes, ci_minutes_limit: total_minutes, ci_minutes_used: total_minutes_used) }
context 'when monthly minutes quota greater than monthly minutes used' do
let(:total_minutes_used) { total_minutes - 1 }
......@@ -221,10 +215,10 @@ RSpec.describe Ci::Minutes::Quota do
end
with_them do
let(:namespace) { create(:namespace, :with_ci_minutes, ci_minutes_limit: monthly_minutes, ci_minutes_used: total_minutes_used) }
before do
allow(namespace).to receive(:shared_runners_seconds).and_return(total_minutes_used * 60)
allow(namespace).to receive(:extra_shared_runners_minutes_limit).and_return(purchased_minutes)
allow(namespace).to receive(:shared_runners_minutes_limit).and_return(monthly_minutes)
end
it { is_expected.to eq(result) }
......
......@@ -20,7 +20,6 @@ RSpec.describe Namespace do
it { is_expected.to have_one :upcoming_reconciliation }
it { is_expected.to have_many(:ci_minutes_additional_packs) }
it { is_expected.to delegate_method(:shared_runners_seconds).to(:namespace_statistics) }
it { is_expected.to delegate_method(:shared_runners_seconds_last_reset).to(:namespace_statistics) }
it { is_expected.to delegate_method(:trial?).to(:gitlab_subscription) }
it { is_expected.to delegate_method(:trial_ends_on).to(:gitlab_subscription) }
......@@ -700,6 +699,22 @@ RSpec.describe Namespace do
end
end
describe '#new_monthly_ci_minutes_enabled?' do
subject { namespace.new_monthly_ci_minutes_enabled? }
context 'when feature flag ci_use_new_monthly_minutes is enabled' do
it { is_expected.to be_truthy }
end
context 'when feature flag ci_use_new_monthly_minutes is disabled' do
before do
stub_feature_flags(ci_use_new_monthly_minutes: false)
end
it { is_expected.to be_falsy }
end
end
describe '#shared_runners_minutes_limit_enabled?' do
subject { namespace.shared_runners_minutes_limit_enabled? }
......
......@@ -188,8 +188,10 @@ RSpec.describe API::Namespaces do
end
describe 'PUT /namespaces/:id' do
let!(:namespace_statistics) do
create(:namespace_statistics, namespace: group1, shared_runners_seconds: 1600 * 60)
let(:group1) { create(:group, :with_ci_minutes, ci_minutes_used: 1600) }
let(:usage) do
::Ci::Minutes::NamespaceMonthlyUsage.current_month.find_by(namespace_id: group1)
end
let(:params) do
......@@ -201,6 +203,7 @@ RSpec.describe API::Namespaces do
end
before do
usage.update!(notification_level: 30)
allow(Gitlab).to receive(:com?).and_return(true)
group1.update!(shared_runners_minutes_limit: 1000, extra_shared_runners_minutes_limit: 500)
end
......@@ -235,8 +238,6 @@ RSpec.describe API::Namespaces do
end
context 'when current CI minutes notification level is set' do
let!(:usage) { create(:ci_namespace_monthly_usage, :with_warning_notification_level, namespace: group1) }
it 'resets the current CI minutes notification level' do
expect do
put api("/namespaces/#{group1.id}", admin), params: params
......@@ -277,8 +278,6 @@ RSpec.describe API::Namespaces do
end
context 'when current CI minutes notification level is set' do
let!(:usage) { create(:ci_namespace_monthly_usage, :with_warning_notification_level, namespace: group1) }
it 'resets the current CI minutes notification level' do
expect do
put api("/namespaces/#{group1.id}", admin), params: params
......@@ -297,8 +296,6 @@ RSpec.describe API::Namespaces do
end
context 'when current CI minutes notification level is set' do
let!(:usage) { create(:ci_namespace_monthly_usage, :with_warning_notification_level, namespace: group1) }
it 'does not reset the current CI minutes notification level' do
params.delete(:shared_runners_minutes_limit)
......
......@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe BuildDetailsEntity do
let_it_be(:user) { create(:user) }
let(:namespace) { create(:namespace) }
let(:namespace) { create(:namespace, :with_ci_minutes, ci_minutes_used: 800) }
let(:project) { create(:project, namespace: namespace) }
let(:request) { double('request', project: project) }
let(:build) { create(:ci_build, project: project) }
......@@ -17,7 +17,6 @@ RSpec.describe BuildDetailsEntity do
before do
allow(request).to receive(:current_user).and_return(user)
allow(namespace).to receive(:shared_runners_seconds).and_return(800.minutes)
end
context 'when namespace has CI minutes limit enabled' do
......
......@@ -11,10 +11,10 @@ RSpec.describe Ci::Minutes::ResetUsageService do
context 'when project has namespace_statistics' do
let_it_be(:namespace) { create(:namespace, :with_used_build_minutes_limit) }
let_it_be(:namespace_usage) do
create(:ci_namespace_monthly_usage, :with_warning_notification_level,
namespace: namespace,
amount_used: 100)
let(:namespace_usage) do
Ci::Minutes::NamespaceMonthlyUsage.current_month.find_by(namespace_id: namespace).tap do |usage|
usage.update!(notification_level: 100)
end
end
it 'clears the amount used and notification levels', :aggregate_failures do
......
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