Commit c95e4fd4 authored by Erick Bajao's avatar Erick Bajao

Use upsert_all to simplify code and less IO

Use Rails 6 upsert_all to reduce queries and simplify code.
parent 028257ef
...@@ -13,25 +13,27 @@ module Ci ...@@ -13,25 +13,27 @@ module Ci
coverage: 12 coverage: 12
}.freeze }.freeze
enum param: REPORT_PARAMS enum param_type: REPORT_PARAMS
def self.store_coverage(pipeline) def self.store_coverage(pipeline)
return unless Feature.enabled?(:ci_daily_code_coverage, default_enabled: true) return unless Feature.enabled?(:ci_daily_code_coverage, default_enabled: true)
ref_path = connection.quote(pipeline.source_ref_path) base_attrs = {
date = connection.quote(pipeline.created_at.to_date) project_id: pipeline.project_id,
param = params[:coverage] ref_path: pipeline.source_ref_path,
param_type: param_types[:coverage],
pipeline.builds.with_coverage.each do |build| date: pipeline.created_at.to_date,
title = connection.quote(build.group_name) last_pipeline_id: pipeline.id
}
connection.execute <<-EOF.strip_heredoc
INSERT INTO #{table_name} (project_id, ref_path, param, title, date, last_pipeline_id, value) data = pipeline.builds.with_coverage.map do |build|
VALUES (#{build.project_id}, #{ref_path}, #{param}, #{title}, #{date}, #{pipeline.id}, #{build.coverage}) base_attrs.merge(
ON CONFLICT (project_id, ref_path, param, title, date) title: build.group_name,
DO UPDATE SET value = #{build.coverage}, last_pipeline_id = #{pipeline.id} WHERE #{table_name}.last_pipeline_id < #{pipeline.id}; value: build.coverage
EOF )
end end
upsert_all(data, unique_by: :index_daily_report_results_unique_columns) if data.any?
end end
end end
end end
...@@ -948,9 +948,9 @@ module Ci ...@@ -948,9 +948,9 @@ module Ci
def source_ref_path def source_ref_path
if branch? || merge_request? if branch? || merge_request?
Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s Gitlab::Git::BRANCH_REF_PREFIX + source_ref.to_s
elsif tag? elsif tag?
Gitlab::Git::TAG_REF_PREFIX + ref.to_s Gitlab::Git::TAG_REF_PREFIX + source_ref.to_s
end end
end end
......
...@@ -9,12 +9,12 @@ class CreateDailyReportResults < ActiveRecord::Migration[6.0] ...@@ -9,12 +9,12 @@ class CreateDailyReportResults < ActiveRecord::Migration[6.0]
t.bigint :project_id, null: false t.bigint :project_id, null: false
t.bigint :last_pipeline_id, null: false t.bigint :last_pipeline_id, null: false
t.float :value, null: false t.float :value, null: false
t.integer :param, limit: 2, null: false t.integer :param_type, limit: 2, null: false
t.string :ref_path, null: false # rubocop:disable Migration/AddLimitToStringColumns t.string :ref_path, null: false # rubocop:disable Migration/AddLimitToStringColumns
t.string :title, null: false # rubocop:disable Migration/AddLimitToStringColumns t.string :title, null: false # rubocop:disable Migration/AddLimitToStringColumns
t.index :last_pipeline_id t.index :last_pipeline_id
t.index [:project_id, :ref_path, :param, :date, :title], name: 'index_daily_report_results_unique_columns', unique: true t.index [:project_id, :ref_path, :param_type, :date, :title], name: 'index_daily_report_results_unique_columns', unique: true
t.foreign_key :projects, on_delete: :cascade t.foreign_key :projects, on_delete: :cascade
t.foreign_key :ci_pipelines, column: :last_pipeline_id, on_delete: :cascade t.foreign_key :ci_pipelines, column: :last_pipeline_id, on_delete: :cascade
end end
......
...@@ -743,11 +743,11 @@ ActiveRecord::Schema.define(version: 2020_03_13_123934) do ...@@ -743,11 +743,11 @@ ActiveRecord::Schema.define(version: 2020_03_13_123934) do
t.bigint "project_id", null: false t.bigint "project_id", null: false
t.bigint "last_pipeline_id", null: false t.bigint "last_pipeline_id", null: false
t.float "value", null: false t.float "value", null: false
t.integer "param", limit: 2, null: false t.integer "param_type", limit: 2, null: false
t.string "ref_path", null: false t.string "ref_path", null: false
t.string "title", null: false t.string "title", null: false
t.index ["last_pipeline_id"], name: "index_ci_daily_report_results_on_last_pipeline_id" t.index ["last_pipeline_id"], name: "index_ci_daily_report_results_on_last_pipeline_id"
t.index ["project_id", "ref_path", "param", "date", "title"], name: "index_daily_report_results_unique_columns", unique: true t.index ["project_id", "ref_path", "param_type", "date", "title"], name: "index_daily_report_results_unique_columns", unique: true
end end
create_table "ci_group_variables", id: :serial, force: :cascade do |t| create_table "ci_group_variables", id: :serial, force: :cascade do |t|
......
...@@ -6,7 +6,7 @@ FactoryBot.define do ...@@ -6,7 +6,7 @@ FactoryBot.define do
date { Time.zone.now.to_date } date { Time.zone.now.to_date }
project project
last_pipeline factory: :ci_pipeline last_pipeline factory: :ci_pipeline
param { Ci::DailyReportResult.params[:coverage] } param_type { Ci::DailyReportResult.param_types[:coverage] }
title { 'rspec' } title { 'rspec' }
value { 77.0 } value { 77.0 }
end end
......
...@@ -17,7 +17,7 @@ describe Ci::DailyReportResult do ...@@ -17,7 +17,7 @@ describe Ci::DailyReportResult do
project_id: pipeline.project.id, project_id: pipeline.project.id,
last_pipeline_id: pipeline.id, last_pipeline_id: pipeline.id,
ref_path: pipeline.source_ref_path, ref_path: pipeline.source_ref_path,
param: 'coverage', param_type: 'coverage',
title: rspec_job.group_name, title: rspec_job.group_name,
value: rspec_job.coverage, value: rspec_job.coverage,
date: pipeline.created_at.to_date date: pipeline.created_at.to_date
...@@ -29,7 +29,7 @@ describe Ci::DailyReportResult do ...@@ -29,7 +29,7 @@ describe Ci::DailyReportResult do
project_id: pipeline.project.id, project_id: pipeline.project.id,
last_pipeline_id: pipeline.id, last_pipeline_id: pipeline.id,
ref_path: pipeline.source_ref_path, ref_path: pipeline.source_ref_path,
param: 'coverage', param_type: 'coverage',
title: karma_job.group_name, title: karma_job.group_name,
value: karma_job.coverage, value: karma_job.coverage,
date: pipeline.created_at.to_date date: pipeline.created_at.to_date
...@@ -96,7 +96,7 @@ describe Ci::DailyReportResult do ...@@ -96,7 +96,7 @@ describe Ci::DailyReportResult do
described_class.store_coverage(new_pipeline) described_class.store_coverage(new_pipeline)
end end
it 'does not update the existing daily code coverage records' do it 'updates the existing daily code coverage records' do
rspec_coverage = Ci::DailyReportResult.find_by(title: 'rspec') rspec_coverage = Ci::DailyReportResult.find_by(title: 'rspec')
karma_coverage = Ci::DailyReportResult.find_by(title: 'karma') karma_coverage = Ci::DailyReportResult.find_by(title: 'karma')
...@@ -104,22 +104,39 @@ describe Ci::DailyReportResult do ...@@ -104,22 +104,39 @@ describe Ci::DailyReportResult do
# This simulates the scenario wherein the success worker # This simulates the scenario wherein the success worker
# of an older pipeline, for some network hiccup, was delayed # of an older pipeline, for some network hiccup, was delayed
# and only got executed right after the newer pipeline's success worker. # and only got executed right after the newer pipeline's success worker.
# In this case, we don't want to bump the coverage value with an older one. # Ideally, we don't want to bump the coverage value with an older one
# but given this can be a rare edge case and can be remedied by re-running
# the pipeline we'll just let it be for now. In return, we are able to use
# Rails 6 shiny new method, upsert_all, and simplify the code a lot.
described_class.store_coverage(pipeline) described_class.store_coverage(pipeline)
rspec_coverage.reload rspec_coverage.reload
karma_coverage.reload karma_coverage.reload
expect(rspec_coverage).to have_attributes( expect(rspec_coverage).to have_attributes(
last_pipeline_id: new_pipeline.id, last_pipeline_id: pipeline.id,
value: new_rspec_job.coverage value: rspec_job.coverage
) )
expect(karma_coverage).to have_attributes( expect(karma_coverage).to have_attributes(
last_pipeline_id: new_pipeline.id, last_pipeline_id: pipeline.id,
value: new_karma_job.coverage value: karma_job.coverage
)
end
end
context 'when pipeline has no builds with coverage' do
let!(:new_pipeline) do
create(
:ci_pipeline,
created_at: '2020-02-06 00:02:20'
) )
end end
let!(:some_job) { create(:ci_build, pipeline: new_pipeline, name: 'foo') }
it 'does nothing' do
expect { described_class.store_coverage(new_pipeline) }.not_to raise_error
end
end end
end end
end end
...@@ -3119,20 +3119,20 @@ describe Ci::Pipeline, :mailer do ...@@ -3119,20 +3119,20 @@ describe Ci::Pipeline, :mailer do
subject { pipeline.source_ref_path } subject { pipeline.source_ref_path }
context 'when pipeline is for a branch' do context 'when pipeline is for a branch' do
it { is_expected.to eq(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.ref.to_s) } it { is_expected.to eq(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.source_ref.to_s) }
end end
context 'when pipeline is for a merge request' do context 'when pipeline is for a merge request' do
let(:merge_request) { create(:merge_request, source_project: project) } let(:merge_request) { create(:merge_request, source_project: project) }
let(:pipeline) { create(:ci_pipeline, project: project, head_pipeline_of: merge_request) } let(:pipeline) { create(:ci_pipeline, project: project, head_pipeline_of: merge_request) }
it { is_expected.to eq(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.ref.to_s) } it { is_expected.to eq(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.source_ref.to_s) }
end end
context 'when pipeline is for a tag' do context 'when pipeline is for a tag' do
let(:pipeline) { create(:ci_pipeline, project: project, tag: true) } let(:pipeline) { create(:ci_pipeline, project: project, tag: true) }
it { is_expected.to eq(Gitlab::Git::TAG_REF_PREFIX + pipeline.ref.to_s) } it { is_expected.to eq(Gitlab::Git::TAG_REF_PREFIX + pipeline.source_ref.to_s) }
end end
end end
end end
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