Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
dd36b5f5
Commit
dd36b5f5
authored
Jul 22, 2021
by
Allison Browne
Committed by
Fabio Pitino
Jul 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move Minutes Usage Update to Async Job
parent
fe91c0a6
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
211 additions
and
54 deletions
+211
-54
app/services/ci/destroy_pipeline_service.rb
app/services/ci/destroy_pipeline_service.rb
+1
-1
ee/app/models/ci/minutes/namespace_monthly_usage.rb
ee/app/models/ci/minutes/namespace_monthly_usage.rb
+2
-2
ee/app/models/ci/minutes/project_monthly_usage.rb
ee/app/models/ci/minutes/project_monthly_usage.rb
+2
-2
ee/app/models/ee/ci/build.rb
ee/app/models/ee/ci/build.rb
+1
-3
ee/app/services/ci/minutes/update_build_minutes_service.rb
ee/app/services/ci/minutes/update_build_minutes_service.rb
+9
-3
ee/app/services/ci/minutes/update_project_and_namespace_usage_service.rb
.../ci/minutes/update_project_and_namespace_usage_service.rb
+49
-19
ee/app/workers/all_queues.yml
ee/app/workers/all_queues.yml
+9
-0
ee/app/workers/ci/minutes/update_project_and_namespace_usage_worker.rb
...s/ci/minutes/update_project_and_namespace_usage_worker.rb
+17
-0
ee/app/workers/ee/ci/build_finished_worker.rb
ee/app/workers/ee/ci/build_finished_worker.rb
+1
-1
ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb
ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb
+1
-1
ee/spec/models/ci/minutes/project_monthly_usage_spec.rb
ee/spec/models/ci/minutes/project_monthly_usage_spec.rb
+1
-1
ee/spec/services/ci/minutes/update_build_minutes_service_spec.rb
.../services/ci/minutes/update_build_minutes_service_spec.rb
+29
-15
ee/spec/services/ci/minutes/update_project_and_namespace_usage_service_spec.rb
...inutes/update_project_and_namespace_usage_service_spec.rb
+45
-5
ee/spec/workers/ci/minutes/update_project_and_namespace_usage_worker_spec.rb
...minutes/update_project_and_namespace_usage_worker_spec.rb
+43
-0
lib/gitlab/ci/features.rb
lib/gitlab/ci/features.rb
+1
-1
No files found.
app/services/ci/destroy_pipeline_service.rb
View file @
dd36b5f5
...
@@ -7,7 +7,7 @@ module Ci
...
@@ -7,7 +7,7 @@ module Ci
Ci
::
ExpirePipelineCacheService
.
new
.
execute
(
pipeline
,
delete:
true
)
Ci
::
ExpirePipelineCacheService
.
new
.
execute
(
pipeline
,
delete:
true
)
pipeline
.
cancel_running
if
pipeline
.
cancelable?
&&
::
Feature
.
enabled?
(
:cancel_pipelines_prior_to_destroy
,
default_enabled: :yaml
)
pipeline
.
cancel_running
if
pipeline
.
cancelable?
&&
::
Feature
.
enabled?
(
:cancel_pipelines_prior_to_destroy
,
pipeline
.
project
,
default_enabled: :yaml
)
pipeline
.
reset
.
destroy!
pipeline
.
reset
.
destroy!
...
...
ee/app/models/ci/minutes/namespace_monthly_usage.rb
View file @
dd36b5f5
...
@@ -22,8 +22,8 @@ module Ci
...
@@ -22,8 +22,8 @@ module Ci
#
#
# Here we will also do any recalculation of additional minutes based on the
# Here we will also do any recalculation of additional minutes based on the
# previous month usage.
# previous month usage.
def
self
.
find_or_create_current
(
namespace
)
def
self
.
find_or_create_current
(
namespace
_id
:
)
current_month
.
safe_find_or_create_by
(
namespace
:
namespace
)
current_month
.
safe_find_or_create_by
(
namespace
_id:
namespace_id
)
end
end
def
self
.
increase_usage
(
usage
,
amount
)
def
self
.
increase_usage
(
usage
,
amount
)
...
...
ee/app/models/ci/minutes/project_monthly_usage.rb
View file @
dd36b5f5
...
@@ -19,8 +19,8 @@ module Ci
...
@@ -19,8 +19,8 @@ module Ci
# since this will lazily create an entry if it doesn't exist.
# since this will lazily create an entry if it doesn't exist.
# For example, on the 1st of each month, when we update the usage for a project,
# For example, on the 1st of each month, when we update the usage for a project,
# we will automatically generate new records and reset usage for the current month.
# we will automatically generate new records and reset usage for the current month.
def
self
.
find_or_create_current
(
project
)
def
self
.
find_or_create_current
(
project
_id
:
)
current_month
.
safe_find_or_create_by
(
project
:
project
)
current_month
.
safe_find_or_create_by
(
project
_id:
project_id
)
end
end
def
self
.
increase_usage
(
usage
,
amount
)
def
self
.
increase_usage
(
usage
,
amount
)
...
...
ee/app/models/ee/ci/build.rb
View file @
dd36b5f5
...
@@ -52,9 +52,7 @@ module EE
...
@@ -52,9 +52,7 @@ module EE
state_machine
:status
do
state_machine
:status
do
after_transition
any
=>
[
:success
,
:failed
,
:canceled
]
do
|
build
|
after_transition
any
=>
[
:success
,
:failed
,
:canceled
]
do
|
build
|
build
.
run_after_commit
do
build
.
run_after_commit
do
# TODO(Issue #331891): before enabling this feature flag. Move update consumption to async while keeping consumption calculation sync.
if
::
Feature
.
enabled?
(
:cancel_pipelines_prior_to_destroy
,
build
.
project
,
default_enabled: :yaml
)
# This will ensure consumption is calculated before related records are deleted.
if
::
Feature
.
enabled?
(
:cancel_pipelines_prior_to_destroy
,
default_enabled: :yaml
)
::
Ci
::
Minutes
::
UpdateBuildMinutesService
.
new
(
build
.
project
,
nil
).
execute
(
build
)
::
Ci
::
Minutes
::
UpdateBuildMinutesService
.
new
(
build
.
project
,
nil
).
execute
(
build
)
end
end
end
end
...
...
ee/app/services/ci/minutes/update_build_minutes_service.rb
View file @
dd36b5f5
...
@@ -14,14 +14,20 @@ module Ci
...
@@ -14,14 +14,20 @@ module Ci
return
unless
consumption
>
0
return
unless
consumption
>
0
# TODO(Issue #335338): Introduce async worker UpdateProjectAndNamespaceUsageWorker
update_minutes
(
consumption
)
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageService
.
new
(
project
,
namespace
).
execute
(
consumption
)
compare_with_live_consumption
(
build
,
consumption
)
compare_with_live_consumption
(
build
,
consumption
)
end
end
private
private
def
update_minutes
(
consumption
)
if
::
Feature
.
enabled?
(
:cancel_pipelines_prior_to_destroy
,
project
,
default_enabled: :yaml
)
::
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageWorker
.
perform_async
(
consumption
,
project
.
id
,
namespace
.
id
)
else
::
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageService
.
new
(
project
.
id
,
namespace
.
id
).
execute
(
consumption
)
end
end
def
compare_with_live_consumption
(
build
,
consumption
)
def
compare_with_live_consumption
(
build
,
consumption
)
live_consumption
=
::
Ci
::
Minutes
::
TrackLiveConsumptionService
.
new
(
build
).
live_consumption
live_consumption
=
::
Ci
::
Minutes
::
TrackLiveConsumptionService
.
new
(
build
).
live_consumption
return
if
live_consumption
==
0
return
if
live_consumption
==
0
...
...
ee/app/services/ci/minutes/update_project_and_namespace_usage_service.rb
View file @
dd36b5f5
...
@@ -3,53 +3,83 @@
...
@@ -3,53 +3,83 @@
module
Ci
module
Ci
module
Minutes
module
Minutes
class
UpdateProjectAndNamespaceUsageService
class
UpdateProjectAndNamespaceUsageService
def
initialize
(
project
,
namespace
)
include
Gitlab
::
Utils
::
StrongMemoize
@project
=
project
@namespace
=
namespace
def
initialize
(
project_id
,
namespace_id
)
@project_id
=
project_id
@namespace_id
=
namespace_id
# TODO(issue 335885): Use project_id only and don't query for projects which may be deleted
@project
=
Project
.
find_by_id
(
project_id
)
end
end
# Updates the project and namespace usage based on the passed consumption amount
# Updates the project and namespace usage based on the passed consumption amount
def
execute
(
consumption
)
def
execute
(
consumption
)
consumption_in_seconds
=
consumption
.
minutes
.
to_i
legacy_track_usage_of_monthly_minutes
(
consumption
)
legacy_track_usage_of_monthly_minutes
(
consumption_in_seconds
)
ApplicationRecord
.
transaction
do
track_usage_of_monthly_minutes
(
consumption
)
track_usage_of_monthly_minutes
(
consumption
)
send_minutes_email_notification
send_minutes_email_notification
end
end
end
private
private
def
send_minutes_email_notification
def
send_minutes_email_notification
# `perform reset` on `project` because `Namespace#namespace_statistics` will otherwise return stale data.
# `perform reset` on `project` because `Namespace#namespace_statistics` will otherwise return stale data.
# TODO(issue 335885): Remove @project
::
Ci
::
Minutes
::
EmailNotificationService
.
new
(
@project
.
reset
).
execute
if
::
Gitlab
.
com?
::
Ci
::
Minutes
::
EmailNotificationService
.
new
(
@project
.
reset
).
execute
if
::
Gitlab
.
com?
end
end
def
legacy_track_usage_of_monthly_minutes
(
consumption_in_seconds
)
def
legacy_track_usage_of_monthly_minutes
(
consumption
)
ProjectStatistics
.
update_counters
(
project_statistics
,
consumption_in_seconds
=
consumption
.
minutes
.
to_i
shared_runners_seconds:
consumption_in_seconds
)
NamespaceStatistics
.
update_counters
(
namespace_statistics
,
update_legacy_project_minutes
(
consumption_in_seconds
)
shared_runners_seconds:
consumption_in_seconds
)
update_legacy_namespace_minutes
(
consumption_in_seconds
)
end
end
def
track_usage_of_monthly_minutes
(
consumption
)
def
track_usage_of_monthly_minutes
(
consumption
)
# TODO(issue 335885): Remove @project
return
unless
Feature
.
enabled?
(
:ci_minutes_monthly_tracking
,
@project
,
default_enabled: :yaml
)
return
unless
Feature
.
enabled?
(
:ci_minutes_monthly_tracking
,
@project
,
default_enabled: :yaml
)
namespace_usage
=
::
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
@namespace
)
::
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
increase_usage
(
namespace_usage
,
consumption
)
if
namespace_usage
project_usage
=
::
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_or_create_current
(
@project
)
::
Ci
::
Minutes
::
ProjectMonthlyUsage
.
increase_usage
(
project_usage
,
consumption
)
if
project_usage
end
ApplicationRecord
.
transaction
do
def
update_legacy_project_minutes
(
consumption_in_seconds
)
::
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
increase_usage
(
namespace_usage
,
consumption
)
if
project_statistics
::
Ci
::
Minutes
::
ProjectMonthlyUsage
.
increase_usage
(
project_usage
,
consumption
)
ProjectStatistics
.
update_counters
(
project_statistics
,
shared_runners_seconds:
consumption_in_seconds
)
end
end
def
update_legacy_namespace_minutes
(
consumption_in_seconds
)
if
namespace_statistics
NamespaceStatistics
.
update_counters
(
namespace_statistics
,
shared_runners_seconds:
consumption_in_seconds
)
end
end
def
namespace_usage
::
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
namespace_id:
@namespace_id
)
end
def
project_usage
strong_memoize
(
:project_usage
)
do
::
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_or_create_current
(
project_id:
@project_id
)
rescue
ActiveRecord
::
InvalidForeignKey
end
end
end
end
def
namespace_statistics
def
namespace_statistics
@namespace
.
namespace_statistics
||
@namespace
.
create_namespace_statistics
strong_memoize
(
:namespace_statistics
)
do
NamespaceStatistics
.
safe_find_or_create_by!
(
namespace_id:
@namespace_id
)
rescue
ActiveRecord
::
NotNullViolation
,
ActiveRecord
::
RecordInvalid
end
end
end
def
project_statistics
def
project_statistics
@project
.
statistics
||
@project
.
create_statistics
(
namespace:
@project
.
namespace
)
strong_memoize
(
:project_statistics
)
do
ProjectStatistics
.
safe_find_or_create_by!
(
project_id:
@project_id
)
rescue
ActiveRecord
::
NotNullViolation
,
ActiveRecord
::
RecordInvalid
end
end
end
end
end
end
end
...
...
ee/app/workers/all_queues.yml
View file @
dd36b5f5
...
@@ -791,6 +791,15 @@
...
@@ -791,6 +791,15 @@
:weight:
1
:weight:
1
:idempotent:
:idempotent:
:tags: []
:tags: []
-
:name: pipeline_background:ci_minutes_update_project_and_namespace_usage
:worker_name: Ci::Minutes::UpdateProjectAndNamespaceUsageWorker
:feature_category: :continuous_integration
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight:
1
:idempotent:
:tags: []
-
:name: pipeline_background:ci_sync_reports_to_report_approval_rules
-
:name: pipeline_background:ci_sync_reports_to_report_approval_rules
:worker_name: Ci::SyncReportsToReportApprovalRulesWorker
:worker_name: Ci::SyncReportsToReportApprovalRulesWorker
:feature_category: :continuous_integration
:feature_category: :continuous_integration
...
...
ee/app/workers/ci/minutes/update_project_and_namespace_usage_worker.rb
0 → 100644
View file @
dd36b5f5
# frozen_string_literal: true
module
Ci
module
Minutes
class
UpdateProjectAndNamespaceUsageWorker
# rubocop:disable Scalability/IdempotentWorker
include
ApplicationWorker
include
PipelineBackgroundQueue
urgency
:low
data_consistency
:always
# primarily performs writes
def
perform
(
consumption
,
project_id
,
namespace_id
)
::
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageService
.
new
(
project_id
,
namespace_id
).
execute
(
consumption
)
end
end
end
end
ee/app/workers/ee/ci/build_finished_worker.rb
View file @
dd36b5f5
...
@@ -4,7 +4,7 @@ module EE
...
@@ -4,7 +4,7 @@ module EE
module
Ci
module
Ci
module
BuildFinishedWorker
module
BuildFinishedWorker
def
process_build
(
build
)
def
process_build
(
build
)
unless
::
Feature
.
enabled?
(
:cancel_pipelines_prior_to_destroy
,
default_enabled: :yaml
)
unless
::
Feature
.
enabled?
(
:cancel_pipelines_prior_to_destroy
,
build
.
project
,
default_enabled: :yaml
)
::
Ci
::
Minutes
::
UpdateBuildMinutesService
.
new
(
build
.
project
,
nil
).
execute
(
build
)
::
Ci
::
Minutes
::
UpdateBuildMinutesService
.
new
(
build
.
project
,
nil
).
execute
(
build
)
end
end
...
...
ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb
View file @
dd36b5f5
...
@@ -22,7 +22,7 @@ RSpec.describe Ci::Minutes::NamespaceMonthlyUsage do
...
@@ -22,7 +22,7 @@ RSpec.describe Ci::Minutes::NamespaceMonthlyUsage do
end
end
describe
'.find_or_create_current'
do
describe
'.find_or_create_current'
do
subject
{
described_class
.
find_or_create_current
(
namespace
)
}
subject
{
described_class
.
find_or_create_current
(
namespace
_id:
namespace
.
id
)
}
shared_examples
'creates usage record'
do
shared_examples
'creates usage record'
do
it
'creates new record and resets minutes consumption'
do
it
'creates new record and resets minutes consumption'
do
...
...
ee/spec/models/ci/minutes/project_monthly_usage_spec.rb
View file @
dd36b5f5
...
@@ -22,7 +22,7 @@ RSpec.describe Ci::Minutes::ProjectMonthlyUsage do
...
@@ -22,7 +22,7 @@ RSpec.describe Ci::Minutes::ProjectMonthlyUsage do
end
end
describe
'.find_or_create_current'
do
describe
'.find_or_create_current'
do
subject
{
described_class
.
find_or_create_current
(
project
)
}
subject
{
described_class
.
find_or_create_current
(
project
_id:
project
.
id
)
}
shared_examples
'creates usage record'
do
shared_examples
'creates usage record'
do
it
'creates new record and resets minutes consumption'
do
it
'creates new record and resets minutes consumption'
do
...
...
ee/spec/services/ci/minutes/update_build_minutes_service_spec.rb
View file @
dd36b5f5
...
@@ -3,28 +3,28 @@
...
@@ -3,28 +3,28 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Ci
::
Minutes
::
UpdateBuildMinutesService
do
RSpec
.
describe
Ci
::
Minutes
::
UpdateBuildMinutesService
do
describe
'#perform'
do
let
(
:namespace
)
{
create
(
:namespace
,
shared_runners_minutes_limit:
100
)
}
let
(
:namespace
)
{
create
(
:namespace
,
shared_runners_minutes_limit:
100
)
}
let
(
:project
)
{
create
(
:project
,
:private
,
namespace:
namespace
)
}
let
(
:project
)
{
create
(
:project
,
:private
,
namespace:
namespace
)
}
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
)
}
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
)
}
let
(
:build
)
do
let
(
:build
)
do
create
(
:ci_build
,
:success
,
create
(
:ci_build
,
:success
,
runner:
runner
,
pipeline:
pipeline
,
runner:
runner
,
pipeline:
pipeline
,
started_at:
2
.
hours
.
ago
,
finished_at:
1
.
hour
.
ago
)
started_at:
2
.
hours
.
ago
,
finished_at:
1
.
hour
.
ago
)
end
end
let
(
:namespace_amount_used
)
{
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
namespace
).
amount_used
}
let
(
:namespace_amount_used
)
{
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
namespace_id:
namespace
.
id
).
amount_used
}
let
(
:project_amount_used
)
{
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_or_create_current
(
project
).
amount_used
}
let
(
:project_amount_used
)
{
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_or_create_current
(
project_id:
project
.
id
).
amount_used
}
subject
{
described_class
.
new
(
project
,
nil
).
execute
(
build
)
}
subject
{
described_class
.
new
(
project
,
nil
).
execute
(
build
)
}
shared_examples
'executes service'
do
shared_examples
'new tracking matches legacy tracking'
do
shared_examples
'new tracking matches legacy tracking'
do
it
'stores the same information in both legacy and new tracking'
do
it
'stores the same information in both legacy and new tracking'
do
subject
subject
expect
(
namespace_amount_used
)
expect
(
namespace_amount_used
)
.
to
eq
((
namespace
.
namespace_statistics
.
reload
.
shared_runners_seconds
.
to_f
/
60
).
round
(
2
))
.
to
eq
((
namespace
.
reload
.
namespace_statistics
.
shared_runners_seconds
.
to_f
/
60
).
round
(
2
))
expect
(
project_amount_used
)
expect
(
project_amount_used
)
.
to
eq
((
project
.
statistics
.
reload
.
shared_runners_seconds
.
to_f
/
60
).
round
(
2
))
.
to
eq
((
project
.
statistics
.
reload
.
shared_runners_seconds
.
to_f
/
60
).
round
(
2
))
...
@@ -181,7 +181,7 @@ RSpec.describe Ci::Minutes::UpdateBuildMinutesService do
...
@@ -181,7 +181,7 @@ RSpec.describe Ci::Minutes::UpdateBuildMinutesService do
let
(
:root_ancestor
)
{
create
(
:group
,
shared_runners_minutes_limit:
100
)
}
let
(
:root_ancestor
)
{
create
(
:group
,
shared_runners_minutes_limit:
100
)
}
let
(
:namespace
)
{
create
(
:group
,
parent:
root_ancestor
)
}
let
(
:namespace
)
{
create
(
:group
,
parent:
root_ancestor
)
}
let
(
:namespace_amount_used
)
{
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
root_ancestor
).
amount_used
}
let
(
:namespace_amount_used
)
{
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
namespace_id:
root_ancestor
.
id
).
amount_used
}
it
'creates a statistics in root group'
do
it
'creates a statistics in root group'
do
subject
subject
...
@@ -253,4 +253,18 @@ RSpec.describe Ci::Minutes::UpdateBuildMinutesService do
...
@@ -253,4 +253,18 @@ RSpec.describe Ci::Minutes::UpdateBuildMinutesService do
it_behaves_like
'does nothing'
it_behaves_like
'does nothing'
end
end
end
end
describe
'#execute'
do
context
'when cancel_pipelines_prior_to_destroy enabled'
,
:sidekiq_inline
do
include_examples
'executes service'
end
context
'when cancel_pipelines_prior_to_destroy disabled'
do
before
do
stub_feature_flags
(
cancel_pipelines_prior_to_destroy:
false
)
end
include_examples
'executes service'
end
end
end
end
ee/spec/services/ci/minutes/update_project_and_namespace_usage_service_spec.rb
View file @
dd36b5f5
...
@@ -3,16 +3,16 @@
...
@@ -3,16 +3,16 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageService
do
RSpec
.
describe
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageService
do
let_it_be
(
:
namespace
)
{
create
(
:namespace
,
shared_runners_minutes_limit:
100
)
}
let_it_be
(
:
project
)
{
create
(
:project
,
:private
)
}
let_it_be
(
:
project
)
{
create
(
:project
,
:private
,
namespace:
namespace
)
}
let_it_be
(
:
namespace
)
{
project
.
namespace
}
let
(
:consumption_minutes
)
{
120
}
let
(
:consumption_minutes
)
{
120
}
let
(
:consumption_seconds
)
{
consumption_minutes
*
60
}
let
(
:consumption_seconds
)
{
consumption_minutes
*
60
}
let
(
:namespace_amount_used
)
{
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
namespace
).
amount_used
}
let
(
:namespace_amount_used
)
{
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_or_create_current
(
namespace
_id:
namespace
.
id
).
amount_used
}
let
(
:project_amount_used
)
{
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_or_create_current
(
project
).
amount_used
}
let
(
:project_amount_used
)
{
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_or_create_current
(
project
_id:
project
.
id
).
amount_used
}
describe
'#execute'
do
describe
'#execute'
do
subject
{
described_class
.
new
(
project
,
namespace
).
execute
(
consumption_minutes
)
}
subject
{
described_class
.
new
(
project
.
id
,
namespace
.
id
).
execute
(
consumption_minutes
)
}
context
'with shared runner'
do
context
'with shared runner'
do
context
'when statistics and usage do not have existing values'
do
context
'when statistics and usage do not have existing values'
do
...
@@ -26,6 +26,46 @@ RSpec.describe Ci::Minutes::UpdateProjectAndNamespaceUsageService do
...
@@ -26,6 +26,46 @@ RSpec.describe Ci::Minutes::UpdateProjectAndNamespaceUsageService do
.
to
eq
(
consumption_seconds
)
.
to
eq
(
consumption_seconds
)
end
end
context
'when project deleted'
do
let
(
:project
)
{
double
(
id:
non_existing_record_id
)
}
it
'will complete successfully and increment namespace statistics'
do
subject
expect
(
ProjectStatistics
.
find_by_project_id
(
project
.
id
)).
to
be_nil
expect
(
NamespaceStatistics
.
find_by_namespace_id
(
namespace
.
id
).
shared_runners_seconds
).
to
eq
(
consumption_seconds
)
expect
(
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_by_project_id
(
project
.
id
)).
to
be_nil
expect
(
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_by_namespace_id
(
namespace
.
id
).
amount_used
).
to
eq
(
consumption_minutes
)
end
end
context
'when namespace deleted'
do
let
(
:namespace
)
{
double
(
id:
non_existing_record_id
)
}
it
'will complete successfully'
do
subject
expect
(
ProjectStatistics
.
find_by_project_id
(
project
.
id
).
shared_runners_seconds
).
to
eq
(
consumption_seconds
)
expect
(
NamespaceStatistics
.
find_by_namespace_id
(
namespace
.
id
)).
to
be_nil
expect
(
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_by_project_id
(
project
.
id
).
amount_used
).
to
eq
(
consumption_minutes
)
expect
(
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_by_namespace_id
(
namespace
.
id
).
amount_used
).
to
eq
(
consumption_minutes
)
end
end
context
'when project and namespace deleted'
do
let
(
:project
)
{
double
(
id:
non_existing_record_id
)
}
let
(
:namespace
)
{
double
(
id:
non_existing_record_id
)
}
it
'will complete successfully'
do
subject
expect
(
ProjectStatistics
.
find_by_project_id
(
project
.
id
)).
to
be_nil
expect
(
NamespaceStatistics
.
find_by_namespace_id
(
namespace
.
id
)).
to
be_nil
expect
(
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_by_project_id
(
project
.
id
)).
to
be_nil
expect
(
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_by_namespace_id
(
namespace
.
id
).
amount_used
).
to
eq
(
consumption_minutes
)
end
end
it
'updates monthly usage with consumption minutes'
do
it
'updates monthly usage with consumption minutes'
do
subject
subject
...
...
ee/spec/workers/ci/minutes/update_project_and_namespace_usage_worker_spec.rb
0 → 100644
View file @
dd36b5f5
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageWorker
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:namespace
)
{
project
.
namespace
}
let
(
:consumption
)
{
100
}
let
(
:consumption_seconds
)
{
consumption
*
60
}
let
(
:worker
)
{
described_class
.
new
}
describe
'#perform'
do
it
'executes UpdateProjectAndNamespaceUsageService'
do
service_instance
=
double
expect
(
::
Ci
::
Minutes
::
UpdateProjectAndNamespaceUsageService
).
to
receive
(
:new
).
with
(
project
.
id
,
namespace
.
id
).
and_return
(
service_instance
)
expect
(
service_instance
).
to
receive
(
:execute
).
with
(
consumption
)
worker
.
perform
(
consumption
,
project
.
id
,
namespace
.
id
)
end
it
'updates statistics and usage'
do
worker
.
perform
(
consumption
,
project
.
id
,
namespace
.
id
)
expect
(
project
.
statistics
.
reload
.
shared_runners_seconds
).
to
eq
(
consumption_seconds
)
expect
(
namespace
.
namespace_statistics
.
reload
.
shared_runners_seconds
).
to
eq
(
consumption_seconds
)
expect
(
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_by
(
namespace:
namespace
).
amount_used
).
to
eq
(
consumption
)
expect
(
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_by
(
project:
project
).
amount_used
).
to
eq
(
consumption
)
end
it
'accumulates only legacy statistics on failure (behaves transactionally)'
do
allow
(
Ci
::
Minutes
::
ProjectMonthlyUsage
).
to
receive
(
:new
).
and_raise
(
StandardError
)
expect
{
worker
.
perform
(
consumption
,
project
.
id
,
namespace
.
id
)
}.
to
raise_error
(
StandardError
)
expect
(
project
.
reload
.
statistics
.
shared_runners_seconds
).
to
eq
(
consumption_seconds
)
expect
(
namespace
.
reload
.
namespace_statistics
.
shared_runners_seconds
).
to
eq
(
consumption_seconds
)
expect
(
Ci
::
Minutes
::
NamespaceMonthlyUsage
.
find_by
(
namespace:
namespace
)).
to
eq
(
nil
)
expect
(
Ci
::
Minutes
::
ProjectMonthlyUsage
.
find_by
(
project:
project
)).
to
eq
(
nil
)
expect
(
::
Ci
::
Minutes
::
EmailNotificationService
).
not_to
receive
(
:new
)
end
end
end
lib/gitlab/ci/features.rb
View file @
dd36b5f5
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
module
Gitlab
module
Gitlab
module
Ci
module
Ci
##
##
# Ci::Features is a class that aggregates all CI/CD feature flags in one place.
#
Deprecated:
Ci::Features is a class that aggregates all CI/CD feature flags in one place.
#
#
module
Features
module
Features
# NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project`
# NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project`
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment