Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
cc4e1c884c
commit
5d7e5a8902
|
|
@ -43,7 +43,7 @@ prepare-as-if-jh-branch:
|
|||
- git commit -m 'Add JH files' # TODO: Mark which SHA we add
|
||||
# Fetch for the history of the branch so it does not cause the following error:
|
||||
# ! [remote rejected] ref -> ref (shallow update not allowed)
|
||||
- git fetch --unshallow --filter=tree:0 origin "${CI_COMMIT_REF_NAME}"
|
||||
- git fetch --unshallow --filter=tree:0 origin "${CI_COMMIT_SHA}"
|
||||
- git push -f "${SANDBOX_REPOSITORY}" "${AS_IF_JH_BRANCH}"
|
||||
|
||||
start-as-if-jh:
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
|
|||
options[:merge_ref_head_diff]
|
||||
]
|
||||
|
||||
expires_in(1.day) if cache_with_max_age?
|
||||
|
||||
return unless stale?(etag: [cache_context + diff_options_hash.fetch(:paths, []), diffs])
|
||||
|
||||
Gitlab::Metrics.measure(:diffs_unfold) do
|
||||
|
|
@ -238,4 +240,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
|
|||
Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter
|
||||
.track_mr_diffs_single_file_action(merge_request: @merge_request, user: current_user)
|
||||
end
|
||||
|
||||
def cache_with_max_age?
|
||||
@merge_request.diffs_batch_cache_with_max_age? &&
|
||||
params[:ck].present? &&
|
||||
render_merge_ref_head_diff?
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -414,6 +414,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
@update_current_user_path = expose_path(api_v4_user_preferences_path)
|
||||
@endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request)
|
||||
@endpoint_diff_batch_url = endpoint_diff_batch_url(@project, @merge_request)
|
||||
@diffs_batch_cache_key = @merge_request.merge_head_diff&.id if merge_request.diffs_batch_cache_with_max_age?
|
||||
|
||||
set_pipeline_variables
|
||||
|
||||
|
|
@ -571,6 +572,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
def endpoint_diff_batch_url(project, merge_request)
|
||||
per_page = current_user&.view_diffs_file_by_file ? '1' : '5'
|
||||
params = request.query_parameters.merge(view: 'inline', diff_head: true, w: show_whitespace, page: '0', per_page: per_page)
|
||||
params[:ck] = merge_request.merge_head_diff&.id if merge_request.diffs_batch_cache_with_max_age?
|
||||
|
||||
diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ class Projects::ReleasesController < Projects::ApplicationController
|
|||
before_action :authorize_create_release!, only: :new
|
||||
before_action :validate_suffix_path, :fetch_latest_tag, only: :latest_permalink
|
||||
|
||||
prepend_before_action(only: [:downloads]) do
|
||||
authenticate_sessionless_user!(:download) if Feature.enabled?(:allow_release_as_web_access_format)
|
||||
end
|
||||
|
||||
feature_category :release_orchestration
|
||||
urgency :low
|
||||
|
||||
|
|
|
|||
|
|
@ -2019,6 +2019,10 @@ class MergeRequest < ApplicationRecord
|
|||
Feature.enabled?(:hide_merge_requests_from_banned_users) && author&.banned?
|
||||
end
|
||||
|
||||
def diffs_batch_cache_with_max_age?
|
||||
Feature.enabled?(:diffs_batch_cache_with_max_age, project)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :skip_fetch_ref
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
class PlanLimits < ApplicationRecord
|
||||
include IgnorableColumns
|
||||
ignore_column :ci_max_artifact_size_running_container_scanning, remove_with: '14.3', remove_after: '2021-08-22'
|
||||
ignore_column :web_hook_calls, remove_with: '15.10', remove_after: '2022-02-22'
|
||||
ignore_column :web_hook_calls_high, remove_with: '15.10', remove_after: '2022-02-22'
|
||||
|
||||
LimitUndefinedError = Class.new(StandardError)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Tracks egress of various services per project
|
||||
# This class ensures that we keep 1 record per project per month.
|
||||
module Projects
|
||||
class DataTransfer < ApplicationRecord
|
||||
self.table_name = 'project_data_transfers'
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :namespace
|
||||
|
||||
scope :current_month, -> { where(date: beginning_of_month) }
|
||||
|
||||
def self.beginning_of_month(time = Time.current)
|
||||
time.utc.beginning_of_month
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -15,17 +15,20 @@
|
|||
= stylesheet_link_tag 'notify'
|
||||
= yield :head
|
||||
%body
|
||||
= html_header_message
|
||||
.content
|
||||
= yield
|
||||
.footer{ style: "margin-top: 10px;" }
|
||||
%p
|
||||
—
|
||||
%br
|
||||
= link_to "Unsubscribe", @unsubscribe_url
|
||||
%p
|
||||
—
|
||||
%br
|
||||
= link_to "Unsubscribe", @unsubscribe_url
|
||||
|
||||
-# EE-specific start
|
||||
- if Gitlab::CurrentSettings.email_additional_text.present?
|
||||
%br
|
||||
%br
|
||||
= Gitlab::Utils.nlbr(Gitlab::CurrentSettings.email_additional_text)
|
||||
-# EE-specific end
|
||||
-# EE-specific start
|
||||
- if Gitlab::CurrentSettings.email_additional_text.present?
|
||||
%br
|
||||
%br
|
||||
= Gitlab::Utils.nlbr(Gitlab::CurrentSettings.email_additional_text)
|
||||
-# EE-specific end
|
||||
|
||||
= html_footer_message
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<%= text_header_message %>
|
||||
|
||||
<%= yield -%>
|
||||
|
||||
<%= @unsubscribe_url %>
|
||||
<%# EE-specific start %><%= render_if_exists 'layouts/mailer/additional_text' %><%# EE-specific end %>
|
||||
<%= text_footer_message -%>
|
||||
|
|
@ -3,4 +3,3 @@
|
|||
<%= _("Author: %{author_name}") % { author_name: sanitize_name(@note.author_name) } %>
|
||||
|
||||
<%= @note.note %>
|
||||
<%# EE-specific start %><%= render_if_exists 'layouts/mailer/additional_text'%><%# EE-specific end %>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
<%= _("Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can.") % { issue_iid: @issue.iid } %>
|
||||
|
||||
<%= _("To unsubscribe from this issue, please paste the following link into your browser:") %>
|
||||
|
||||
<%= @unsubscribe_url %>
|
||||
<%# EE-specific start %><%= render_if_exists 'layouts/mailer/additional_text' %><%# EE-specific end %>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
- if mr_action == 'diffs'
|
||||
- add_page_startup_api_call @endpoint_diff_batch_url
|
||||
|
||||
.merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version } }
|
||||
.merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version, diffs_batch_cache_key: @diffs_batch_cache_key } }
|
||||
- if moved_mr_sidebar_enabled?
|
||||
#js-merge-sticky-header{ data: { data: sticky_header_data.to_json } }
|
||||
= render "projects/merge_requests/mr_title"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: allow_release_as_web_access_format
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109217
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/388471
|
||||
milestone: '15.8'
|
||||
type: development
|
||||
group: group::release
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: diffs_batch_cache_with_max_age
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109451
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/388778
|
||||
milestone: '15.9'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
table_name: project_data_transfers
|
||||
classes:
|
||||
- Projects::DataTransfer
|
||||
feature_categories:
|
||||
- source_code_management
|
||||
description: Data transfer metrics per project
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/107970
|
||||
milestone: '15.9'
|
||||
gitlab_schema: gitlab_main
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateProjectDataTransfer < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
create_table :project_data_transfers do |t|
|
||||
t.references :project, index: false, null: false
|
||||
t.references :namespace, index: true, null: false
|
||||
t.bigint :repository_egress, null: false, default: 0
|
||||
t.bigint :artifacts_egress, null: false, default: 0
|
||||
t.bigint :packages_egress, null: false, default: 0
|
||||
t.bigint :registry_egress, null: false, default: 0
|
||||
t.date :date, null: false
|
||||
t.datetime_with_timezone :created_at, null: false
|
||||
|
||||
t.index [:project_id, :namespace_id, :date], unique: true,
|
||||
name: 'index_project_data_transfers_on_project_and_namespace_and_date'
|
||||
end
|
||||
end
|
||||
|
||||
add_check_constraint :project_data_transfers,
|
||||
"(date = date_trunc('month', date))", 'project_data_transfers_project_year_month_constraint'
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
drop_table :project_data_transfers
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ReAddWebHookCallsColumn < Gitlab::Database::Migration[2.1]
|
||||
enable_lock_retries!
|
||||
|
||||
def change
|
||||
add_column :plan_limits, :web_hook_calls, :integer, default: 0, null: false, if_not_exists: true
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DropSyncTriggersFromWebHookCallsPlanLimits < Gitlab::Database::Migration[2.1]
|
||||
enable_lock_retries!
|
||||
|
||||
def up
|
||||
drop_trigger('trigger_c0776354152a', 'plan_limits')
|
||||
drop_trigger('trigger_d0c336b01d00', 'plan_limits')
|
||||
drop_trigger('trigger_e19c4cf656dc', 'plan_limits')
|
||||
end
|
||||
|
||||
def down
|
||||
# noop
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SyncPlanLimitsWebHookCallsColumns < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
def up
|
||||
execute('UPDATE plan_limits SET web_hook_calls=web_hook_calls_high')
|
||||
end
|
||||
|
||||
def down
|
||||
# noop
|
||||
end
|
||||
end
|
||||
|
|
@ -4,7 +4,7 @@ class CleanupWebHookCallsColumnRename < Gitlab::Database::Migration[2.1]
|
|||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
cleanup_concurrent_column_rename :plan_limits, :web_hook_calls, :web_hook_calls_high
|
||||
# noop, related incident: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/8264
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
ee7f3ba064eaaf4a1bf92e5c0a2ed32e5d294ddd6f1fdd8e6eed54c8b83c2af5
|
||||
|
|
@ -0,0 +1 @@
|
|||
036fd539aa235ccaba493bfa7294f28cf71cfd73a1e069de2977b9313fd0b655
|
||||
|
|
@ -0,0 +1 @@
|
|||
61838f8cfb759c53aa8ccc47620cd4d6595a72293172c7e3ac77b2e79e422200
|
||||
|
|
@ -0,0 +1 @@
|
|||
c0f53f169d2525ebd5e374c102fe73521d344df078c37384675995ac97fbed9a
|
||||
|
|
@ -19656,6 +19656,7 @@ CREATE TABLE plan_limits (
|
|||
notification_limit integer DEFAULT 0 NOT NULL,
|
||||
dashboard_limit_enabled_at timestamp with time zone,
|
||||
web_hook_calls_high integer DEFAULT 0,
|
||||
web_hook_calls integer DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT check_0fa68f370e CHECK ((web_hook_calls_high IS NOT NULL))
|
||||
);
|
||||
|
||||
|
|
@ -20226,6 +20227,28 @@ CREATE SEQUENCE project_daily_statistics_id_seq
|
|||
|
||||
ALTER SEQUENCE project_daily_statistics_id_seq OWNED BY project_daily_statistics.id;
|
||||
|
||||
CREATE TABLE project_data_transfers (
|
||||
id bigint NOT NULL,
|
||||
project_id bigint NOT NULL,
|
||||
namespace_id bigint NOT NULL,
|
||||
repository_egress bigint DEFAULT 0 NOT NULL,
|
||||
artifacts_egress bigint DEFAULT 0 NOT NULL,
|
||||
packages_egress bigint DEFAULT 0 NOT NULL,
|
||||
registry_egress bigint DEFAULT 0 NOT NULL,
|
||||
date date NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
CONSTRAINT project_data_transfers_project_year_month_constraint CHECK ((date = date_trunc('month'::text, (date)::timestamp with time zone)))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE project_data_transfers_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE project_data_transfers_id_seq OWNED BY project_data_transfers.id;
|
||||
|
||||
CREATE TABLE project_deploy_tokens (
|
||||
id integer NOT NULL,
|
||||
project_id integer NOT NULL,
|
||||
|
|
@ -24583,6 +24606,8 @@ ALTER TABLE ONLY project_custom_attributes ALTER COLUMN id SET DEFAULT nextval('
|
|||
|
||||
ALTER TABLE ONLY project_daily_statistics ALTER COLUMN id SET DEFAULT nextval('project_daily_statistics_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY project_data_transfers ALTER COLUMN id SET DEFAULT nextval('project_data_transfers_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY project_deploy_tokens ALTER COLUMN id SET DEFAULT nextval('project_deploy_tokens_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY project_export_jobs ALTER COLUMN id SET DEFAULT nextval('project_export_jobs_id_seq'::regclass);
|
||||
|
|
@ -26821,6 +26846,9 @@ ALTER TABLE ONLY project_custom_attributes
|
|||
ALTER TABLE ONLY project_daily_statistics
|
||||
ADD CONSTRAINT project_daily_statistics_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY project_data_transfers
|
||||
ADD CONSTRAINT project_data_transfers_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY project_deploy_tokens
|
||||
ADD CONSTRAINT project_deploy_tokens_pkey PRIMARY KEY (id);
|
||||
|
||||
|
|
@ -30717,6 +30745,10 @@ CREATE UNIQUE INDEX index_project_custom_attributes_on_project_id_and_key ON pro
|
|||
|
||||
CREATE UNIQUE INDEX index_project_daily_statistics_on_project_id_and_date ON project_daily_statistics USING btree (project_id, date DESC);
|
||||
|
||||
CREATE INDEX index_project_data_transfers_on_namespace_id ON project_data_transfers USING btree (namespace_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_project_data_transfers_on_project_and_namespace_and_date ON project_data_transfers USING btree (project_id, namespace_id, date);
|
||||
|
||||
CREATE INDEX index_project_deploy_tokens_on_deploy_token_id ON project_deploy_tokens USING btree (deploy_token_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_project_deploy_tokens_on_project_id_and_deploy_token_id ON project_deploy_tokens USING btree (project_id, deploy_token_id);
|
||||
|
|
|
|||
|
|
@ -385,9 +385,9 @@ The Ruby gem which performs the check is hard coded with `pool.ntp.org` as its r
|
|||
|
||||
This issue occurs when the hostname `pool.ntp.org` resolves to a server which does not provide a time service.
|
||||
|
||||
There is [an issue open](https://gitlab.com/gitlab-org/gitlab/-/issues/381422) for this dependency on `pool.ntp.org`.
|
||||
In this case, in GitLab 15.7 and newer, [specify a custom NTP server using environment variables](#health-check-rake-task).
|
||||
|
||||
To workaround this, do one of the following:
|
||||
In GitLab 15.6 and older, use one of the following workarounds:
|
||||
|
||||
- Add entries in `/etc/hosts` for `pool.ntp.org` to direct the request to valid local time servers.
|
||||
This fixes the long timeout and the timeout error.
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ To set this limit for a self-managed installation, run the following in the
|
|||
# If limits don't exist for the default plan, you can create one with:
|
||||
# Plan.default.create_limits!
|
||||
|
||||
Plan.default.actual_limits.update!(web_hook_calls_high: 10)
|
||||
Plan.default.actual_limits.update!(web_hook_calls: 10)
|
||||
```
|
||||
|
||||
Set the limit to `0` to disable it.
|
||||
|
|
@ -1077,6 +1077,16 @@ If a branch is merged while open merge requests still point to it, GitLab can
|
|||
retarget merge requests pointing to the now-merged branch. To learn more, read
|
||||
[Update merge requests when target branch merges](../user/project/merge_requests/index.md#update-merge-requests-when-target-branch-merges).
|
||||
|
||||
## Maximum number of assignees and reviewers
|
||||
|
||||
> - Maximum assignees [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368936) in GitLab 15.6.
|
||||
> - Maximum reviewers [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366485) in GitLab 15.9.
|
||||
|
||||
Issues and merge requests enforce these maximums:
|
||||
|
||||
- Maximum assignees: 200
|
||||
- Maximum reviewers: 200
|
||||
|
||||
## CDN-based limits on GitLab.com
|
||||
|
||||
In addition to application-based limits, GitLab.com is configured to use Cloudflare's standard DDoS protection and Spectrum to protect Git over SSH. Cloudflare terminates client TLS connections but is not application aware and cannot be used for limits tied to users or groups. Cloudflare page rules and rate limits are configured with Terraform. These configurations are [not public](https://about.gitlab.com/handbook/communication/#not-public) because they include security and abuse implementations that detect malicious activities and making them public would undermine those operations.
|
||||
|
|
|
|||
|
|
@ -331,11 +331,15 @@ for `shared_buffers` is quite high, and we are
|
|||
|
||||
GitLab.com uses the default of 60 seconds for [Puma request timeouts](../../administration/operations/puma.md#change-the-worker-timeout).
|
||||
|
||||
## Merge request reviewer maximum
|
||||
## Maximum number of reviewers and assignees
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91406) in GitLab 15.3.
|
||||
> - Maximum assignees [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368936) in GitLab 15.6.
|
||||
> - Maximum reviewers [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366485) in GitLab 15.9.
|
||||
|
||||
A maximum of 100 reviewers can be assigned to a merge request.
|
||||
Merge requests enforce these maximums:
|
||||
|
||||
- Maximum assignees: 200
|
||||
- Maximum reviewers: 200
|
||||
|
||||
## GitLab.com-specific rate limits
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ module Gitlab
|
|||
group_import: { threshold: -> { application_settings.group_import_limit }, interval: 1.minute },
|
||||
group_testing_hook: { threshold: 5, interval: 1.minute },
|
||||
profile_add_new_email: { threshold: 5, interval: 1.minute },
|
||||
web_hook_calls_high: { interval: 1.minute },
|
||||
web_hook_calls: { interval: 1.minute },
|
||||
web_hook_calls_mid: { interval: 1.minute },
|
||||
web_hook_calls_low: { interval: 1.minute },
|
||||
users_get_by_id: { threshold: -> { application_settings.users_get_by_id_limit }, interval: 10.minutes },
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ module Gitlab
|
|||
# It is also used by GraphQL/API requests.
|
||||
# And to allow accessing /archive programatically as it was a big pain point
|
||||
# for users https://gitlab.com/gitlab-org/gitlab/-/issues/28978.
|
||||
# Used for release downloading as well
|
||||
def find_user_from_web_access_token(request_format, scopes: [:api])
|
||||
return unless access_token && valid_web_access_format?(request_format)
|
||||
|
||||
|
|
@ -301,6 +302,8 @@ module Gitlab
|
|||
api_request?
|
||||
when :archive
|
||||
archive_request?
|
||||
when :download
|
||||
download_request?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -352,6 +355,10 @@ module Gitlab
|
|||
current_request.path.include?('/-/archive/')
|
||||
end
|
||||
|
||||
def download_request?
|
||||
current_request.path.include?('/downloads/')
|
||||
end
|
||||
|
||||
def blob_request?
|
||||
current_request.path.include?('/raw/')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module Gitlab
|
|||
class RateLimiter
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
LIMIT_NAME = :web_hook_calls_high
|
||||
LIMIT_NAME = :web_hook_calls
|
||||
NO_LIMIT = 0
|
||||
# SystemHooks (instance admin hooks) and ServiceHooks (integration hooks)
|
||||
# are not rate-limited.
|
||||
|
|
|
|||
|
|
@ -610,5 +610,39 @@ RSpec.describe Projects::MergeRequests::DiffsController do
|
|||
go
|
||||
end
|
||||
end
|
||||
|
||||
context 'when ck param is present' do
|
||||
let(:cache_key) { merge_request.merge_head_diff.id }
|
||||
|
||||
before do
|
||||
create(:merge_request_diff, :merge_head, merge_request: merge_request)
|
||||
end
|
||||
|
||||
it 'sets Cache-Control with max-age' do
|
||||
go(ck: cache_key, diff_head: true)
|
||||
|
||||
expect(response.headers['Cache-Control']).to eq('max-age=86400, private')
|
||||
end
|
||||
|
||||
context 'when diffs_batch_cache_with_max_age feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(diffs_batch_cache_with_max_age: false)
|
||||
end
|
||||
|
||||
it 'does not set Cache-Control with max-age' do
|
||||
go(ck: cache_key, diff_head: true)
|
||||
|
||||
expect(response.headers['Cache-Control']).not_to eq('max-age=86400, private')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not rendering merge head diff' do
|
||||
it 'does not set Cache-Control with max-age' do
|
||||
go(ck: cache_key, diff_head: false)
|
||||
|
||||
expect(response.headers['Cache-Control']).not_to eq('max-age=86400, private')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -82,6 +82,61 @@ RSpec.describe Projects::MergeRequestsController, feature_category: :code_review
|
|||
w: '0'))
|
||||
end
|
||||
|
||||
context 'when merge_head diff is present' do
|
||||
before do
|
||||
create(:merge_request_diff, :merge_head, merge_request: merge_request)
|
||||
end
|
||||
|
||||
it 'sets the endpoint_diff_batch_url with ck' do
|
||||
go
|
||||
|
||||
expect(assigns["endpoint_diff_batch_url"]).to eq(
|
||||
diffs_batch_project_json_merge_request_path(
|
||||
project,
|
||||
merge_request,
|
||||
'json',
|
||||
diff_head: true,
|
||||
view: 'inline',
|
||||
w: '0',
|
||||
page: '0',
|
||||
per_page: '5',
|
||||
ck: merge_request.merge_head_diff.id))
|
||||
end
|
||||
|
||||
it 'sets diffs_batch_cache_key' do
|
||||
go
|
||||
|
||||
expect(assigns['diffs_batch_cache_key']).to eq(merge_request.merge_head_diff.id)
|
||||
end
|
||||
|
||||
context 'when diffs_batch_cache_with_max_age feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(diffs_batch_cache_with_max_age: false)
|
||||
end
|
||||
|
||||
it 'sets the endpoint_diff_batch_url without ck param' do
|
||||
go
|
||||
|
||||
expect(assigns['endpoint_diff_batch_url']).to eq(
|
||||
diffs_batch_project_json_merge_request_path(
|
||||
project,
|
||||
merge_request,
|
||||
'json',
|
||||
diff_head: true,
|
||||
view: 'inline',
|
||||
w: '0',
|
||||
page: '0',
|
||||
per_page: '5'))
|
||||
end
|
||||
|
||||
it 'does not set diffs_batch_cache_key' do
|
||||
go
|
||||
|
||||
expect(assigns['diffs_batch_cache_key']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when diff files were cleaned' do
|
||||
render_views
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ RSpec.describe 'Database schema', feature_category: :database do
|
|||
oauth_applications: %w[owner_id],
|
||||
product_analytics_events_experimental: %w[event_id txn_id user_id],
|
||||
project_build_artifacts_size_refreshes: %w[last_job_artifact_id],
|
||||
project_data_transfers: %w[project_id namespace_id],
|
||||
project_error_tracking_settings: %w[sentry_project_id],
|
||||
project_group_links: %w[group_id],
|
||||
project_statistics: %w[namespace_id],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :project_data_transfer, class: 'Projects::DataTransfer' do
|
||||
project factory: :project
|
||||
namespace { project.root_namespace }
|
||||
date { Time.current.utc.beginning_of_month }
|
||||
end
|
||||
end
|
||||
|
|
@ -470,7 +470,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
expect { find_user_from_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
|
||||
end
|
||||
|
||||
context 'no feed, API or archive requests' do
|
||||
context 'no feed, API, archive or download requests' do
|
||||
it 'returns nil if the request is not RSS' do
|
||||
expect(find_user_from_web_access_token(:rss)).to be_nil
|
||||
end
|
||||
|
|
@ -486,6 +486,10 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
it 'returns nil if the request is not ARCHIVE' do
|
||||
expect(find_user_from_web_access_token(:archive)).to be_nil
|
||||
end
|
||||
|
||||
it 'returns nil if the request is not DOWNLOAD' do
|
||||
expect(find_user_from_web_access_token(:download)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the user for RSS requests' do
|
||||
|
|
@ -506,6 +510,12 @@ RSpec.describe Gitlab::Auth::AuthFinders do
|
|||
expect(find_user_from_web_access_token(:archive)).to eq(user)
|
||||
end
|
||||
|
||||
it 'returns the user for DOWNLOAD requests' do
|
||||
set_header('SCRIPT_NAME', '/-/1.0.0/downloads/main.zip')
|
||||
|
||||
expect(find_user_from_web_access_token(:download)).to eq(user)
|
||||
end
|
||||
|
||||
context 'for API requests' do
|
||||
it 'returns the user' do
|
||||
set_header('SCRIPT_NAME', '/api/endpoint')
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting
|
|||
|
||||
context 'when there is a plan limit' do
|
||||
before_all do
|
||||
create(:plan_limits, plan: plan, web_hook_calls_high: limit)
|
||||
create(:plan_limits, plan: plan, web_hook_calls: limit)
|
||||
end
|
||||
|
||||
where(:hook, :limitless_hook_type) do
|
||||
|
|
@ -65,7 +65,7 @@ RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting
|
|||
|
||||
describe 'rate limit scope' do
|
||||
it 'rate limits all hooks from the same namespace', :freeze_time do
|
||||
create(:plan_limits, plan: plan, web_hook_calls_high: limit)
|
||||
create(:plan_limits, plan: plan, web_hook_calls: limit)
|
||||
project_hook_in_different_namespace = create(:project_hook)
|
||||
project_hook_in_same_namespace = create(:project_hook,
|
||||
project: create(:project, namespace: project_hook.project.namespace)
|
||||
|
|
@ -92,7 +92,7 @@ RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting
|
|||
|
||||
context 'when there is a plan limit' do
|
||||
before_all do
|
||||
create(:plan_limits, plan: plan, web_hook_calls_high: limit)
|
||||
create(:plan_limits, plan: plan, web_hook_calls: limit)
|
||||
end
|
||||
|
||||
context 'when hook is not rate-limited' do
|
||||
|
|
|
|||
|
|
@ -1409,6 +1409,8 @@ RSpec.describe Notify do
|
|||
subject { described_class.service_desk_thank_you_email(issue.id) }
|
||||
|
||||
it_behaves_like 'an unsubscribeable thread'
|
||||
it_behaves_like 'appearance header and footer enabled'
|
||||
it_behaves_like 'appearance header and footer not enabled'
|
||||
|
||||
it 'has the correct recipient' do
|
||||
is_expected.to deliver_to('service.desk@example.com')
|
||||
|
|
@ -1450,6 +1452,8 @@ RSpec.describe Notify do
|
|||
subject { described_class.service_desk_new_note_email(issue.id, first_note.id, 'service.desk@example.com') }
|
||||
|
||||
it_behaves_like 'an unsubscribeable thread'
|
||||
it_behaves_like 'appearance header and footer enabled'
|
||||
it_behaves_like 'appearance header and footer not enabled'
|
||||
|
||||
it 'has the correct recipient' do
|
||||
is_expected.to deliver_to('service.desk@example.com')
|
||||
|
|
|
|||
|
|
@ -5535,4 +5535,24 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#diffs_batch_cache_with_max_age?' do
|
||||
let(:merge_request) { build_stubbed(:merge_request) }
|
||||
|
||||
subject(:diffs_batch_cache_with_max_age?) { merge_request.diffs_batch_cache_with_max_age? }
|
||||
|
||||
it 'returns true' do
|
||||
expect(diffs_batch_cache_with_max_age?).to be_truthy
|
||||
end
|
||||
|
||||
context 'when diffs_batch_cache_with_max_age is disabled' do
|
||||
before do
|
||||
stub_feature_flags(diffs_batch_cache_with_max_age: false)
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
expect(diffs_batch_cache_with_max_age?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ RSpec.describe PlanLimits do
|
|||
ci_active_jobs
|
||||
storage_size_limit
|
||||
daily_invites
|
||||
web_hook_calls_high
|
||||
web_hook_calls
|
||||
web_hook_calls_mid
|
||||
web_hook_calls_low
|
||||
ci_daily_pipeline_schedule_triggers
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::DataTransfer, feature_category: :source_code_management do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
it { expect(subject).to be_valid }
|
||||
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to belong_to(:namespace) }
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
describe '.current_month' do
|
||||
subject { described_class.current_month }
|
||||
|
||||
it 'returns data transfer for the current month' do
|
||||
travel_to(Time.utc(2022, 5, 2)) do
|
||||
_past_month = create(:project_data_transfer, project: project, date: '2022-04-01')
|
||||
current_month = create(:project_data_transfer, project: project, date: '2022-05-01')
|
||||
|
||||
is_expected.to match_array([current_month])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.beginning_of_month' do
|
||||
subject { described_class.beginning_of_month(time) }
|
||||
|
||||
let(:time) { Time.utc(2022, 5, 2) }
|
||||
|
||||
it { is_expected.to eq(Time.utc(2022, 5, 1)) }
|
||||
end
|
||||
|
||||
describe 'unique index' do
|
||||
before do
|
||||
create(:project_data_transfer, project: project, date: '2022-05-01')
|
||||
end
|
||||
|
||||
it 'raises unique index violation' do
|
||||
expect { create(:project_data_transfer, project: project, namespace: project.root_namespace, date: '2022-05-01') }
|
||||
.to raise_error(ActiveRecord::RecordNotUnique)
|
||||
end
|
||||
|
||||
context 'when project was moved from one namespace to another' do
|
||||
it 'creates a new record' do
|
||||
expect { create(:project_data_transfer, project: project, namespace: create(:namespace), date: '2022-05-01') }
|
||||
.to change { described_class.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a different project is created' do
|
||||
it 'creates a new record' do
|
||||
expect { create(:project_data_transfer, project: build(:project), date: '2022-05-01') }
|
||||
.to change { described_class.count }.by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -8,17 +8,20 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
|
|||
|
||||
before do
|
||||
project.add_developer(user)
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
# Added as a request spec because of https://gitlab.com/gitlab-org/gitlab/-/issues/232386
|
||||
describe 'GET #downloads' do
|
||||
context 'filepath redirection' do
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
|
||||
let!(:link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') }
|
||||
let_it_be(:url) { "#{project_releases_path(project)}/#{release.tag}/downloads/bin/darwin-amd64" }
|
||||
let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
|
||||
let!(:link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') }
|
||||
let_it_be(:url) { "#{project_releases_path(project)}/#{release.tag}/downloads/bin/darwin-amd64" }
|
||||
|
||||
let(:subject) { get url }
|
||||
let(:subject) { get url }
|
||||
|
||||
context 'filepath redirection' do
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
context 'valid filepath' do
|
||||
let(:filepath) { '/bin/darwin-amd64' }
|
||||
|
|
@ -47,14 +50,45 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
|
|||
end
|
||||
end
|
||||
|
||||
context 'invalid filepath' do
|
||||
let(:invalid_filepath) { 'bin/darwin-amd64' }
|
||||
context 'sessionless download authentication' do
|
||||
let(:personal_access_token) { create(:personal_access_token, user: user) }
|
||||
let(:filepath) { '/bin/darwin-amd64' }
|
||||
|
||||
let(:subject) { create(:release_link, name: 'linux-amd64 binaries', filepath: invalid_filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') }
|
||||
subject { get url, params: { private_token: personal_access_token.token } }
|
||||
|
||||
it 'cannot create an invalid filepath' do
|
||||
expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
|
||||
context 'when allow_release_as_web_access_format FF is disabled' do
|
||||
before do
|
||||
stub_feature_flags(allow_release_as_web_access_format: false)
|
||||
end
|
||||
|
||||
it 'will not allow sessionless authentication' do
|
||||
expect_next_instance_of(::Projects::ReleasesController) do |controller|
|
||||
expect(controller).not_to receive(:authenticate_sessionless_user!)
|
||||
end
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'when allow_release_as_web_access_format FF is enabled' do
|
||||
it 'will allow sessionless users to download the file' do
|
||||
subject
|
||||
|
||||
expect(controller.current_user).to eq(user)
|
||||
expect(response).to have_gitlab_http_status(:redirect)
|
||||
expect(response).to redirect_to(link.url)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'invalid filepath' do
|
||||
let(:invalid_filepath) { 'bin/darwin-amd64' }
|
||||
|
||||
let(:subject) { create(:release_link, name: 'linux-amd64 binaries', filepath: invalid_filepath, url: 'https://aws.example.com/s3/project/bin/hello-darwin-amd64') }
|
||||
|
||||
it 'cannot create an invalid filepath' do
|
||||
expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
|
|||
|
||||
def expect_to_rate_limit(hook, threshold:, throttled: false)
|
||||
expect(Gitlab::ApplicationRateLimiter).to receive(:throttled?)
|
||||
.with(:web_hook_calls_high, scope: [hook.parent.root_namespace], threshold: threshold)
|
||||
.with(:web_hook_calls, scope: [hook.parent.root_namespace], threshold: threshold)
|
||||
.and_return(throttled)
|
||||
end
|
||||
|
||||
|
|
@ -621,7 +621,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
|
|||
|
||||
context 'when rate limiting is configured' do
|
||||
let_it_be(:threshold) { 3 }
|
||||
let_it_be(:plan_limits) { create(:plan_limits, :default_plan, web_hook_calls_high: threshold) }
|
||||
let_it_be(:plan_limits) { create(:plan_limits, :default_plan, web_hook_calls: threshold) }
|
||||
|
||||
it 'queues a worker and tracks the call' do
|
||||
expect_to_rate_limit(project_hook, threshold: threshold)
|
||||
|
|
|
|||
Loading…
Reference in New Issue