Commit 4a9efc60 authored by Alessio Caiazza's avatar Alessio Caiazza

Move ci_environments_status to a model

GET :namespace/merge_requests/:id/ci_environments_status complexity
already reached a limit for a direct serialization from an hash
computed at within the controller function.

Here we introduce a virtual model EnvironmentStatus and its serializer.
parent c09de611
......@@ -198,43 +198,11 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def ci_environments_status
environments =
begin
@merge_request.environments_for(current_user).map do |environment|
project = environment.project
deployment = environment.first_deployment_for(@merge_request.diff_head_sha)
stop_url =
if can?(current_user, :stop_environment, environment)
stop_project_environment_path(project, environment)
end
metrics_url =
if can?(current_user, :read_environment, environment) && environment.has_metrics?
metrics_project_environment_deployment_path(project, environment, deployment)
end
metrics_monitoring_url =
if can?(current_user, :read_environment, environment)
environment_metrics_path(environment)
end
{
id: environment.id,
name: environment.name,
url: project_environment_path(project, environment),
metrics_url: metrics_url,
metrics_monitoring_url: metrics_monitoring_url,
stop_url: stop_url,
external_url: environment.external_url,
external_url_formatted: environment.formatted_external_url,
deployed_at: deployment.try(:created_at),
deployed_at_formatted: deployment.try(:formatted_deployment_time)
}
end.compact
end
environments = @merge_request.environments_for(current_user).map do |environment|
EnvironmentStatus.new(environment, @merge_request)
end
render json: environments
render json: EnvironmentStatusSerializer.new(current_user: current_user).represent(environments)
end
def rebase
......
# frozen_string_literal: true
class EnvironmentStatus
include Gitlab::Utils::StrongMemoize
attr_reader :environment, :merge_request
delegate :id, to: :environment
delegate :name, to: :environment
delegate :project, to: :environment
delegate :deployed_at, to: :deployment, allow_nil: true
def initialize(environment, merge_request)
@environment = environment
@merge_request = merge_request
end
def deployment
strong_memoize(:deployment) do
environment.first_deployment_for(merge_request.diff_head_sha)
end
end
def deployed_at
deployment&.created_at
end
end
# frozen_string_literal: true
class EnvironmentStatusEntity < Grape::Entity
include RequestAwareEntity
expose :id
expose :name
expose :url do |es|
project_environment_path(es.project, es.environment)
end
expose :metrics_url, if: ->(*) { can_read_environment? && environment.has_metrics? } do |es|
metrics_project_environment_deployment_path(es.project, es.environment, es.deployment)
end
expose :metrics_monitoring_url, if: ->(*) { can_read_environment? } do |es|
environment_metrics_path(es.environment)
end
expose :stop_url, if: ->(*) { can_stop_environment? } do |es|
stop_project_environment_path(es.project, es.environment)
end
expose :external_url do |es|
es.environment.external_url
end
expose :external_url_formatted do |es|
es.environment.formatted_external_url
end
expose :deployed_at
expose :deployed_at_formatted do |es|
es.deployment.try(:formatted_deployment_time)
end
private
def environment
object.environment
end
def project
object.environment.project
end
def current_user
request.current_user
end
def can_read_environment?
can?(current_user, :read_environment, environment)
end
def can_stop_environment?
can?(current_user, :stop_environment, environment)
end
end
# frozen_string_literal: true
class EnvironmentStatusSerializer < BaseSerializer
entity EnvironmentStatusEntity
end
......@@ -16,5 +16,10 @@ FactoryBot.define do
allow(deployment.project.repository).to receive(:create_ref)
end
end
trait :review_app do
sha { TestEnv::BRANCH_SHA['pages-deploy'] }
ref 'pages-deploy'
end
end
end
......@@ -101,6 +101,20 @@ FactoryBot.define do
end
end
trait :deployed_review_app do
target_branch 'pages-deploy-target'
transient do
deployment { create(:deployment, :review_app) }
end
after(:build) do |merge_request, evaluator|
merge_request.source_branch = evaluator.deployment.ref
merge_request.source_project = evaluator.deployment.project
merge_request.target_project = evaluator.deployment.project
end
end
after(:build) do |merge_request|
target_project = merge_request.target_project
source_project = merge_request.source_project
......
require 'spec_helper'
describe EnvironmentStatus do
let(:deployment) { create(:deployment, :review_app) }
let(:environment) { deployment.environment}
let(:project) { deployment.project }
let(:merge_request) { create(:merge_request, :deployed_review_app, deployment: deployment) }
subject(:environment_status) { described_class.new(environment, merge_request) }
it { is_expected.to delegate_method(:id).to(:environment) }
it { is_expected.to delegate_method(:name).to(:environment) }
it { is_expected.to delegate_method(:project).to(:environment) }
it { is_expected.to delegate_method(:deployed_at).to(:deployment).as(:created_at) }
describe '#project' do
subject { environment_status.project }
it { is_expected.to eq(project) }
end
describe '#merge_request' do
subject { environment_status.merge_request }
it { is_expected.to eq(merge_request) }
end
describe '#deployment' do
subject { environment_status.deployment }
it { is_expected.to eq(deployment) }
end
end
require 'spec_helper'
describe EnvironmentStatusEntity do
let(:user) { create(:user) }
let(:request) { double('request') }
let(:deployment) { create(:deployment, :review_app) }
let(:environment) { deployment.environment}
let(:project) { deployment.project }
let(:merge_request) { create(:merge_request, :deployed_review_app, deployment: deployment) }
let(:environment_status) { EnvironmentStatus.new(environment, merge_request) }
let(:entity) { described_class.new(environment_status, request: request) }
subject { entity.as_json }
before do
allow(request).to receive(:current_user).and_return(user)
end
it { is_expected.to include(:id) }
it { is_expected.to include(:name) }
it { is_expected.to include(:url) }
it { is_expected.to include(:external_url) }
it { is_expected.to include(:external_url_formatted) }
it { is_expected.to include(:deployed_at) }
it { is_expected.to include(:deployed_at_formatted) }
it { is_expected.not_to include(:stop_url) }
it { is_expected.not_to include(:metrics_url) }
it { is_expected.not_to include(:metrics_monitoring_url) }
context 'when the user is project maintainer' do
before do
project.add_maintainer(user)
end
it { is_expected.to include(:stop_url) }
end
end
......@@ -31,6 +31,8 @@ module TestEnv
'symlink-expand-diff' => '81e6355',
'expand-collapse-files' => '025db92',
'expand-collapse-lines' => '238e82d',
'pages-deploy' => '7897d5b',
'pages-deploy-target' => '7975be0',
'video' => '8879059',
'add-balsamiq-file' => 'b89b56d',
'crlf-diff' => '5938907',
......
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