Read about our upcoming Code of Conduct on this issue

Unverified Commit 3e999684 authored by Yorick Peterse's avatar Yorick Peterse
Browse files

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.
parent 12ea678511ea
......@@ -1163,6 +1163,23 @@ def pipeline_for(ref, sha = nil)
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
......
- 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>
......
---
title: Memoize pipelines for project download buttons
merge_request:
author:
type: other
......@@ -2682,4 +2682,60 @@ def enable_lfs
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
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