Commit 8e1deb2a authored by Jan Provaznik's avatar Jan Provaznik

Merge branch 'cycle-analytics-summary-endpoint' into 'master'

Expose cycle analytics summary separately

See merge request gitlab-org/gitlab!19229
parents 51d5357b 0172b7c9
# frozen_string_literal: true
module Analytics
module CycleAnalytics
class SummaryController < Analytics::ApplicationController
include CycleAnalyticsParams
check_feature_flag Gitlab::Analytics::CYCLE_ANALYTICS_FEATURE_FLAG
before_action :load_group
before_action :validate_params
def show
return render_403 unless can?(current_user, :read_group_cycle_analytics, @group)
group_level = ::CycleAnalytics::GroupLevel.new(group: @group, options: options(allowed_group_params))
render json: group_level.summary
end
private
def allowed_group_params
params.permit(:created_after, :created_before, project_ids: [])
end
def validate_params
if request_params.invalid?
render(
json: { message: 'Invalid parameters', errors: request_params.errors },
status: :unprocessable_entity
)
end
end
def request_params
@request_params ||= Gitlab::Analytics::CycleAnalytics::RequestParams.new(params.permit(:created_before, :created_after))
end
end
end
end
......@@ -14,6 +14,7 @@ namespace :analytics do
get :records
end
end
resource :summary, controller: :summary, only: [:show]
end
end
......
......@@ -187,18 +187,7 @@ describe Analytics::CycleAnalytics::StagesController do
expect(response).to match_response_schema('analytics/cycle_analytics/median', dir: 'ee')
end
context 'when params are invalid' do
before do
params[:created_before] = '2018-01-01'
end
it 'renders `unprocessable_entity`' do
subject
expect(response).to have_gitlab_http_status(:unprocessable_entity)
expect(response).to match_response_schema('analytics/cycle_analytics/validation_error', dir: 'ee')
end
end
include_examples 'date parameter examples'
include_examples 'group permission check on the controller level'
end
......@@ -217,6 +206,8 @@ describe Analytics::CycleAnalytics::StagesController do
expect(response).to be_successful
end
include_examples 'date parameter examples'
include_examples 'group permission check on the controller level'
end
end
......
# frozen_string_literal: true
require 'spec_helper'
describe Analytics::CycleAnalytics::SummaryController do
let_it_be(:user) { create(:user) }
let_it_be(:group, refind: true) { create(:group) }
let(:params) { { group_id: group.full_path, created_after: '2010-01-01', created_before: '2010-01-02' } }
before do
stub_feature_flags(Gitlab::Analytics::CYCLE_ANALYTICS_FEATURE_FLAG => true)
stub_licensed_features(cycle_analytics_for_groups: true)
group.add_reporter(user)
sign_in(user)
end
describe 'GET `show`' do
subject { get :show, params: params }
it 'succeeds' do
subject
expect(response).to be_successful
expect(response).to match_response_schema('analytics/cycle_analytics/summary', dir: 'ee')
end
include_examples 'date parameter examples'
include_examples 'group permission check on the controller level'
end
end
{
"type": "array",
"items": {
"minItems": 2,
"maxItems": 2,
"type": "object",
"required": ["value", "title"],
"properties": {
"value": {
"type": "integer"
},
"title": {
"type": "string"
}
},
"additionalProperties": false
}
}
......@@ -77,3 +77,68 @@ shared_context 'when invalid stage parameters are given' do
expect(response).to match_response_schema('analytics/cycle_analytics/validation_error', dir: 'ee')
end
end
shared_examples 'date parameter examples' do
before do
params[:created_after] = '2019-01-01'
params[:created_before] = '2020-01-01'
end
context 'when valid parameters are given' do
it 'succeeds' do
subject
expect(response).to be_successful
end
end
shared_examples 'example for invalid parameter' do
it 'renders `unprocessable_entity`' do
subject
expect(response).to have_gitlab_http_status(:unprocessable_entity)
expect(response).to match_response_schema('analytics/cycle_analytics/validation_error', dir: 'ee')
end
end
context 'when `created_after` is missing' do
before do
params.delete(:created_after)
end
include_examples 'example for invalid parameter'
end
context 'when `created_after` is invalid' do
before do
params[:created_after] = 'not-a-date'
end
include_examples 'example for invalid parameter'
end
context 'when `created_before` is missing' do
before do
params.delete(:created_before)
end
include_examples 'example for invalid parameter'
end
context 'when `created_after` is invalid' do
before do
params[:created_before] = 'not-a-date'
end
include_examples 'example for invalid parameter'
end
context 'when `created_after` is later than `created_before`' do
before do
params[:created_after] = '2012-01-01'
params[:created_before] = '2010-01-01'
end
include_examples 'example for invalid parameter'
end
end
......@@ -3,18 +3,17 @@
module Gitlab
module CycleAnalytics
class GroupStageSummary
attr_reader :group, :from, :current_user, :options
attr_reader :group, :current_user, :options
def initialize(group, options:)
@group = group
@from = options[:from]
@current_user = options[:current_user]
@options = options
end
def data
[serialize(Summary::Group::Issue.new(group: group, from: from, current_user: current_user, options: options)),
serialize(Summary::Group::Deploy.new(group: group, from: from, options: options))]
[serialize(Summary::Group::Issue.new(group: group, current_user: current_user, options: options)),
serialize(Summary::Group::Deploy.new(group: group, options: options))]
end
private
......
......@@ -5,11 +5,10 @@ module Gitlab
module Summary
module Group
class Base
attr_reader :group, :from, :options
attr_reader :group, :options
def initialize(group:, from:, options:)
def initialize(group:, options:)
@group = group
@from = from
@options = options
end
......
......@@ -20,7 +20,8 @@ module Gitlab
def find_deployments
deployments = Deployment.joins(:project).merge(Project.inside_path(group.full_path))
deployments = deployments.where(projects: { id: options[:projects] }) if options[:projects]
deployments = deployments.where("deployments.created_at > ?", from)
deployments = deployments.where("deployments.created_at > ?", options[:from])
deployments = deployments.where("deployments.created_at < ?", options[:to]) if options[:to]
deployments.success.count
end
end
......
......@@ -5,11 +5,10 @@ module Gitlab
module Summary
module Group
class Issue < Group::Base
attr_reader :group, :from, :current_user, :options
attr_reader :group, :current_user, :options
def initialize(group:, from:, current_user:, options:)
def initialize(group:, current_user:, options:)
@group = group
@from = from
@current_user = current_user
@options = options
end
......@@ -25,10 +24,19 @@ module Gitlab
private
def find_issues
issues = IssuesFinder.new(current_user, group_id: group.id, include_subgroups: true, created_after: from).execute
issues = IssuesFinder.new(current_user, finder_params).execute
issues = issues.where(projects: { id: options[:projects] }) if options[:projects]
issues.count
end
def finder_params
{
group_id: group.id,
include_subgroups: true,
created_after: options[:from],
created_before: options[:to]
}.compact
end
end
end
end
......
......@@ -44,6 +44,14 @@ describe Gitlab::CycleAnalytics::GroupStageSummary do
expect(subject.first[:value]).to eq(2)
end
end
context 'when `from` and `to` parameters are provided' do
subject { described_class.new(group, options: { from: 10.days.ago, to: Time.now, current_user: user }).data }
it 'finds issues from 5 days ago' do
expect(subject.first[:value]).to eq(2)
end
end
end
context 'with other projects' do
......@@ -97,6 +105,14 @@ describe Gitlab::CycleAnalytics::GroupStageSummary do
expect(subject.second[:value]).to eq(2)
end
end
context 'when `from` and `to` parameters are provided' do
subject { described_class.new(group, options: { from: 10.days.ago, to: Time.now, current_user: user }).data }
it 'finds deployments from 5 days ago' do
expect(subject.second[:value]).to eq(2)
end
end
end
context 'with other projects' 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