Commit 8831c2df authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 1c8fa70f
...@@ -20,6 +20,10 @@ module CacheMarkdownField ...@@ -20,6 +20,10 @@ module CacheMarkdownField
false false
end end
def can_cache_field?(field)
true
end
# Returns the default Banzai render context for the cached markdown field. # Returns the default Banzai render context for the cached markdown field.
def banzai_render_context(field) def banzai_render_context(field)
raise ArgumentError.new("Unknown field: #{field.inspect}") unless raise ArgumentError.new("Unknown field: #{field.inspect}") unless
...@@ -38,17 +42,23 @@ module CacheMarkdownField ...@@ -38,17 +42,23 @@ module CacheMarkdownField
context context
end end
# Update every column in a row if any one is invalidated, as we only store def rendered_field_content(markdown_field)
# one version per row return unless can_cache_field?(markdown_field)
def refresh_markdown_cache
options = { skip_project_check: skip_project_check? } options = { skip_project_check: skip_project_check? }
Banzai::Renderer.cacheless_render_field(self, markdown_field, options)
end
# Update every applicable column in a row if any one is invalidated, as we only store
# one version per row
def refresh_markdown_cache
updates = cached_markdown_fields.markdown_fields.map do |markdown_field| updates = cached_markdown_fields.markdown_fields.map do |markdown_field|
[ [
cached_markdown_fields.html_field(markdown_field), cached_markdown_fields.html_field(markdown_field),
Banzai::Renderer.cacheless_render_field(self, markdown_field, options) rendered_field_content(markdown_field)
] ]
end.to_h end.to_h
updates['cached_markdown_version'] = latest_cached_markdown_version updates['cached_markdown_version'] = latest_cached_markdown_version
updates.each { |field, data| write_markdown_field(field, data) } updates.each { |field, data| write_markdown_field(field, data) }
......
...@@ -406,12 +406,16 @@ class Group < Namespace ...@@ -406,12 +406,16 @@ class Group < Namespace
end end
def ci_variables_for(ref, project) def ci_variables_for(ref, project)
cache_key = "ci_variables_for:group:#{self&.id}:project:#{project&.id}:ref:#{ref}"
::Gitlab::SafeRequestStore.fetch(cache_key) do
list_of_ids = [self] + ancestors list_of_ids = [self] + ancestors
variables = Ci::GroupVariable.where(group: list_of_ids) variables = Ci::GroupVariable.where(group: list_of_ids)
variables = variables.unprotected unless project.protected_for?(ref) variables = variables.unprotected unless project.protected_for?(ref)
variables = variables.group_by(&:group_id) variables = variables.group_by(&:group_id)
list_of_ids.reverse.flat_map { |group| variables[group.id] }.compact list_of_ids.reverse.flat_map { |group| variables[group.id] }.compact
end end
end
def group_member(user) def group_member(user)
if group_members.loaded? if group_members.loaded?
......
...@@ -1963,6 +1963,14 @@ class Project < ApplicationRecord ...@@ -1963,6 +1963,14 @@ class Project < ApplicationRecord
end end
def ci_variables_for(ref:, environment: nil) def ci_variables_for(ref:, environment: nil)
cache_key = "ci_variables_for:project:#{self&.id}:ref:#{ref}:environment:#{environment}"
::Gitlab::SafeRequestStore.fetch(cache_key) do
uncached_ci_variables_for(ref: ref, environment: environment)
end
end
def uncached_ci_variables_for(ref:, environment: nil)
result = if protected_for?(ref) result = if protected_for?(ref)
variables variables
else else
......
...@@ -301,6 +301,10 @@ class Snippet < ApplicationRecord ...@@ -301,6 +301,10 @@ class Snippet < ApplicationRecord
repository.update!(shard_name: repository_storage, disk_path: disk_path) repository.update!(shard_name: repository_storage, disk_path: disk_path)
end end
def can_cache_field?(field)
field != :content || MarkupHelper.gitlab_markdown?(file_name)
end
class << self class << self
# Searches for snippets with a matching title or file name. # Searches for snippets with a matching title or file name.
# #
......
---
title: Fix Snippet content incorrectly caching
merge_request: 25985
author:
type: fixed
---
title: Add link to dependency proxy docs on the dependency proxy page
merge_request: 26092
author:
type: changed
---
title: 'Geo: Show secondary-only setting on only on secondaries'
merge_request: 26029
author:
type: fixed
---
title: Memoize loading of CI variables
merge_request: 26147
author:
type: performance
...@@ -9,10 +9,6 @@ and [deployments](../../ci/environments.md) when using [Auto DevOps](../../topic ...@@ -9,10 +9,6 @@ and [deployments](../../ci/environments.md) when using [Auto DevOps](../../topic
You can install them after you You can install them after you
[create a cluster](../project/clusters/add_remove_clusters.md). [create a cluster](../project/clusters/add_remove_clusters.md).
Interested in contributing a new GitLab managed app? Visit the
[development guidelines page](../../development/kubernetes.md#gitlab-managed-apps)
to get started.
## Installing applications ## Installing applications
Applications managed by GitLab will be installed onto the `gitlab-managed-apps` namespace. Applications managed by GitLab will be installed onto the `gitlab-managed-apps` namespace.
...@@ -466,6 +462,12 @@ The chart will deploy 5 Elasticsearch nodes: 2 masters, 2 data and 1 client node ...@@ -466,6 +462,12 @@ The chart will deploy 5 Elasticsearch nodes: 2 masters, 2 data and 1 client node
with resource requests totalling 0.125 CPU and 4.5GB RAM. Each data node requests 1.5GB of memory, with resource requests totalling 0.125 CPU and 4.5GB RAM. Each data node requests 1.5GB of memory,
which makes it incompatible with clusters of `f1-micro` and `g1-small` instance types. which makes it incompatible with clusters of `f1-micro` and `g1-small` instance types.
### Future apps
Interested in contributing a new GitLab managed app? Visit the
[development guidelines page](../../development/kubernetes.md#gitlab-managed-apps)
to get started.
## Install using GitLab CI (alpha) ## Install using GitLab CI (alpha)
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20822) in GitLab 12.6. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20822) in GitLab 12.6.
......
...@@ -82,7 +82,7 @@ module.exports = { ...@@ -82,7 +82,7 @@ module.exports = {
'^.+\\.js$': 'babel-jest', '^.+\\.js$': 'babel-jest',
'^.+\\.vue$': 'vue-jest', '^.+\\.vue$': 'vue-jest',
}, },
transformIgnorePatterns: ['node_modules/(?!(@gitlab/ui)/)'], transformIgnorePatterns: ['node_modules/(?!(@gitlab/ui|bootstrap-vue)/)'],
timers: 'fake', timers: 'fake',
testEnvironment: '<rootDir>/spec/frontend/environment.js', testEnvironment: '<rootDir>/spec/frontend/environment.js',
testEnvironmentOptions: { testEnvironmentOptions: {
......
import $ from 'jquery'; import $ from 'jquery';
import blobBundle from '~/blob_edit/blob_bundle'; import blobBundle from '~/blob_edit/blob_bundle';
jest.mock('~/blob_edit/edit_blob');
describe('BlobBundle', () => { describe('BlobBundle', () => {
beforeEach(() => { beforeEach(() => {
spyOnDependency(blobBundle, 'EditBlob').and.stub();
setFixtures(` setFixtures(`
<div class="js-edit-blob-form" data-blob-filename="blah"> <div class="js-edit-blob-form" data-blob-filename="blah">
<button class="js-commit-button"></button> <button class="js-commit-button"></button>
......
export const defaultProps = {
endpoint: '/foo/bar/issues/1/related_issues',
currentNamespacePath: 'foo',
currentProjectPath: 'bar',
};
export const issuable1 = {
id: 200,
epicIssueId: 1,
confidential: false,
reference: 'foo/bar#123',
displayReference: '#123',
title: 'some title',
path: '/foo/bar/issues/123',
relationPath: '/foo/bar/issues/123/relation',
state: 'opened',
linkType: 'relates_to',
dueDate: '2010-11-22',
weight: 5,
};
export const issuable2 = {
id: 201,
epicIssueId: 2,
confidential: false,
reference: 'foo/bar#124',
displayReference: '#124',
title: 'some other thing',
path: '/foo/bar/issues/124',
relationPath: '/foo/bar/issues/124/relation',
state: 'opened',
linkType: 'blocks',
};
export const issuable3 = {
id: 202,
epicIssueId: 3,
confidential: false,
reference: 'foo/bar#125',
displayReference: '#125',
title: 'some other other thing',
path: '/foo/bar/issues/125',
relationPath: '/foo/bar/issues/125/relation',
state: 'opened',
linkType: 'is_blocked_by',
};
export const issuable4 = {
id: 203,
epicIssueId: 4,
confidential: false,
reference: 'foo/bar#126',
displayReference: '#126',
title: 'some other other other thing',
path: '/foo/bar/issues/126',
relationPath: '/foo/bar/issues/126/relation',
state: 'opened',
};
export const issuable5 = {
id: 204,
epicIssueId: 5,
confidential: false,
reference: 'foo/bar#127',
displayReference: '#127',
title: 'some other other other thing',
path: '/foo/bar/issues/127',
relationPath: '/foo/bar/issues/127/relation',
state: 'opened',
};
export const defaultMilestone = {
id: 1,
state: 'active',
title: 'Milestone title',
start_date: '2018-01-01',
due_date: '2019-12-31',
};
export const defaultAssignees = [
{
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/root`,
status_tooltip_html: null,
path: '/root',
},
{
id: 13,
name: 'Brooks Beatty',
username: 'brynn_champlin',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/brynn_champlin`,
status_tooltip_html: null,
path: '/brynn_champlin',
},
{
id: 6,
name: 'Bryce Turcotte',
username: 'melynda',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/melynda`,
status_tooltip_html: null,
path: '/melynda',
},
{
id: 20,
name: 'Conchita Eichmann',
username: 'juliana_gulgowski',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/juliana_gulgowski`,
status_tooltip_html: null,
path: '/juliana_gulgowski',
},
];
export const defaultProps = { export * from '../../../../frontend/vue_shared/components/issue/related_issuable_mock_data';
endpoint: '/foo/bar/issues/1/related_issues',
currentNamespacePath: 'foo',
currentProjectPath: 'bar',
};
export const issuable1 = {
id: 200,
epicIssueId: 1,
confidential: false,
reference: 'foo/bar#123',
displayReference: '#123',
title: 'some title',
path: '/foo/bar/issues/123',
state: 'opened',
linkType: 'relates_to',
dueDate: '2010-11-22',
weight: 5,
};
export const issuable2 = {
id: 201,
epicIssueId: 2,
confidential: false,
reference: 'foo/bar#124',
displayReference: '#124',
title: 'some other thing',
path: '/foo/bar/issues/124',
state: 'opened',
linkType: 'blocks',
};
export const issuable3 = {
id: 202,
epicIssueId: 3,
confidential: false,
reference: 'foo/bar#125',
displayReference: '#125',
title: 'some other other thing',
path: '/foo/bar/issues/125',
state: 'opened',
linkType: 'is_blocked_by',
};
export const issuable4 = {
id: 203,
epicIssueId: 4,
confidential: false,
reference: 'foo/bar#126',
displayReference: '#126',
title: 'some other other other thing',
path: '/foo/bar/issues/126',
state: 'opened',
};
export const issuable5 = {
id: 204,
epicIssueId: 5,
confidential: false,
reference: 'foo/bar#127',
displayReference: '#127',
title: 'some other other other thing',
path: '/foo/bar/issues/127',
state: 'opened',
};
export const defaultMilestone = {
id: 1,
state: 'active',
title: 'Milestone title',
start_date: '2018-01-01',
due_date: '2019-12-31',
};
export const defaultAssignees = [
{
id: 1,
name: 'Administrator',
username: 'root',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/root`,
status_tooltip_html: null,
path: '/root',
},
{
id: 13,
name: 'Brooks Beatty',
username: 'brynn_champlin',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/brynn_champlin`,
status_tooltip_html: null,
path: '/brynn_champlin',
},
{
id: 6,
name: 'Bryce Turcotte',
username: 'melynda',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/melynda`,
status_tooltip_html: null,
path: '/melynda',
},
{
id: 20,
name: 'Conchita Eichmann',
username: 'juliana_gulgowski',
state: 'active',
avatar_url: `${gl.TEST_HOST}`,
web_url: `${gl.TEST_HOST}/juliana_gulgowski`,
status_tooltip_html: null,
path: '/juliana_gulgowski',
},
];
...@@ -230,6 +230,26 @@ describe CacheMarkdownField, :clean_gitlab_redis_cache do ...@@ -230,6 +230,26 @@ describe CacheMarkdownField, :clean_gitlab_redis_cache do
end end
end end
end end
describe '#rendered_field_content' do
let(:thing) { klass.new(description: markdown, description_html: nil, cached_markdown_version: cache_version) }
context 'when a field can be cached' do
it 'returns the html' do
thing.description = updated_markdown
expect(thing.rendered_field_content(:description)).to eq updated_html
end
end
context 'when a field cannot be cached' do
it 'returns nil' do
allow(thing).to receive(:can_cache_field?).with(:description).and_return false
expect(thing.rendered_field_content(:description)).to eq nil
end
end
end
end end
context 'for Active record classes' do context 'for Active record classes' do
......
...@@ -911,6 +911,16 @@ describe Group do ...@@ -911,6 +911,16 @@ describe Group do
subject { group.ci_variables_for('ref', project) } subject { group.ci_variables_for('ref', project) }
it 'memoizes the result by ref', :request_store do
expect(project).to receive(:protected_for?).with('ref').once.and_return(true)
expect(project).to receive(:protected_for?).with('other').once.and_return(false)
2.times do
expect(group.ci_variables_for('ref', project)).to contain_exactly(ci_variable, protected_variable)
expect(group.ci_variables_for('other', project)).to contain_exactly(ci_variable)
end
end
shared_examples 'ref is protected' do shared_examples 'ref is protected' do
it 'contains all the variables' do it 'contains all the variables' do
is_expected.to contain_exactly(ci_variable, protected_variable) is_expected.to contain_exactly(ci_variable, protected_variable)
......
...@@ -2930,6 +2930,19 @@ describe Project do ...@@ -2930,6 +2930,19 @@ describe Project do
end end
end end
it 'memoizes the result by ref and environment', :request_store do
scoped_variable = create(:ci_variable, value: 'secret', project: project, environment_scope: 'scoped')
expect(project).to receive(:protected_for?).with('ref').once.and_return(true)
expect(project).to receive(:protected_for?).with('other').twice.and_return(false)
2.times do
expect(project.reload.ci_variables_for(ref: 'ref', environment: 'production')).to contain_exactly(ci_variable, protected_variable)
expect(project.reload.ci_variables_for(ref: 'other')).to contain_exactly(ci_variable)
expect(project.reload.ci_variables_for(ref: 'other', environment: 'scoped')).to contain_exactly(ci_variable, scoped_variable)
end
end
context 'when the ref is not protected' do context 'when the ref is not protected' do
before do before do
allow(project).to receive(:protected_for?).with('ref').and_return(false) allow(project).to receive(:protected_for?).with('ref').and_return(false)
......
...@@ -632,4 +632,26 @@ describe Snippet do ...@@ -632,4 +632,26 @@ describe Snippet do
end end
end end
end end
describe '#can_cache_field?' do
using RSpec::Parameterized::TableSyntax
let(:snippet) { create(:snippet, file_name: file_name) }
subject { snippet.can_cache_field?(field) }
where(:field, :file_name, :result) do
:title | nil | true
:title | 'foo.bar' | true
:description | nil | true
:description | 'foo.bar' | true
:content | nil | false
:content | 'bar.foo' | false
:content | 'markdown.md' | true
end
with_them do
it { is_expected.to eq result }
end
end
end end
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -796,15 +796,15 @@ ...@@ -796,15 +796,15 @@
dependencies: dependencies:
vue-eslint-parser "^7.0.0" vue-eslint-parser "^7.0.0"
"@gitlab/svgs@^1.103.0": "@gitlab/svgs@^1.104.0":
version "1.103.0" version "1.104.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.103.0.tgz#fb7136df9f5df3f53685740daf0ebf565b735608" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.104.0.tgz#ebbf99788d74b7224f116f1c0040fa0c90034d99"
integrity sha512-+Bt+a8ln9KSz3QxB2P57ub71/eiEnKXJQSheTagYh2KlT6Glzh7XeLjyc3W6uGWBOONqsp96H/tYEa9dmDnLqQ== integrity sha512-lWg/EzxFdbx4YIdDWB2p5ag6Cna78AYGET8nXQYXYwd21/U3wKXKL7vsGR4kOxe1goA9ZAYG9eY+MK7cf+X2cA==
"@gitlab/ui@^9.17.0": "@gitlab/ui@^9.18.0":
version "9.17.0" version "9.18.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.17.0.tgz#2c2e0412b8293889ab3c2e8f9d7ae1e4b9b508b7" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.18.0.tgz#3f4f09e8b7791d0bd01f90920ac6e4477e977ab9"
integrity sha512-6Ph3eE7ygUc6A72J6+mfce/MQSkyN4Rl2moSIZeMcAnHhIXBn6qoj4+Pq+jTWXYFqy3/ow6Iddle63Flj1dnkA== integrity sha512-GdQFuH4fPU+/wvX+UL5wSYN6VB2EuIXHBjjrdLHeUhEWuXrtrbBBmtoVEfmii0XcX5iUccgw55orz8Dmq3DlGg==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0" "@gitlab/vue-toasted" "^1.3.0"
...@@ -819,6 +819,7 @@ ...@@ -819,6 +819,7 @@
url-search-params-polyfill "^5.0.0" url-search-params-polyfill "^5.0.0"
vue "^2.6.10" vue "^2.6.10"
vue-loader "^15.4.2" vue-loader "^15.4.2"
vue-runtime-helpers "^1.1.2"
"@gitlab/visual-review-tools@1.5.1": "@gitlab/visual-review-tools@1.5.1":
version "1.5.1" version "1.5.1"
...@@ -11849,6 +11850,11 @@ vue-router@^3.0.2: ...@@ -11849,6 +11850,11 @@ vue-router@^3.0.2:
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"
integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg== integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==
vue-runtime-helpers@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vue-runtime-helpers/-/vue-runtime-helpers-1.1.2.tgz#446b7b820888ab0c5264d2c3a32468e72e4100f3"
integrity sha512-pZfGp+PW/IXEOyETE09xQHR1CKkR9HfHZdnMD/FVLUNI+HxYTa82evx5WrF6Kz4s82qtqHvMZ8MZpbk2zT2E1Q==
vue-style-loader@^4.1.0: vue-style-loader@^4.1.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.0.tgz#7588bd778e2c9f8d87bfc3c5a4a039638da7a863" resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.0.tgz#7588bd778e2c9f8d87bfc3c5a4a039638da7a863"
......
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