Adapt cycle analytics spec helper and cycle analytics usage data spec
This commit is contained in:
parent
335ee79a73
commit
522f4b2c6a
|
|
@ -7,8 +7,7 @@ class AnalyticsStageEntity < Grape::Entity
|
|||
expose :description
|
||||
|
||||
expose :median, as: :value do |stage|
|
||||
if stage.median && !(stage.median.nil? || stage.median.zero?)
|
||||
distance_of_time_in_words(stage.median)
|
||||
end
|
||||
# median returns a BatchLoader instance which we first have to unwrap by using to_i
|
||||
!stage.median.to_i.zero? ? distance_of_time_in_words(stage.median) : nil
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Include cycle time in usage ping data
|
||||
merge_request: 16973
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -15,7 +15,7 @@ module Gitlab
|
|||
query = mr_closing_issues_table.join(issue_table).on(issue_table[:id].eq(mr_closing_issues_table[:issue_id]))
|
||||
.join(issue_metrics_table).on(issue_table[:id].eq(issue_metrics_table[:issue_id]))
|
||||
.project(issue_table[:project_id].as("project_id"))
|
||||
.where(issue_table[:project_id].in(Array(project_ids)))
|
||||
.where(issue_table[:project_id].in(project_ids))
|
||||
.where(issue_table[:created_at].gteq(@options[:from])) # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
|
||||
# Load merge_requests
|
||||
|
|
|
|||
|
|
@ -31,12 +31,16 @@ module Gitlab
|
|||
interval_query = Arel::Nodes::As.new(cte_table,
|
||||
subtract_datetimes(stage_query(project_ids), start_time_attrs, end_time_attrs, name.to_s))
|
||||
|
||||
if project_ids.size == 1
|
||||
if project_ids.one?
|
||||
loader.call(@project.id, median_datetime(cte_table, interval_query, name))
|
||||
else
|
||||
begin
|
||||
median_datetimes(cte_table, interval_query, name, :project_id)&.each do |project_id, median|
|
||||
loader.call(project_id, median)
|
||||
end
|
||||
rescue NotSupportedError
|
||||
{}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
module Gitlab
|
||||
module Database
|
||||
module Median
|
||||
NotSupportedError = Class.new(StandardError)
|
||||
|
||||
def median_datetime(arel_table, query_so_far, column_sym)
|
||||
extract_median(execute_queries(arel_table, query_so_far, column_sym)).presence
|
||||
end
|
||||
|
|
@ -23,11 +25,11 @@ module Gitlab
|
|||
end
|
||||
|
||||
def extract_medians(results)
|
||||
return {} if Gitlab::Database.mysql?
|
||||
median_values = results.compact.first.values
|
||||
|
||||
results.compact.first.values.map do |id, median|
|
||||
[id.to_i, median&.to_f]
|
||||
end.to_h
|
||||
median_values.each_with_object({}) do |(id, median), hash|
|
||||
hash[id.to_i] = median&.to_f
|
||||
end
|
||||
end
|
||||
|
||||
def mysql_median_datetime_sql(arel_table, query_so_far, column_sym)
|
||||
|
|
@ -113,6 +115,8 @@ module Gitlab
|
|||
if Gitlab::Database.postgresql?
|
||||
pg_median_datetime_sql(arel_table, query_so_far, column_sym, partition_column)
|
||||
elsif Gitlab::Database.mysql?
|
||||
raise NotSupportedError, "partition_column is not supported for MySQL" if partition_column
|
||||
|
||||
mysql_median_datetime_sql(arel_table, query_so_far, column_sym)
|
||||
end
|
||||
end
|
||||
|
|
@ -159,12 +163,10 @@ module Gitlab
|
|||
end
|
||||
|
||||
def median_projections(table, column_sym, partition_column)
|
||||
if partition_column
|
||||
[table[partition_column],
|
||||
average([extract_epoch(table[column_sym])], "median")]
|
||||
else
|
||||
[average([extract_epoch(table[column_sym])], "median")]
|
||||
end
|
||||
projections = []
|
||||
projections << table[partition_column] if partition_column
|
||||
projections << average([extract_epoch(table[column_sym])], "median")
|
||||
projections
|
||||
end
|
||||
|
||||
def extract_epoch(arel_attribute)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ describe Projects::CycleAnalyticsController do
|
|||
milestone = create(:milestone, project: project, created_at: 5.days.ago)
|
||||
issue.update(milestone: milestone)
|
||||
|
||||
create_merge_request_closing_issue(issue)
|
||||
create_merge_request_closing_issue(user, project, issue)
|
||||
end
|
||||
|
||||
it 'is false' do
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ feature 'Cycle Analytics', :js do
|
|||
let(:project) { create(:project, :repository) }
|
||||
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
|
||||
let(:milestone) { create(:milestone, project: project) }
|
||||
let(:mr) { create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}") }
|
||||
let(:mr) { create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}") }
|
||||
let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr) }
|
||||
|
||||
context 'as an allowed user' do
|
||||
|
|
@ -42,7 +42,7 @@ feature 'Cycle Analytics', :js do
|
|||
project.add_master(user)
|
||||
|
||||
@build = create_cycle(user, project, issue, mr, milestone, pipeline)
|
||||
deploy_master
|
||||
deploy_master(user, project)
|
||||
|
||||
sign_in(user)
|
||||
visit project_cycle_analytics_path(project)
|
||||
|
|
@ -118,7 +118,7 @@ feature 'Cycle Analytics', :js do
|
|||
|
||||
allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue])
|
||||
create_cycle(user, project, issue, mr, milestone, pipeline)
|
||||
deploy_master
|
||||
deploy_master(user, project)
|
||||
|
||||
sign_in(guest)
|
||||
visit project_cycle_analytics_path(project)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ describe Gitlab::CycleAnalytics::BaseEventFetcher do
|
|||
milestone = create(:milestone, project: project)
|
||||
|
||||
issue.update(milestone: milestone)
|
||||
create_merge_request_closing_issue(issue)
|
||||
create_merge_request_closing_issue(user, project, issue)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -236,8 +236,8 @@ describe 'cycle analytics events' do
|
|||
pipeline.run!
|
||||
pipeline.succeed!
|
||||
|
||||
merge_merge_requests_closing_issue(context)
|
||||
deploy_master
|
||||
merge_merge_requests_closing_issue(user, project, context)
|
||||
deploy_master(user, project)
|
||||
end
|
||||
|
||||
it 'has the name' do
|
||||
|
|
@ -294,8 +294,8 @@ describe 'cycle analytics events' do
|
|||
let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
|
||||
|
||||
before do
|
||||
merge_merge_requests_closing_issue(context)
|
||||
deploy_master
|
||||
merge_merge_requests_closing_issue(user, project, context)
|
||||
deploy_master(user, project)
|
||||
end
|
||||
|
||||
it 'has the total time' do
|
||||
|
|
@ -334,7 +334,7 @@ describe 'cycle analytics events' do
|
|||
def setup(context)
|
||||
milestone = create(:milestone, project: project)
|
||||
context.update(milestone: milestone)
|
||||
mr = create_merge_request_closing_issue(context, commit_message: "References #{context.to_reference}")
|
||||
mr = create_merge_request_closing_issue(user, project, context, commit_message: "References #{context.to_reference}")
|
||||
|
||||
ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.to_hash)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,36 +1,140 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::CycleAnalytics::UsageData do
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:user) { create(:user, :admin) }
|
||||
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
|
||||
let(:milestone) { create(:milestone, project: project) }
|
||||
let(:mr) { create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}") }
|
||||
let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr) }
|
||||
|
||||
subject { described_class.new([project]) }
|
||||
|
||||
describe '#to_json' do
|
||||
before do
|
||||
Timecop.freeze do
|
||||
user = create(:user, :admin)
|
||||
projects = create_list(:project, 2, :repository)
|
||||
|
||||
projects.each_with_index do |project, time|
|
||||
issue = create(:issue, project: project, created_at: (time + 1).hour.ago)
|
||||
|
||||
allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue])
|
||||
|
||||
milestone = create(:milestone, project: project)
|
||||
mr = create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}")
|
||||
pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr)
|
||||
|
||||
create_cycle(user, project, issue, mr, milestone, pipeline)
|
||||
deploy_master
|
||||
deploy_master(user, project, environment: 'staging')
|
||||
deploy_master(user, project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'a valid usage data result' do
|
||||
it 'returns the aggregated usage data of every selected project' do
|
||||
result = subject.to_json
|
||||
avg_cycle_analytics = result[:avg_cycle_analytics]
|
||||
|
||||
expect(result).to have_key(:avg_cycle_analytics)
|
||||
CycleAnalytics::STAGES.each do |stage_name|
|
||||
stage_values = avg_cycle_analytics[stage_name]
|
||||
|
||||
expect(avg_cycle_analytics).to have_key(stage_name)
|
||||
expect(stage_values).to have_key(:average)
|
||||
expect(stage_values).to have_key(:sd)
|
||||
expect(stage_values).to have_key(:missing)
|
||||
CycleAnalytics::STAGES.each do |stage|
|
||||
expect(result[:avg_cycle_analytics]).to have_key(stage)
|
||||
|
||||
stage_values = result[:avg_cycle_analytics][stage]
|
||||
expected_values = expect_values_per_stage[stage]
|
||||
|
||||
expected_values.each_pair do |op, value|
|
||||
expect(stage_values).to have_key(op)
|
||||
|
||||
if op == :missing
|
||||
expect(stage_values[op]).to eq(value)
|
||||
else
|
||||
# delta is used because of git timings that Timecop does not stub
|
||||
expect(stage_values[op].to_i).to be_within(5).of(value.to_i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using postgresql', :postgresql do
|
||||
let(:expect_values_per_stage) do
|
||||
{
|
||||
issue: {
|
||||
average: 5400,
|
||||
sd: 2545,
|
||||
missing: 0
|
||||
},
|
||||
plan: {
|
||||
average: 2,
|
||||
sd: 2,
|
||||
missing: 0
|
||||
},
|
||||
code: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
test: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
review: {
|
||||
average: 0,
|
||||
sd: 0,
|
||||
missing: 0
|
||||
},
|
||||
staging: {
|
||||
average: 0,
|
||||
sd: 0,
|
||||
missing: 0
|
||||
},
|
||||
production: {
|
||||
average: 5400,
|
||||
sd: 2545,
|
||||
missing: 0
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like 'a valid usage data result'
|
||||
end
|
||||
|
||||
context 'when using mysql', :mysql do
|
||||
let(:expect_values_per_stage) do
|
||||
{
|
||||
issue: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
plan: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
code: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
test: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
review: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
staging: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
},
|
||||
production: {
|
||||
average: nil,
|
||||
sd: 0,
|
||||
missing: 2
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it_behaves_like 'a valid usage data result'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Database::Median do
|
||||
describe '#extract_medians' do
|
||||
context 'when using MySQL' do
|
||||
it 'returns an empty hash' do
|
||||
values = [["1", "1000"]]
|
||||
|
||||
allow(Gitlab::Database).to receive(:mysql?).and_return(true)
|
||||
|
||||
expect(described_class.new.extract_median(values)).eq({})
|
||||
let(:dummy_class) do
|
||||
Class.new do
|
||||
include Gitlab::Database::Median
|
||||
end
|
||||
end
|
||||
|
||||
subject(:median) { dummy_class.new }
|
||||
|
||||
describe '#median_datetimes' do
|
||||
it 'raises NotSupportedError', :mysql do
|
||||
expect { median.median_datetimes(nil, nil, nil, :project_id) }.to raise_error(dummy_class::NotSupportedError, "partition_column is not supported for MySQL")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ describe 'CycleAnalytics#code' do
|
|||
end]],
|
||||
end_time_conditions: [["merge request that closes issue is created",
|
||||
-> (context, data) do
|
||||
context.create_merge_request_closing_issue(data[:issue])
|
||||
context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
|
||||
end]],
|
||||
post_fn: -> (context, data) do
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.deploy_master
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
context.deploy_master(context.user, context.project)
|
||||
end)
|
||||
|
||||
context "when a regular merge request (that doesn't close the issue) is created" do
|
||||
|
|
@ -30,10 +30,10 @@ describe 'CycleAnalytics#code' do
|
|||
issue = create(:issue, project: project)
|
||||
|
||||
create_commit_referencing_issue(issue)
|
||||
create_merge_request_closing_issue(issue, message: "Closes nothing")
|
||||
create_merge_request_closing_issue(user, project, issue, message: "Closes nothing")
|
||||
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
deploy_master
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
deploy_master(user, project)
|
||||
|
||||
expect(subject[:code].median).to be_nil
|
||||
end
|
||||
|
|
@ -50,10 +50,10 @@ describe 'CycleAnalytics#code' do
|
|||
end]],
|
||||
end_time_conditions: [["merge request that closes issue is created",
|
||||
-> (context, data) do
|
||||
context.create_merge_request_closing_issue(data[:issue])
|
||||
context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
|
||||
end]],
|
||||
post_fn: -> (context, data) do
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
end)
|
||||
|
||||
context "when a regular merge request (that doesn't close the issue) is created" do
|
||||
|
|
@ -61,9 +61,9 @@ describe 'CycleAnalytics#code' do
|
|||
issue = create(:issue, project: project)
|
||||
|
||||
create_commit_referencing_issue(issue)
|
||||
create_merge_request_closing_issue(issue, message: "Closes nothing")
|
||||
create_merge_request_closing_issue(user, project, issue, message: "Closes nothing")
|
||||
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
|
||||
expect(subject[:code].median).to be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ describe 'CycleAnalytics#issue' do
|
|||
end]],
|
||||
post_fn: -> (context, data) do
|
||||
if data[:issue].persisted?
|
||||
context.create_merge_request_closing_issue(data[:issue].reload)
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.create_merge_request_closing_issue(context.user, context.project, data[:issue].reload)
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
@ -37,8 +37,8 @@ describe 'CycleAnalytics#issue' do
|
|||
issue = create(:issue, project: project)
|
||||
issue.update(label_ids: [regular_label.id])
|
||||
|
||||
create_merge_request_closing_issue(issue)
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
create_merge_request_closing_issue(user, project, issue)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
|
||||
expect(subject[:issue].median).to be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ describe 'CycleAnalytics#plan' do
|
|||
context.create_commit_referencing_issue(data[:issue], branch_name: data[:branch_name])
|
||||
end]],
|
||||
post_fn: -> (context, data) do
|
||||
context.create_merge_request_closing_issue(data[:issue], source_branch: data[:branch_name])
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.create_merge_request_closing_issue(context.user, context.project, data[:issue], source_branch: data[:branch_name])
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
end)
|
||||
|
||||
context "when a regular label (instead of a list label) is added to the issue" do
|
||||
|
|
@ -41,8 +41,8 @@ describe 'CycleAnalytics#plan' do
|
|||
issue.update(label_ids: [label.id])
|
||||
create_commit_referencing_issue(issue, branch_name: branch_name)
|
||||
|
||||
create_merge_request_closing_issue(issue, source_branch: branch_name)
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
create_merge_request_closing_issue(user, project, issue, source_branch: branch_name)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
|
||||
expect(subject[:issue].median).to be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ describe 'CycleAnalytics#production' do
|
|||
data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } },
|
||||
start_time_conditions: [["issue is created", -> (context, data) { data[:issue].save }]],
|
||||
before_end_fn: lambda do |context, data|
|
||||
context.create_merge_request_closing_issue(data[:issue])
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
end,
|
||||
end_time_conditions:
|
||||
[["merge request that closes issue is deployed to production", -> (context, data) { context.deploy_master }],
|
||||
[["merge request that closes issue is deployed to production", -> (context, data) { context.deploy_master(context.user, context.project) }],
|
||||
["production deploy happens after merge request is merged (along with other changes)",
|
||||
lambda do |context, data|
|
||||
# Make other changes on master
|
||||
|
|
@ -29,14 +29,14 @@ describe 'CycleAnalytics#production' do
|
|||
branch_name: 'master')
|
||||
context.project.repository.commit(sha)
|
||||
|
||||
context.deploy_master
|
||||
context.deploy_master(context.user, context.project)
|
||||
end]])
|
||||
|
||||
context "when a regular merge request (that doesn't close the issue) is merged and deployed" do
|
||||
it "returns nil" do
|
||||
merge_request = create(:merge_request)
|
||||
MergeRequests::MergeService.new(project, user).execute(merge_request)
|
||||
deploy_master
|
||||
deploy_master(user, project)
|
||||
|
||||
expect(subject[:production].median).to be_nil
|
||||
end
|
||||
|
|
@ -45,9 +45,9 @@ describe 'CycleAnalytics#production' do
|
|||
context "when the deployment happens to a non-production environment" do
|
||||
it "returns nil" do
|
||||
issue = create(:issue, project: project)
|
||||
merge_request = create_merge_request_closing_issue(issue)
|
||||
merge_request = create_merge_request_closing_issue(user, project, issue)
|
||||
MergeRequests::MergeService.new(project, user).execute(merge_request)
|
||||
deploy_master(environment: 'staging')
|
||||
deploy_master(user, project, environment: 'staging')
|
||||
|
||||
expect(subject[:production].median).to be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ describe 'CycleAnalytics#review' do
|
|||
data_fn: -> (context) { { issue: context.create(:issue, project: context.project) } },
|
||||
start_time_conditions: [["merge request that closes issue is created",
|
||||
-> (context, data) do
|
||||
context.create_merge_request_closing_issue(data[:issue])
|
||||
context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
|
||||
end]],
|
||||
end_time_conditions: [["merge request that closes issue is merged",
|
||||
-> (context, data) do
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
end]],
|
||||
post_fn: nil)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ describe 'CycleAnalytics#staging' do
|
|||
phase: :staging,
|
||||
data_fn: lambda do |context|
|
||||
issue = context.create(:issue, project: context.project)
|
||||
{ issue: issue, merge_request: context.create_merge_request_closing_issue(issue) }
|
||||
{ issue: issue, merge_request: context.create_merge_request_closing_issue(context.user, context.project, issue) }
|
||||
end,
|
||||
start_time_conditions: [["merge request that closes issue is merged",
|
||||
-> (context, data) do
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
end]],
|
||||
end_time_conditions: [["merge request that closes issue is deployed to production",
|
||||
-> (context, data) do
|
||||
context.deploy_master
|
||||
context.deploy_master(context.user, context.project)
|
||||
end],
|
||||
["production deploy happens after merge request is merged (along with other changes)",
|
||||
lambda do |context, data|
|
||||
|
|
@ -34,14 +34,14 @@ describe 'CycleAnalytics#staging' do
|
|||
branch_name: 'master')
|
||||
context.project.repository.commit(sha)
|
||||
|
||||
context.deploy_master
|
||||
context.deploy_master(context.user, context.project)
|
||||
end]])
|
||||
|
||||
context "when a regular merge request (that doesn't close the issue) is merged and deployed" do
|
||||
it "returns nil" do
|
||||
merge_request = create(:merge_request)
|
||||
MergeRequests::MergeService.new(project, user).execute(merge_request)
|
||||
deploy_master
|
||||
deploy_master(user, project)
|
||||
|
||||
expect(subject[:staging].median).to be_nil
|
||||
end
|
||||
|
|
@ -50,9 +50,9 @@ describe 'CycleAnalytics#staging' do
|
|||
context "when the deployment happens to a non-production environment" do
|
||||
it "returns nil" do
|
||||
issue = create(:issue, project: project)
|
||||
merge_request = create_merge_request_closing_issue(issue)
|
||||
merge_request = create_merge_request_closing_issue(user, project, issue)
|
||||
MergeRequests::MergeService.new(project, user).execute(merge_request)
|
||||
deploy_master(environment: 'staging')
|
||||
deploy_master(user, project, environment: 'staging')
|
||||
|
||||
expect(subject[:staging].median).to be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,26 +12,26 @@ describe 'CycleAnalytics#test' do
|
|||
phase: :test,
|
||||
data_fn: lambda do |context|
|
||||
issue = context.create(:issue, project: context.project)
|
||||
merge_request = context.create_merge_request_closing_issue(issue)
|
||||
merge_request = context.create_merge_request_closing_issue(context.user, context.project, issue)
|
||||
pipeline = context.create(:ci_pipeline, ref: merge_request.source_branch, sha: merge_request.diff_head_sha, project: context.project, head_pipeline_of: merge_request)
|
||||
{ pipeline: pipeline, issue: issue }
|
||||
end,
|
||||
start_time_conditions: [["pipeline is started", -> (context, data) { data[:pipeline].run! }]],
|
||||
end_time_conditions: [["pipeline is finished", -> (context, data) { data[:pipeline].succeed! }]],
|
||||
post_fn: -> (context, data) do
|
||||
context.merge_merge_requests_closing_issue(data[:issue])
|
||||
context.merge_merge_requests_closing_issue(context.user, context.project, data[:issue])
|
||||
end)
|
||||
|
||||
context "when the pipeline is for a regular merge request (that doesn't close an issue)" do
|
||||
it "returns nil" do
|
||||
issue = create(:issue, project: project)
|
||||
merge_request = create_merge_request_closing_issue(issue)
|
||||
merge_request = create_merge_request_closing_issue(user, project, issue)
|
||||
pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha)
|
||||
|
||||
pipeline.run!
|
||||
pipeline.succeed!
|
||||
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
|
||||
expect(subject[:test].median).to be_nil
|
||||
end
|
||||
|
|
@ -51,13 +51,13 @@ describe 'CycleAnalytics#test' do
|
|||
context "when the pipeline is dropped (failed)" do
|
||||
it "returns nil" do
|
||||
issue = create(:issue, project: project)
|
||||
merge_request = create_merge_request_closing_issue(issue)
|
||||
merge_request = create_merge_request_closing_issue(user, project, issue)
|
||||
pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha)
|
||||
|
||||
pipeline.run!
|
||||
pipeline.drop!
|
||||
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
|
||||
expect(subject[:test].median).to be_nil
|
||||
end
|
||||
|
|
@ -66,13 +66,13 @@ describe 'CycleAnalytics#test' do
|
|||
context "when the pipeline is cancelled" do
|
||||
it "returns nil" do
|
||||
issue = create(:issue, project: project)
|
||||
merge_request = create_merge_request_closing_issue(issue)
|
||||
merge_request = create_merge_request_closing_issue(user, project, issue)
|
||||
pipeline = create(:ci_pipeline, ref: "refs/heads/#{merge_request.source_branch}", sha: merge_request.diff_head_sha)
|
||||
|
||||
pipeline.run!
|
||||
pipeline.cancel!
|
||||
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
|
||||
expect(subject[:test].median).to be_nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ describe CycleAnalytics do
|
|||
let(:user) { create(:user, :admin) }
|
||||
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
|
||||
let(:milestone) { create(:milestone, project: project) }
|
||||
let(:mr) { create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}") }
|
||||
let(:mr) { create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}") }
|
||||
let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr) }
|
||||
|
||||
subject { described_class.new(project, from: from_date) }
|
||||
|
|
@ -16,7 +16,7 @@ describe CycleAnalytics do
|
|||
allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue])
|
||||
|
||||
create_cycle(user, project, issue, mr, milestone, pipeline)
|
||||
deploy_master
|
||||
deploy_master(user, project)
|
||||
end
|
||||
|
||||
it 'returns every median for each stage for a specific project' do
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ describe 'cycle analytics events' do
|
|||
end
|
||||
end
|
||||
|
||||
deploy_master
|
||||
deploy_master(user, project)
|
||||
|
||||
login_as(user)
|
||||
end
|
||||
|
|
@ -119,7 +119,7 @@ describe 'cycle analytics events' do
|
|||
def create_cycle
|
||||
milestone = create(:milestone, project: project)
|
||||
issue.update(milestone: milestone)
|
||||
mr = create_merge_request_closing_issue(issue, commit_message: "References #{issue.to_reference}")
|
||||
mr = create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}")
|
||||
|
||||
pipeline = create(:ci_empty_pipeline, status: 'created', project: project, ref: mr.source_branch, sha: mr.source_branch_sha, head_pipeline_of: mr)
|
||||
pipeline.run
|
||||
|
|
@ -127,7 +127,7 @@ describe 'cycle analytics events' do
|
|||
create(:ci_build, pipeline: pipeline, status: :success, author: user)
|
||||
create(:ci_build, pipeline: pipeline, status: :success, author: user)
|
||||
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
|
||||
ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.to_hash)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -186,6 +186,10 @@ RSpec.configure do |config|
|
|||
example.run if Gitlab::Database.postgresql?
|
||||
end
|
||||
|
||||
config.around(:each, :mysql) do |example|
|
||||
example.run if Gitlab::Database.mysql?
|
||||
end
|
||||
|
||||
# This makes sure the `ApplicationController#can?` method is stubbed with the
|
||||
# original implementation for all view specs.
|
||||
config.before(:each, type: :view) do
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ module CycleAnalyticsHelpers
|
|||
|
||||
ci_build = create(:ci_build, pipeline: pipeline, status: :success, author: user)
|
||||
|
||||
merge_merge_requests_closing_issue(issue)
|
||||
merge_merge_requests_closing_issue(user, project, issue)
|
||||
ProcessCommitWorker.new.perform(project.id, user.id, mr.commits.last.to_hash)
|
||||
|
||||
ci_build
|
||||
end
|
||||
|
||||
def create_merge_request_closing_issue(issue, message: nil, source_branch: nil, commit_message: 'commit message')
|
||||
def create_merge_request_closing_issue(user, project, issue, message: nil, source_branch: nil, commit_message: 'commit message')
|
||||
if !source_branch || project.repository.commit(source_branch).blank?
|
||||
source_branch = generate(:branch)
|
||||
project.repository.add_branch(user, source_branch, 'master')
|
||||
|
|
@ -64,19 +64,19 @@ module CycleAnalyticsHelpers
|
|||
mr
|
||||
end
|
||||
|
||||
def merge_merge_requests_closing_issue(issue)
|
||||
def merge_merge_requests_closing_issue(user, project, issue)
|
||||
merge_requests = issue.closed_by_merge_requests(user)
|
||||
|
||||
merge_requests.each { |merge_request| MergeRequests::MergeService.new(project, user).execute(merge_request) }
|
||||
end
|
||||
|
||||
def deploy_master(environment: 'production')
|
||||
def deploy_master(user, project, environment: 'production')
|
||||
dummy_job =
|
||||
case environment
|
||||
when 'production'
|
||||
dummy_production_job
|
||||
dummy_production_job(user, project)
|
||||
when 'staging'
|
||||
dummy_staging_job
|
||||
dummy_staging_job(user, project)
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
|
|
@ -84,16 +84,15 @@ module CycleAnalyticsHelpers
|
|||
CreateDeploymentService.new(dummy_job).execute
|
||||
end
|
||||
|
||||
def dummy_production_job
|
||||
@dummy_job ||= new_dummy_job('production')
|
||||
def dummy_production_job(user, project)
|
||||
new_dummy_job(user, project, 'production')
|
||||
end
|
||||
|
||||
def dummy_staging_job
|
||||
@dummy_job ||= new_dummy_job('staging')
|
||||
def dummy_staging_job(user, project)
|
||||
new_dummy_job(user, project, 'staging')
|
||||
end
|
||||
|
||||
def dummy_pipeline
|
||||
@dummy_pipeline ||=
|
||||
def dummy_pipeline(project)
|
||||
Ci::Pipeline.new(
|
||||
sha: project.repository.commit('master').sha,
|
||||
ref: 'master',
|
||||
|
|
@ -102,7 +101,7 @@ module CycleAnalyticsHelpers
|
|||
protected: false)
|
||||
end
|
||||
|
||||
def new_dummy_job(environment)
|
||||
def new_dummy_job(user, project, environment)
|
||||
project.environments.find_or_create_by(name: environment)
|
||||
|
||||
Ci::Build.new(
|
||||
|
|
@ -113,7 +112,7 @@ module CycleAnalyticsHelpers
|
|||
tag: false,
|
||||
name: 'dummy',
|
||||
stage: 'dummy',
|
||||
pipeline: dummy_pipeline,
|
||||
pipeline: dummy_pipeline(project),
|
||||
protected: false)
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue