Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-04-01 18:08:46 +00:00
parent cdd826bc3a
commit 1c7a88b121
116 changed files with 155355 additions and 41734 deletions

View File

@ -49,8 +49,8 @@
- tmp/tests/gitaly/config.toml
- tmp/tests/gitaly/gitaly2.config.toml
- tmp/tests/gitaly/internal/
- tmp/tests/gitaly/internal_gitaly2/
- tmp/tests/gitaly/internal_sockets/
- tmp/tests/gitaly/run/
- tmp/tests/gitaly/run2/
- tmp/tests/gitaly/Makefile
- tmp/tests/gitaly/praefect.config.toml
- tmp/tests/gitaly/ruby/

View File

@ -206,8 +206,8 @@ setup-test-env:
- ${TMP_TEST_FOLDER}/gitaly/config.toml
- ${TMP_TEST_FOLDER}/gitaly/gitaly2.config.toml
- ${TMP_TEST_FOLDER}/gitaly/internal/
- ${TMP_TEST_FOLDER}/gitaly/internal_gitaly2/
- ${TMP_TEST_FOLDER}/gitaly/internal_sockets/
- ${TMP_TEST_FOLDER}/gitaly/run/
- ${TMP_TEST_FOLDER}/gitaly/run2/
- ${TMP_TEST_FOLDER}/gitaly/Makefile
- ${TMP_TEST_FOLDER}/gitaly/praefect.config.toml
- ${TMP_TEST_FOLDER}/gitaly/ruby/

View File

@ -11,6 +11,9 @@ const LINK_TAG_PATTERN = '[{text}](url)';
// followed by one or more whitespace characters
const LIST_LINE_HEAD_PATTERN = /^(?<indent>\s*)(?<leader>((?<isUl>[*+-])|(?<isOl>\d+\.))( \[([xX ])\])?\s)(?<content>.)?/;
// detect a horizontal rule that might be mistaken for a list item (not full pattern for an <hr>)
const HR_PATTERN = /^((\s{0,3}-+\s*-+\s*-+\s*[\s-]*)|(\s{0,3}\*+\s*\*+\s*\*+\s*[\s*]*))$/;
function selectedText(text, textarea) {
return text.substring(textarea.selectionStart, textarea.selectionEnd);
}
@ -381,13 +384,15 @@ function handleContinueList(e, textArea) {
let itemToInsert;
// Behaviors specific to either `ol` or `ul`
if (isOl) {
const nextLine = lineAfter(textArea.value, textArea, false);
const nextLineResult = nextLine.match(LIST_LINE_HEAD_PATTERN);
itemToInsert = continueOlText(result, nextLineResult);
} else {
// isUl
if (currentLine.match(HR_PATTERN)) return;
itemToInsert = `${indent}${leader}`;
}

View File

@ -1,6 +1,5 @@
<script>
import produce from 'immer';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { IssuableType } from '~/issues/constants';
import { assigneesQueries } from '~/sidebar/constants';
@ -17,10 +16,6 @@ export default {
type: String,
required: true,
},
issuableId: {
type: Number,
required: true,
},
queryVariables: {
type: Object,
required: true,
@ -30,6 +25,9 @@ export default {
issuableClass() {
return Object.keys(IssuableType).find((key) => IssuableType[key] === this.issuableType);
},
issuableId() {
return this.issuable?.id;
},
},
apollo: {
issuable: {
@ -48,29 +46,36 @@ export default {
},
variables() {
return {
issuableId: convertToGraphQLId(this.issuableClass, this.issuableId),
issuableId: this.issuableId,
};
},
updateQuery(prev, { subscriptionData }) {
if (prev && subscriptionData?.data?.issuableAssigneesUpdated) {
const data = produce(prev, (draftData) => {
draftData.workspace.issuable.assignees.nodes =
subscriptionData.data.issuableAssigneesUpdated.assignees.nodes;
});
skip() {
return !this.issuableId;
},
updateQuery(
_,
{
subscriptionData: {
data: { issuableAssigneesUpdated },
},
},
) {
if (issuableAssigneesUpdated) {
const {
id,
assignees: { nodes },
} = issuableAssigneesUpdated;
if (this.mediator) {
this.handleFetchResult(data);
this.handleFetchResult(nodes);
}
return data;
this.$emit('assigneesUpdated', { id, assignees: nodes });
}
return prev;
},
},
},
},
methods: {
handleFetchResult(data) {
const { nodes } = data.workspace.issuable.assignees;
handleFetchResult(nodes) {
const assignees = nodes.map((n) => ({
...n,
avatar_url: n.avatarUrl,

View File

@ -232,6 +232,7 @@ export default {
:issuable-type="issuableType"
:issuable-id="issuableId"
:query-variables="queryVariables"
@assigneesUpdated="$emit('assignees-updated', $event)"
/>
<sidebar-editable-item
ref="toggle"

View File

@ -110,22 +110,16 @@ export default {
:class="{
'user-item': !showVerticalList,
'gl-display-inline-block': !showVerticalList,
'gl-display-flex': showVerticalList,
'gl-display-grid gl-align-items-center': showVerticalList,
'gl-mb-3': index !== users.length - 1 && showVerticalList,
}"
class="assignee-attention-grid"
>
<attention-requested-toggle
v-if="showVerticalList"
:user="user"
type="assignee"
class="gl-mr-2"
@toggle-attention-requested="toggleAttentionRequested"
/>
<assignee-avatar-link
:user="user"
:issuable-type="issuableType"
:tooltip-has-name="!showVerticalList"
class="gl-word-break-word"
class="gl-grid-column-2 gl-grid-row-1 gl-word-break-word"
>
<div
v-if="showVerticalList"
@ -136,6 +130,13 @@ export default {
<span>@{{ user.username }}</span>
</div>
</assignee-avatar-link>
<attention-requested-toggle
v-if="showVerticalList"
:user="user"
type="assignee"
class="gl-grid-column-1 gl-grid-row-1 gl-mr-2"
@toggle-attention-requested="toggleAttentionRequested"
/>
</div>
</div>
<div v-if="renderShowMoreSection" class="user-list-more gl-hover-text-blue-800">

View File

@ -95,27 +95,27 @@ export default {
v-for="(user, index) in users"
:key="user.id"
:class="{ 'gl-mb-3': index !== users.length - 1 }"
class="gl-display-grid gl-align-items-center reviewer-attention-grid"
data-testid="reviewer"
class="gl-display-flex"
>
<attention-requested-toggle
v-if="glFeatures.mrAttentionRequests"
:user="user"
type="reviewer"
class="gl-mr-2"
@toggle-attention-requested="toggleAttentionRequested"
/>
<reviewer-avatar-link
:user="user"
:root-path="rootPath"
:issuable-type="issuableType"
class="gl-word-break-word gl-mr-2"
class="gl-grid-column-2 gl-grid-row-1 gl-word-break-word gl-mr-2"
>
<div class="gl-ml-3 gl-line-height-normal gl-display-grid">
<span>{{ user.name }}</span>
<span>@{{ user.username }}</span>
</div>
</reviewer-avatar-link>
<attention-requested-toggle
v-if="glFeatures.mrAttentionRequests"
:user="user"
type="reviewer"
class="gl-grid-column-1 gl-grid-row-1 gl-mr-2"
@toggle-attention-requested="toggleAttentionRequested"
/>
<gl-icon
v-if="user.approved"
v-gl-tooltip.left

View File

@ -0,0 +1,22 @@
#import "~/graphql_shared/fragments/label.fragment.graphql"
subscription issuableLabelsUpdated($issuableId: IssuableID!) {
issuableLabelsUpdated(issuableId: $issuableId) {
... on Issue {
id
labels {
nodes {
...Label
}
}
}
... on MergeRequest {
id
labels {
nodes {
...Label
}
}
}
}
}

View File

@ -1,8 +1,11 @@
<script>
import { debounce } from 'lodash';
import issuableLabelsSubscription from 'ee_else_ce/sidebar/queries/issuable_labels.subscription.graphql';
import { MutationOperationMode, getIdFromGraphQLId } from '~/graphql_shared/utils';
import createFlash from '~/flash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { IssuableType } from '~/issues/constants';
import { __ } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import { issuableLabelsQueries } from '~/sidebar/constants';
@ -21,6 +24,7 @@ export default {
DropdownContents,
SidebarEditableItem,
},
mixins: [glFeatureFlagsMixin()],
inject: {
allowLabelEdit: {
default: false,
@ -106,7 +110,7 @@ export default {
data() {
return {
contentIsOnViewport: true,
issuableLabels: [],
issuable: null,
labelsSelectInProgress: false,
oldIid: null,
sidebarExpandedOnClick: false,
@ -114,14 +118,23 @@ export default {
},
computed: {
isLoading() {
return this.labelsSelectInProgress || this.$apollo.queries.issuableLabels.loading;
return this.labelsSelectInProgress || this.$apollo.queries.issuable.loading;
},
issuableLabelIds() {
return this.issuableLabels.map((label) => label.id);
},
issuableLabels() {
return this.issuable?.labels.nodes || [];
},
issuableId() {
return this.issuable?.id;
},
isRealtimeEnabled() {
return this.glFeatures.realtimeLabels;
},
},
apollo: {
issuableLabels: {
issuable: {
query() {
return issuableLabelsQueries[this.issuableType].issuableQuery;
},
@ -135,11 +148,40 @@ export default {
};
},
update(data) {
return data.workspace?.issuable?.labels.nodes || [];
return data.workspace?.issuable;
},
error() {
createFlash({ message: __('Error fetching labels.') });
},
subscribeToMore: {
document() {
return issuableLabelsSubscription;
},
variables() {
return {
issuableId: this.issuableId,
};
},
skip() {
return !this.issuableId || !this.isDropdownVariantSidebar || !this.isRealtimeEnabled;
},
updateQuery(
_,
{
subscriptionData: {
data: { issuableLabelsUpdated },
},
},
) {
if (issuableLabelsUpdated) {
const {
id,
labels: { nodes },
} = issuableLabelsUpdated;
this.$emit('updateSelectedLabels', { id, labels: nodes });
}
},
},
},
},
watch: {

View File

@ -226,3 +226,23 @@
.edit-link {
margin-right: -$gl-spacing-scale-2;
}
.reviewer-attention-grid,
.assignee-attention-grid {
grid-template-columns: min-content 1fr min-content;
}
/* TODO: These are non-standardized classes, and should be moved into gitlab-ui
Please see: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1780
*/
.gl-grid-column-1 {
grid-column: 1;
}
.gl-grid-row-1 {
grid-row: 1;
}
.gl-grid-column-2 {
grid-column: 2;
}

View File

@ -48,7 +48,7 @@ table {
th {
padding: 10px $gl-padding;
line-height: 20px;
vertical-align: middle;
vertical-align: top;
}
th {

View File

@ -9,6 +9,7 @@ class Groups::BoardsController < Groups::ApplicationController
before_action do
push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml)
push_frontend_feature_flag(:realtime_labels, group, default_enabled: :yaml)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
e.control { }
e.candidate { }

View File

@ -9,6 +9,7 @@ class Projects::BoardsController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
push_frontend_feature_flag(:realtime_labels, project&.group, default_enabled: :yaml)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
e.control { }
e.candidate { }

View File

@ -49,6 +49,7 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag(:confidential_notes, project&.group, default_enabled: :yaml)
push_frontend_feature_flag(:issue_assignees_widget, project, default_enabled: :yaml)
push_frontend_feature_flag(:paginated_issue_discussions, project, default_enabled: :yaml)
push_frontend_feature_flag(:realtime_labels, project, default_enabled: :yaml)
push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
end

View File

@ -43,6 +43,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:markdown_continue_lists, project, default_enabled: :yaml)
push_frontend_feature_flag(:secure_vulnerability_training, project, default_enabled: :yaml)
push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
push_frontend_feature_flag(:realtime_labels, project, default_enabled: :yaml)
# Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, project, default_enabled: :yaml)
push_frontend_feature_flag(:diff_settings_usage_data, default_enabled: :yaml)

View File

@ -541,9 +541,9 @@ class ProjectsController < Projects::ApplicationController
def check_export_rate_limit!
prefixed_action = "project_#{params[:action]}".to_sym
project_scope = params[:action] == 'download_export' ? @project : nil
group_scope = params[:action] == 'download_export' ? @project.namespace : nil
check_rate_limit!(prefixed_action, scope: [current_user, project_scope].compact)
check_rate_limit!(prefixed_action, scope: [current_user, group_scope].compact)
end
def render_edit

View File

@ -12,4 +12,8 @@ module GraphqlTriggers
def self.issuable_title_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableTitleUpdated', { issuable_id: issuable.to_gid }, issuable)
end
def self.issuable_labels_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableLabelsUpdated', { issuable_id: issuable.to_gid }, issuable)
end
end

View File

@ -12,5 +12,8 @@ module Types
field :issuable_title_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the title of an issuable is updated.'
field :issuable_labels_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the labels of an issuable are updated.'
end
end

View File

@ -1444,7 +1444,7 @@ class MergeRequest < ApplicationRecord
# This method is for looking for active environments which created via pipelines for merge requests.
# Since deployments run on a merge request ref (e.g. `refs/merge-requests/:iid/head`),
# we cannot look up environments with source branch name.
def environments
def legacy_environments
return Environment.none unless actual_head_pipeline&.merge_request?
build_for_actual_head_pipeline = Ci::Build.latest.where(pipeline: actual_head_pipeline)
@ -1458,6 +1458,14 @@ class MergeRequest < ApplicationRecord
Environment.where(project: project, name: environments)
end
def environments_in_head_pipeline
if ::Feature.enabled?(:fix_related_environments_for_merge_requests, target_project, default_enabled: :yaml)
actual_head_pipeline&.environments_in_self_and_descendants || Environment.none
else
legacy_environments
end
end
def fetch_ref!
target_project.repository.fetch_source_branch!(source_project.repository, source_branch, ref_path)
end

View File

@ -19,7 +19,7 @@ module Environments
end
def execute_for_merge_request(merge_request)
merge_request.environments.each { |environment| execute(environment) }
merge_request.environments_in_head_pipeline.each { |environment| execute(environment) }
end
private

View File

@ -525,12 +525,23 @@ class IssuableBaseService < ::BaseProjectService
attrs_changed || labels_changed || assignees_changed || reviewers_changed
end
def has_label_changes?(issuable, old_labels)
Set.new(issuable.labels) != Set.new(old_labels)
end
def invalidate_cache_counts(issuable, users: [])
users.each do |user|
user.public_send("invalidate_#{issuable.noteable_target_type_name}_cache_counts") # rubocop:disable GitlabSecurity/PublicSend
end
end
# override if needed
def handle_label_changes(issuable, old_labels)
return unless has_label_changes?(issuable, old_labels)
GraphqlTriggers.issuable_labels_updated(issuable)
end
# override if needed
def handle_changes(issuable, options)
end

View File

@ -63,6 +63,7 @@ module Issues
handle_assignee_changes(issue, old_assignees)
handle_confidential_change(issue)
handle_label_changes(issue, old_labels)
handle_added_labels(issue, old_labels)
handle_milestone_change(issue)
handle_added_mentions(issue, old_mentioned_users)

View File

@ -72,7 +72,7 @@ module MergeRequests
end
def cancel_review_app_jobs!(merge_request)
environments = merge_request.environments.in_review_folder.available
environments = merge_request.environments_in_head_pipeline.in_review_folder.available
environments.each { |environment| environment.cancel_deployment_jobs! }
end

View File

@ -34,6 +34,7 @@ module MergeRequests
handle_target_branch_change(merge_request)
handle_milestone_change(merge_request)
handle_draft_status_change(merge_request, changed_fields)
handle_label_changes(merge_request, old_labels)
track_title_and_desc_edits(changed_fields)
track_discussion_lock_toggle(merge_request, changed_fields)

View File

@ -76,7 +76,7 @@ module ContainerRegistry
end
def below_capacity?
current_capacity <= maximum_capacity
current_capacity < maximum_capacity
end
def waiting_time_passed?
@ -111,11 +111,9 @@ module ContainerRegistry
end
def current_capacity
strong_memoize(:current_capacity) do
ContainerRepository.with_migration_states(
%w[pre_importing pre_import_done importing]
).count
end
ContainerRepository.with_migration_states(
%w[pre_importing pre_import_done importing]
).count
end
def maximum_capacity
@ -145,7 +143,7 @@ module ContainerRegistry
end
def re_enqueue_if_capacity
return unless current_capacity < maximum_capacity
return unless below_capacity?
self.class.perform_async
end

View File

@ -0,0 +1,8 @@
---
name: fix_related_environments_for_merge_requests
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83382
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/356642
milestone: '14.10'
type: development
group: group::release
default_enabled: false

View File

@ -0,0 +1,8 @@
---
name: realtime_labels
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83743
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357370
milestone: '14.10'
type: development
group: group::project management
default_enabled: false

View File

@ -1,8 +1,8 @@
---
name: vsa_consistency_worker
introduced_by_url:
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82591
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355709
milestone: '14.9'
type: development
group: group::optimize
default_enabled: false
default_enabled: true

View File

@ -300,7 +300,7 @@ disable enforcement. For more information, see the documentation on configuring
```toml
listen_addr = '0.0.0.0:8075'
internal_socket_dir = '/var/opt/gitlab/gitaly'
runtime_dir = '/var/opt/gitlab/gitaly'
[logging]
format = 'json'
@ -308,6 +308,9 @@ disable enforcement. For more information, see the documentation on configuring
dir = '/var/log/gitaly'
```
For GitLab 14.9 and earlier, set `internal_socket_dir = '/var/opt/gitlab/gitaly'` instead
of `runtime_dir`.
1. Append the following to `/home/git/gitaly/config.toml` for each respective Gitaly server:
On `gitaly1.internal`:

View File

@ -124,9 +124,9 @@ module Gitlab
config[:storage] = storages
internal_socket_dir = options[:internal_socket_dir] || File.join(gitaly_dir, 'internal_sockets')
FileUtils.mkdir(internal_socket_dir) unless File.exist?(internal_socket_dir)
config[:internal_socket_dir] = internal_socket_dir
runtime_dir = options[:runtime_dir] || File.join(gitaly_dir, 'run')
FileUtils.mkdir(runtime_dir) unless File.exist?(runtime_dir)
config[:runtime_dir] = runtime_dir
config[:'gitaly-ruby'] = { dir: File.join(gitaly_dir, 'ruby') } if gitaly_ruby
config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

45603
locale/ml_IN/gitlab.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1443,14 +1443,15 @@ RSpec.describe ProjectsController do
end
describe '#download_export', :clean_gitlab_redis_rate_limiting do
let(:project) { create(:project, :with_export, service_desk_enabled: false) }
let(:action) { :download_export }
context 'object storage enabled' do
context 'when project export is enabled' do
it 'returns 302' do
it 'returns 200' do
get action, params: { namespace_id: project.namespace, id: project }
expect(response).to have_gitlab_http_status(:found)
expect(response).to have_gitlab_http_status(:ok)
end
end
@ -1490,14 +1491,37 @@ RSpec.describe ProjectsController do
expect(response.body).to eq('This endpoint has been requested too many times. Try again later.')
expect(response).to have_gitlab_http_status(:too_many_requests)
end
end
it 'applies correct scope when throttling' do
context 'applies correct scope when throttling', :clean_gitlab_redis_rate_limiting do
before do
stub_application_setting(project_download_export_limit: 1)
end
it 'applies throttle per namespace' do
expect(Gitlab::ApplicationRateLimiter)
.to receive(:throttled?)
.with(:project_download_export, scope: [user, project])
.with(:project_download_export, scope: [user, project.namespace])
post action, params: { namespace_id: project.namespace, id: project }
end
it 'throttles downloads within same namespaces' do
# simulate prior request to the same namespace, which increments the rate limit counter for that scope
Gitlab::ApplicationRateLimiter.throttled?(:project_download_export, scope: [user, project.namespace])
get action, params: { namespace_id: project.namespace, id: project }
expect(response).to have_gitlab_http_status(:too_many_requests)
end
it 'allows downloads from different namespaces' do
# simulate prior request to a different namespace, which increments the rate limit counter for that scope
Gitlab::ApplicationRateLimiter.throttled?(:project_download_export,
scope: [user, create(:project, :with_export).namespace])
get action, params: { namespace_id: project.namespace, id: project }
expect(response).to have_gitlab_http_status(:ok)
end
end
end
end

Some files were not shown because too many files have changed in this diff Show More