Memoize pipelines for project download buttons
This adds Project#latest_successful_pipeline_for and Project#latest_successful_pipeline_for_default_branch. The 2nd method memoizes the result (taking nil values into account) to ensure the underlying query isn't executed multiple times when viewing a project's homepage. See https://gitlab.com/gitlab-org/gitlab-ce/issues/36878#note_40073607 for more information.
This commit is contained in:
parent
1140fcce4f
commit
3e999684f9
|
@ -1163,6 +1163,23 @@ class Project < ActiveRecord::Base
|
|||
pipelines.order(id: :desc).find_by(sha: sha, ref: ref)
|
||||
end
|
||||
|
||||
def latest_successful_pipeline_for_default_branch
|
||||
if defined?(@latest_successful_pipeline_for_default_branch)
|
||||
return @latest_successful_pipeline_for_default_branch
|
||||
end
|
||||
|
||||
@latest_successful_pipeline_for_default_branch =
|
||||
pipelines.latest_successful_for(default_branch)
|
||||
end
|
||||
|
||||
def latest_successful_pipeline_for(ref = nil)
|
||||
if ref && ref != default_branch
|
||||
pipelines.latest_successful_for(ref)
|
||||
else
|
||||
latest_successful_pipeline_for_default_branch
|
||||
end
|
||||
end
|
||||
|
||||
def enable_ci
|
||||
project_feature.update_attribute(:builds_access_level, ProjectFeature::ENABLED)
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
- pipeline = local_assigns.fetch(:pipeline) { project.pipelines.latest_successful_for(ref) }
|
||||
- pipeline = local_assigns.fetch(:pipeline) { project.latest_successful_pipeline_for(ref) }
|
||||
|
||||
- if !project.empty_repo? && can?(current_user, :download_code, project)
|
||||
.project-action-button.dropdown.inline>
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Memoize pipelines for project download buttons
|
||||
merge_request:
|
||||
author:
|
||||
type: other
|
|
@ -2682,4 +2682,60 @@ describe Project do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#latest_successful_builds_for' do
|
||||
let(:project) { build(:project) }
|
||||
|
||||
before do
|
||||
allow(project).to receive(:default_branch).and_return('master')
|
||||
end
|
||||
|
||||
context 'without a ref' do
|
||||
it 'returns a pipeline for the default branch' do
|
||||
expect(project)
|
||||
.to receive(:latest_successful_pipeline_for_default_branch)
|
||||
|
||||
project.latest_successful_pipeline_for
|
||||
end
|
||||
end
|
||||
|
||||
context 'with the ref set to the default branch' do
|
||||
it 'returns a pipeline for the default branch' do
|
||||
expect(project)
|
||||
.to receive(:latest_successful_pipeline_for_default_branch)
|
||||
|
||||
project.latest_successful_pipeline_for(project.default_branch)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a ref that is not the default branch' do
|
||||
it 'returns the latest successful pipeline for the given ref' do
|
||||
expect(project.pipelines).to receive(:latest_successful_for).with('foo')
|
||||
|
||||
project.latest_successful_pipeline_for('foo')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#latest_successful_pipeline_for_default_branch' do
|
||||
let(:project) { build(:project) }
|
||||
|
||||
before do
|
||||
allow(project).to receive(:default_branch).and_return('master')
|
||||
end
|
||||
|
||||
it 'memoizes and returns the latest successful pipeline for the default branch' do
|
||||
pipeline = double(:pipeline)
|
||||
|
||||
expect(project.pipelines).to receive(:latest_successful_for)
|
||||
.with(project.default_branch)
|
||||
.and_return(pipeline)
|
||||
.once
|
||||
|
||||
2.times do
|
||||
expect(project.latest_successful_pipeline_for_default_branch)
|
||||
.to eq(pipeline)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue