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
d886be07
Commit
d886be07
authored
Apr 12, 2022
by
Bala Kumar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Run all deployment jobs for the common pipeline with same environment
Changelog: changed
parent
855a4095
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
281 additions
and
50 deletions
+281
-50
app/controllers/projects/environments_controller.rb
app/controllers/projects/environments_controller.rb
+3
-3
app/models/environment.rb
app/models/environment.rb
+43
-10
app/policies/environment_policy.rb
app/policies/environment_policy.rb
+3
-3
app/serializers/environment_entity.rb
app/serializers/environment_entity.rb
+1
-1
app/services/environments/stop_service.rb
app/services/environments/stop_service.rb
+1
-1
app/workers/environments/auto_stop_worker.rb
app/workers/environments/auto_stop_worker.rb
+4
-2
config/feature_flags/development/environment_multiple_stop_actions.yml
...e_flags/development/environment_multiple_stop_actions.yml
+8
-0
lib/api/environments.rb
lib/api/environments.rb
+1
-1
spec/controllers/projects/environments_controller_spec.rb
spec/controllers/projects/environments_controller_spec.rb
+22
-6
spec/models/environment_spec.rb
spec/models/environment_spec.rb
+185
-21
spec/support/shared_examples/serializers/environment_serializer_shared_examples.rb
...les/serializers/environment_serializer_shared_examples.rb
+10
-2
No files found.
app/controllers/projects/environments_controller.rb
View file @
d886be07
...
@@ -104,11 +104,11 @@ class Projects::EnvironmentsController < Projects::ApplicationController
...
@@ -104,11 +104,11 @@ class Projects::EnvironmentsController < Projects::ApplicationController
def
stop
def
stop
return
render_404
unless
@environment
.
available?
return
render_404
unless
@environment
.
available?
stop_action
=
@environment
.
stop_with_action
!
(
current_user
)
stop_action
s
=
@environment
.
stop_with_actions
!
(
current_user
)
action_or_env_url
=
action_or_env_url
=
if
stop_action
if
stop_action
s
&
.
count
==
1
polymorphic_url
([
project
,
stop_action
])
polymorphic_url
([
project
,
stop_action
s
.
first
])
else
else
project_environment_url
(
project
,
@environment
)
project_environment_url
(
project
,
@environment
)
end
end
...
...
app/models/environment.rb
View file @
d886be07
...
@@ -59,7 +59,7 @@ class Environment < ApplicationRecord
...
@@ -59,7 +59,7 @@ class Environment < ApplicationRecord
allow_nil:
true
,
allow_nil:
true
,
addressable_url:
true
addressable_url:
true
delegate
:
stop_action
,
:
manual_actions
,
to: :last_deployment
,
allow_nil:
true
delegate
:manual_actions
,
to: :last_deployment
,
allow_nil:
true
delegate
:auto_rollback_enabled?
,
to: :project
delegate
:auto_rollback_enabled?
,
to: :project
scope
:available
,
->
{
with_state
(
:available
)
}
scope
:available
,
->
{
with_state
(
:available
)
}
...
@@ -185,6 +185,23 @@ class Environment < ApplicationRecord
...
@@ -185,6 +185,23 @@ class Environment < ApplicationRecord
last_deployment
&
.
deployable
last_deployment
&
.
deployable
end
end
def
last_deployment_pipeline
last_deployable
&
.
pipeline
end
# This method returns the deployment records of the last deployment pipeline, that successfully executed to this environment.
# e.g.
# A pipeline contains
# - deploy job A => production environment
# - deploy job B => production environment
# In this case, `last_deployment_group` returns both deployments, whereas `last_deployable` returns only B.
def
last_deployment_group
return
Deployment
.
none
unless
last_deployment_pipeline
successful_deployments
.
where
(
deployable_id:
last_deployment_pipeline
.
latest_builds
.
pluck
(
:id
))
end
# NOTE: Below assocation overrides is a workaround for issue https://gitlab.com/gitlab-org/gitlab/-/issues/339908
# NOTE: Below assocation overrides is a workaround for issue https://gitlab.com/gitlab-org/gitlab/-/issues/339908
# It helps to avoid cross joins with the CI database.
# It helps to avoid cross joins with the CI database.
# Caveat: It also overrides and losses the default AR caching mechanism.
# Caveat: It also overrides and losses the default AR caching mechanism.
...
@@ -255,8 +272,8 @@ class Environment < ApplicationRecord
...
@@ -255,8 +272,8 @@ class Environment < ApplicationRecord
external_url
.
gsub
(
%r{
\A
.*?://}
,
''
)
external_url
.
gsub
(
%r{
\A
.*?://}
,
''
)
end
end
def
stop_action_available?
def
stop_action
s
_available?
available?
&&
stop_action
.
present?
available?
&&
stop_action
s
.
present?
end
end
def
cancel_deployment_jobs!
def
cancel_deployment_jobs!
...
@@ -269,18 +286,34 @@ class Environment < ApplicationRecord
...
@@ -269,18 +286,34 @@ class Environment < ApplicationRecord
end
end
end
end
def
stop_with_action!
(
current_user
)
def
stop_with_action
s
!
(
current_user
)
return
unless
available?
return
unless
available?
stop!
stop!
return
unless
stop_action
actions
=
[]
Gitlab
::
OptimisticLocking
.
retry_lock
(
stop_actions
.
each
do
|
stop_action
|
stop_action
,
Gitlab
::
OptimisticLocking
.
retry_lock
(
name:
'environment_stop_with_action'
stop_action
,
)
do
|
build
|
name:
'environment_stop_with_actions'
build
&
.
play
(
current_user
)
)
do
|
build
|
actions
<<
build
.
play
(
current_user
)
end
end
actions
end
def
stop_actions
strong_memoize
(
:stop_actions
)
do
if
::
Feature
.
enabled?
(
:environment_multiple_stop_actions
,
project
,
default_enabled: :yaml
)
# Fix N+1 queries it brings to the serializer.
# Tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/358780
last_deployment_group
.
map
(
&
:stop_action
).
compact
else
[
last_deployment
&
.
stop_action
].
compact
end
end
end
end
end
...
...
app/policies/environment_policy.rb
View file @
d886be07
...
@@ -4,12 +4,12 @@ class EnvironmentPolicy < BasePolicy
...
@@ -4,12 +4,12 @@ class EnvironmentPolicy < BasePolicy
delegate
{
@subject
.
project
}
delegate
{
@subject
.
project
}
condition
(
:stop_with_deployment_allowed
)
do
condition
(
:stop_with_deployment_allowed
)
do
@subject
.
stop_action_available?
&&
@subject
.
stop_action
s
_available?
&&
can?
(
:create_deployment
)
&&
can?
(
:update_build
,
@subject
.
stop_action
)
can?
(
:create_deployment
)
&&
can?
(
:update_build
,
@subject
.
stop_action
s
.
last
)
end
end
condition
(
:stop_with_update_allowed
)
do
condition
(
:stop_with_update_allowed
)
do
!
@subject
.
stop_action_available?
&&
can?
(
:update_environment
,
@subject
)
!
@subject
.
stop_action
s
_available?
&&
can?
(
:update_environment
,
@subject
)
end
end
condition
(
:stopped
)
do
condition
(
:stopped
)
do
...
...
app/serializers/environment_entity.rb
View file @
d886be07
...
@@ -18,7 +18,7 @@ class EnvironmentEntity < Grape::Entity
...
@@ -18,7 +18,7 @@ class EnvironmentEntity < Grape::Entity
expose
:environment_type
expose
:environment_type
expose
:name_without_type
expose
:name_without_type
expose
:last_deployment
,
using:
DeploymentEntity
expose
:last_deployment
,
using:
DeploymentEntity
expose
:stop_action_available?
,
as: :has_stop_action
expose
:stop_action
s
_available?
,
as: :has_stop_action
expose
:rollout_status
,
if:
->
(
*
)
{
can_read_deploy_board?
},
using:
RolloutStatusEntity
expose
:rollout_status
,
if:
->
(
*
)
{
can_read_deploy_board?
},
using:
RolloutStatusEntity
expose
:tier
expose
:tier
...
...
app/services/environments/stop_service.rb
View file @
d886be07
...
@@ -7,7 +7,7 @@ module Environments
...
@@ -7,7 +7,7 @@ module Environments
def
execute
(
environment
)
def
execute
(
environment
)
return
unless
can?
(
current_user
,
:stop_environment
,
environment
)
return
unless
can?
(
current_user
,
:stop_environment
,
environment
)
environment
.
stop_with_action!
(
current_user
)
environment
.
stop_with_action
s
!
(
current_user
)
end
end
def
execute_for_branch
(
branch_name
)
def
execute_for_branch
(
branch_name
)
...
...
app/workers/environments/auto_stop_worker.rb
View file @
d886be07
...
@@ -10,8 +10,10 @@ module Environments
...
@@ -10,8 +10,10 @@ module Environments
def
perform
(
environment_id
,
params
=
{})
def
perform
(
environment_id
,
params
=
{})
Environment
.
find_by_id
(
environment_id
).
try
do
|
environment
|
Environment
.
find_by_id
(
environment_id
).
try
do
|
environment
|
user
=
environment
.
stop_action
&
.
user
stop_actions
=
environment
.
stop_actions
environment
.
stop_with_action!
(
user
)
user
=
stop_actions
.
last
&
.
user
environment
.
stop_with_actions!
(
user
)
end
end
end
end
end
end
...
...
config/feature_flags/development/environment_multiple_stop_actions.yml
0 → 100644
View file @
d886be07
---
name
:
environment_multiple_stop_actions
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84922
rollout_issue_url
:
https://gitlab.com/gitlab-org/gitlab/-/issues/358911
milestone
:
'
14.10'
type
:
development
group
:
group::release
default_enabled
:
false
lib/api/environments.rb
View file @
d886be07
...
@@ -131,7 +131,7 @@ module API
...
@@ -131,7 +131,7 @@ module API
environment
=
user_project
.
environments
.
find
(
params
[
:environment_id
])
environment
=
user_project
.
environments
.
find
(
params
[
:environment_id
])
authorize!
:stop_environment
,
environment
authorize!
:stop_environment
,
environment
environment
.
stop_with_action!
(
current_user
)
environment
.
stop_with_action
s
!
(
current_user
)
status
200
status
200
present
environment
,
with:
Entities
::
Environment
,
current_user:
current_user
present
environment
,
with:
Entities
::
Environment
,
current_user:
current_user
...
...
spec/controllers/projects/environments_controller_spec.rb
View file @
d886be07
...
@@ -254,38 +254,54 @@ RSpec.describe Projects::EnvironmentsController do
...
@@ -254,38 +254,54 @@ RSpec.describe Projects::EnvironmentsController do
end
end
describe
'PATCH #stop'
do
describe
'PATCH #stop'
do
subject
{
patch
:stop
,
params:
environment_params
(
format: :json
)
}
context
'when env not available'
do
context
'when env not available'
do
it
'returns 404'
do
it
'returns 404'
do
allow_any_instance_of
(
Environment
).
to
receive
(
:available?
)
{
false
}
allow_any_instance_of
(
Environment
).
to
receive
(
:available?
)
{
false
}
patch
:stop
,
params:
environment_params
(
format: :json
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
end
end
context
'when stop action'
do
context
'when stop action'
do
it
'returns action url'
do
it
'returns action url
for single stop action
'
do
action
=
create
(
:ci_build
,
:manual
)
action
=
create
(
:ci_build
,
:manual
)
allow_any_instance_of
(
Environment
)
allow_any_instance_of
(
Environment
)
.
to
receive_messages
(
available?:
true
,
stop_with_action
!:
action
)
.
to
receive_messages
(
available?:
true
,
stop_with_action
s!:
[
action
]
)
patch
:stop
,
params:
environment_params
(
format: :json
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
json_response
).
to
eq
(
expect
(
json_response
).
to
eq
(
{
'redirect_url'
=>
{
'redirect_url'
=>
project_job_url
(
project
,
action
)
})
project_job_url
(
project
,
action
)
})
end
end
it
'returns environment url for multiple stop actions'
do
actions
=
create_list
(
:ci_build
,
2
,
:manual
)
allow_any_instance_of
(
Environment
)
.
to
receive_messages
(
available?:
true
,
stop_with_actions!:
actions
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
json_response
).
to
eq
(
{
'redirect_url'
=>
project_environment_url
(
project
,
environment
)
})
end
end
end
context
'when no stop action'
do
context
'when no stop action'
do
it
'returns env url'
do
it
'returns env url'
do
allow_any_instance_of
(
Environment
)
allow_any_instance_of
(
Environment
)
.
to
receive_messages
(
available?:
true
,
stop_with_action!:
nil
)
.
to
receive_messages
(
available?:
true
,
stop_with_action
s
!:
nil
)
patch
:stop
,
params:
environment_params
(
format: :json
)
subject
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
json_response
).
to
eq
(
expect
(
json_response
).
to
eq
(
...
...
spec/models/environment_spec.rb
View file @
d886be07
This diff is collapsed.
Click to expand it.
spec/support/shared_examples/serializers/environment_serializer_shared_examples.rb
View file @
d886be07
...
@@ -8,7 +8,11 @@ RSpec.shared_examples 'avoid N+1 on environments serialization' do |ee: false|
...
@@ -8,7 +8,11 @@ RSpec.shared_examples 'avoid N+1 on environments serialization' do |ee: false|
create_environment_with_associations
(
project
)
create_environment_with_associations
(
project
)
create_environment_with_associations
(
project
)
create_environment_with_associations
(
project
)
expect
{
serialize
(
grouping:
true
)
}.
not_to
exceed_query_limit
(
control
.
count
)
# Fix N+1 queries introduced by multi stop_actions for environment.
# Tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/358780
relax_count
=
14
expect
{
serialize
(
grouping:
true
)
}.
not_to
exceed_query_limit
(
control
.
count
+
relax_count
)
end
end
it
'avoids N+1 database queries without grouping'
,
:request_store
do
it
'avoids N+1 database queries without grouping'
,
:request_store
do
...
@@ -19,7 +23,11 @@ RSpec.shared_examples 'avoid N+1 on environments serialization' do |ee: false|
...
@@ -19,7 +23,11 @@ RSpec.shared_examples 'avoid N+1 on environments serialization' do |ee: false|
create_environment_with_associations
(
project
)
create_environment_with_associations
(
project
)
create_environment_with_associations
(
project
)
create_environment_with_associations
(
project
)
expect
{
serialize
(
grouping:
false
)
}.
not_to
exceed_query_limit
(
control
.
count
)
# Fix N+1 queries introduced by multi stop_actions for environment.
# Tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/358780
relax_count
=
14
expect
{
serialize
(
grouping:
false
)
}.
not_to
exceed_query_limit
(
control
.
count
+
relax_count
)
end
end
it
'does not preload for environments that does not exist in the page'
,
:request_store
do
it
'does not preload for environments that does not exist in the page'
,
:request_store
do
...
...
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