diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb index 85c81cba511..002a71b593d 100644 --- a/app/controllers/projects/cycle_analytics_controller.rb +++ b/app/controllers/projects/cycle_analytics_controller.rb @@ -1,5 +1,21 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController def show - @cycle_analytics = CycleAnalytics.new(@project) + @cycle_analytics = CycleAnalytics.new(@project, from: parse_start_date) + end + + private + + def parse_start_date + case cycle_analytics_params[:start_date] + when '30' then 30.days.ago + when '90' then 90.days.ago + else 90.days.ago + end + end + + def cycle_analytics_params + return {} unless params[:cycle_analytics].present? + + { start_date: params[:cycle_analytics][:start_date] } end end diff --git a/app/models/cycle_analytics.rb b/app/models/cycle_analytics.rb index 331bb450e08..d6a0b5fcc7a 100644 --- a/app/models/cycle_analytics.rb +++ b/app/models/cycle_analytics.rb @@ -1,46 +1,49 @@ class CycleAnalytics - def initialize(project) + attr_reader :from + + def initialize(project, from:) @project = project + @from = from end def issue - calculate_metric(Queries::issues(@project), + calculate_metric(Queries::issues(@project, created_after: @from), -> (data_point) { data_point[:issue].created_at }, [Queries::issue_first_associated_with_milestone_at, Queries::issue_first_added_to_list_label_at]) end def plan - calculate_metric(Queries::issues(@project), + calculate_metric(Queries::issues(@project, created_after: @from), [Queries::issue_first_associated_with_milestone_at, Queries::issue_first_added_to_list_label_at], Queries::issue_closing_merge_request_opened_at) end def code - calculate_metric(Queries::merge_requests_closing_issues(@project), + calculate_metric(Queries::merge_requests_closing_issues(@project, created_after: @from), -> (data_point) { data_point[:merge_request].created_at }, [Queries::merge_request_first_assigned_to_user_other_than_author_at, Queries::merge_request_wip_flag_first_removed_at]) end def test - calculate_metric(Queries::merge_requests_closing_issues(@project), + calculate_metric(Queries::merge_requests_closing_issues(@project, created_after: @from), Queries::merge_request_build_started_at, Queries::merge_request_build_finished_at) end def review - calculate_metric(Queries::merge_requests_closing_issues(@project), + calculate_metric(Queries::merge_requests_closing_issues(@project, created_after: @from), [Queries::merge_request_first_assigned_to_user_other_than_author_at, Queries::merge_request_wip_flag_first_removed_at], [Queries::merge_request_first_closed_at, Queries::merge_request_merged_at]) end def staging - calculate_metric(Queries::merge_requests_closing_issues(@project), + calculate_metric(Queries::merge_requests_closing_issues(@project, created_after: @from), Queries::merge_request_merged_at, Queries::merge_request_deployed_to_any_environment_at) end def production - calculate_metric(Queries::merge_requests_closing_issues(@project), + calculate_metric(Queries::merge_requests_closing_issues(@project, created_after: @from), -> (data_point) { data_point[:issue].created_at }, Queries::merge_request_deployed_to_production_at) end diff --git a/app/models/cycle_analytics/queries.rb b/app/models/cycle_analytics/queries.rb index 122b2599bd3..1a9a1daa2b0 100644 --- a/app/models/cycle_analytics/queries.rb +++ b/app/models/cycle_analytics/queries.rb @@ -1,12 +1,12 @@ class CycleAnalytics module Queries class << self - def issues(project) - project.issues.map { |issue| { issue: issue } } + def issues(project, created_after:) + project.issues.where("created_at >= ?", created_after).map { |issue| { issue: issue } } end - def merge_requests_closing_issues(project) - issues(project).map do |data_point| + def merge_requests_closing_issues(project, options = {}) + issues(project, options).map do |data_point| merge_requests = data_point[:issue].closed_by_merge_requests(nil, check_if_open: false) merge_requests.map { |merge_request| { issue: data_point[:issue], merge_request: merge_request } } end.flatten diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml index 160c8eaca72..50ac9904445 100644 --- a/app/views/projects/cycle_analytics/show.html.haml +++ b/app/views/projects/cycle_analytics/show.html.haml @@ -1,3 +1,5 @@ +%h2 Cycle Analytics from #{@cycle_analytics.from} to Today + %ul.list-group %li.list-group-item Issue: diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index 6fdce020642..4dc7f62af98 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' describe 'CycleAnalytics#issue', models: true do let(:project) { create(:project) } - subject { CycleAnalytics.new(project) } + let(:from_date) { 10.days.ago } + subject { CycleAnalytics.new(project, from: from_date) } context "when calculating the median of times between: start: issue created_at @@ -26,16 +27,6 @@ describe 'CycleAnalytics#issue', models: true do median_start_time, median_end_time = start_and_end_times[2] expect(subject.issue).to eq(median_end_time - median_start_time) end - - it "does not include issues from other projects" do - 5.times do - milestone = create(:milestone, project: project) - issue = create(:issue) - issue.update(milestone: milestone) - end - - expect(subject.issue).to be_nil - end end context "when a label is added to the issue" do @@ -80,6 +71,29 @@ describe 'CycleAnalytics#issue', models: true do expect(subject.issue).to eq(milestone_add_time - start_time) end + + + it "does not include issues from other projects" do + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = create(:issue) + issue.update(milestone: milestone) + issue.update(label_ids: [list_label.id]) + + expect(subject.issue).to be_nil + end + + it "excludes issues created before the 'from' date" do + before_from_date = from_date - 5.days + + milestone = create(:milestone, project: project) + list_label = create(:label, lists: [create(:list)]) + issue = Timecop.freeze(before_from_date) { create(:issue, project: project)} + issue.update(milestone: milestone) + issue.update(label_ids: [list_label.id]) + + expect(subject.issue).to be_nil + end end end end