Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
034e7d969a
commit
33f96e8df0
49 changed files with 1213 additions and 195 deletions
|
@ -1 +1 @@
|
||||||
14.2.2
|
14.3.1
|
||||||
|
|
2
Gemfile
2
Gemfile
|
@ -120,7 +120,7 @@ gem 'carrierwave', '~> 1.3'
|
||||||
gem 'mini_magick', '~> 4.10.1'
|
gem 'mini_magick', '~> 4.10.1'
|
||||||
|
|
||||||
# for backups
|
# for backups
|
||||||
gem 'fog-aws', '~> 3.9'
|
gem 'fog-aws', '~> 3.12'
|
||||||
# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
|
# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
|
||||||
# Also see config/initializers/fog_core_patch.rb.
|
# Also see config/initializers/fog_core_patch.rb.
|
||||||
gem 'fog-core', '= 2.1.0'
|
gem 'fog-core', '= 2.1.0'
|
||||||
|
|
|
@ -395,7 +395,7 @@ GEM
|
||||||
fog-json
|
fog-json
|
||||||
ipaddress (~> 0.8)
|
ipaddress (~> 0.8)
|
||||||
xml-simple (~> 1.1)
|
xml-simple (~> 1.1)
|
||||||
fog-aws (3.9.0)
|
fog-aws (3.12.0)
|
||||||
fog-core (~> 2.1)
|
fog-core (~> 2.1)
|
||||||
fog-json (~> 1.1)
|
fog-json (~> 1.1)
|
||||||
fog-xml (~> 0.1)
|
fog-xml (~> 0.1)
|
||||||
|
@ -1452,7 +1452,7 @@ DEPENDENCIES
|
||||||
flipper-active_support_cache_store (~> 0.21.0)
|
flipper-active_support_cache_store (~> 0.21.0)
|
||||||
flowdock (~> 0.7)
|
flowdock (~> 0.7)
|
||||||
fog-aliyun (~> 0.3)
|
fog-aliyun (~> 0.3)
|
||||||
fog-aws (~> 3.9)
|
fog-aws (~> 3.12)
|
||||||
fog-core (= 2.1.0)
|
fog-core (= 2.1.0)
|
||||||
fog-google (~> 1.15)
|
fog-google (~> 1.15)
|
||||||
fog-local (~> 0.6)
|
fog-local (~> 0.6)
|
||||||
|
|
|
@ -202,7 +202,7 @@ export default {
|
||||||
data-testid="resolved-discussion"
|
data-testid="resolved-discussion"
|
||||||
@error="$emit('onDesignDiscussionError', $event)"
|
@error="$emit('onDesignDiscussionError', $event)"
|
||||||
@updateNoteError="$emit('updateNoteError', $event)"
|
@updateNoteError="$emit('updateNoteError', $event)"
|
||||||
@openForm="updateDiscussionWithOpenForm"
|
@open-form="updateDiscussionWithOpenForm"
|
||||||
@click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
|
@click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
|
||||||
/>
|
/>
|
||||||
</gl-collapse>
|
</gl-collapse>
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlButton, GlFormSelect, GlToggle, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
|
import {
|
||||||
|
GlButton,
|
||||||
|
GlFormSelect,
|
||||||
|
GlToggle,
|
||||||
|
GlLoadingIcon,
|
||||||
|
GlSprintf,
|
||||||
|
GlFormInput,
|
||||||
|
GlLink,
|
||||||
|
} from '@gitlab/ui';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||||
|
|
||||||
|
@ -14,6 +22,8 @@ export default {
|
||||||
GlToggle,
|
GlToggle,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
|
GlFormInput,
|
||||||
|
GlLink,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
isEnabled: {
|
isEnabled: {
|
||||||
|
@ -148,17 +158,37 @@ export default {
|
||||||
<span class="sr-only">{{ __('Fetching incoming email') }}</span>
|
<span class="sr-only">{{ __('Fetching incoming email') }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="hasProjectKeySupport">
|
|
||||||
<label for="service-desk-project-suffix" class="mt-3">
|
<label for="service-desk-project-suffix" class="mt-3">
|
||||||
{{ __('Project name suffix') }}
|
{{ __('Project name suffix') }}
|
||||||
</label>
|
</label>
|
||||||
<input id="service-desk-project-suffix" v-model.trim="projectKey" class="form-control" />
|
<gl-form-input
|
||||||
<span class="form-text text-muted">
|
v-if="hasProjectKeySupport"
|
||||||
{{
|
id="service-desk-project-suffix"
|
||||||
__('A string appended to the project path to form the Service Desk email address.')
|
v-model.trim="projectKey"
|
||||||
}}
|
data-testid="project-suffix"
|
||||||
|
class="form-control"
|
||||||
|
/>
|
||||||
|
<span v-if="hasProjectKeySupport" class="form-text text-muted">
|
||||||
|
{{ __('A string appended to the project path to form the Service Desk email address.') }}
|
||||||
</span>
|
</span>
|
||||||
|
<span v-else class="form-text text-muted">
|
||||||
|
<gl-sprintf
|
||||||
|
:message="
|
||||||
|
__(
|
||||||
|
'Please set up a Service Desk email address in order to add a custom suffix. %{linkStart}Learn more%{linkEnd}.',
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #link="{ content }">
|
||||||
|
<gl-link
|
||||||
|
href="https://docs.gitlab.com/ee/user/project/service_desk.html#using-a-custom-email-address"
|
||||||
|
target="_blank"
|
||||||
|
class="gl-text-blue-600 font-size-inherit"
|
||||||
|
>{{ content }}
|
||||||
|
</gl-link>
|
||||||
</template>
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
</span>
|
||||||
|
|
||||||
<label for="service-desk-template-select" class="mt-3">
|
<label for="service-desk-template-select" class="mt-3">
|
||||||
{{ __('Template to append to all Service Desk issues') }}
|
{{ __('Template to append to all Service Desk issues') }}
|
||||||
|
|
|
@ -24,14 +24,16 @@ class Projects::ServiceDeskController < Projects::ApplicationController
|
||||||
private
|
private
|
||||||
|
|
||||||
def setting_params
|
def setting_params
|
||||||
params.permit(:issue_template_key, :outgoing_name, :project_key)
|
params.permit(*allowed_update_attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
def json_response
|
def allowed_update_attributes
|
||||||
respond_to do |format|
|
%i(issue_template_key outgoing_name project_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def service_desk_attributes
|
||||||
service_desk_settings = project.service_desk_setting
|
service_desk_settings = project.service_desk_setting
|
||||||
|
|
||||||
service_desk_attributes =
|
|
||||||
{
|
{
|
||||||
service_desk_address: project.service_desk_address,
|
service_desk_address: project.service_desk_address,
|
||||||
service_desk_enabled: project.service_desk_enabled,
|
service_desk_enabled: project.service_desk_enabled,
|
||||||
|
@ -40,8 +42,13 @@ class Projects::ServiceDeskController < Projects::ApplicationController
|
||||||
outgoing_name: service_desk_settings&.outgoing_name,
|
outgoing_name: service_desk_settings&.outgoing_name,
|
||||||
project_key: service_desk_settings&.project_key
|
project_key: service_desk_settings&.project_key
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def json_response
|
||||||
|
respond_to do |format|
|
||||||
format.json { render json: service_desk_attributes }
|
format.json { render json: service_desk_attributes }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Projects::ServiceDeskController.prepend_mod
|
||||||
|
|
|
@ -27,11 +27,10 @@ class Environment < ApplicationRecord
|
||||||
has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :environment
|
has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :environment
|
||||||
|
|
||||||
has_one :last_deployment, -> { success.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment
|
has_one :last_deployment, -> { success.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment
|
||||||
has_one :last_deployable, through: :last_deployment, source: 'deployable', source_type: 'CommitStatus'
|
|
||||||
has_one :last_pipeline, through: :last_deployable, source: 'pipeline'
|
|
||||||
has_one :last_visible_deployment, -> { visible.distinct_on_environment }, inverse_of: :environment, class_name: 'Deployment'
|
has_one :last_visible_deployment, -> { visible.distinct_on_environment }, inverse_of: :environment, class_name: 'Deployment'
|
||||||
has_one :last_visible_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus'
|
has_one :last_visible_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus', disable_joins: -> { ::Feature.enabled?(:environment_last_visible_pipeline_disable_joins, default_enabled: :yaml) }
|
||||||
has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline'
|
has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline', disable_joins: -> { ::Feature.enabled?(:environment_last_visible_pipeline_disable_joins, default_enabled: :yaml) }
|
||||||
|
|
||||||
has_one :upcoming_deployment, -> { running.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment
|
has_one :upcoming_deployment, -> { running.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment
|
||||||
has_one :latest_opened_most_severe_alert, -> { order_severity_with_open_prometheus_alert }, class_name: 'AlertManagement::Alert', inverse_of: :environment
|
has_one :latest_opened_most_severe_alert, -> { order_severity_with_open_prometheus_alert }, class_name: 'AlertManagement::Alert', inverse_of: :environment
|
||||||
|
|
||||||
|
@ -182,6 +181,35 @@ class Environment < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def last_deployable
|
||||||
|
last_deployment&.deployable
|
||||||
|
end
|
||||||
|
|
||||||
|
# NOTE: Below assocation overrides is a workaround for issue https://gitlab.com/gitlab-org/gitlab/-/issues/339908
|
||||||
|
# It helps to avoid cross joins with the CI database.
|
||||||
|
# Caveat: It also overrides and losses the default AR caching mechanism.
|
||||||
|
# Read - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68870#note_677227727
|
||||||
|
|
||||||
|
# NOTE: Association Preloads does not use the overriden definitions below.
|
||||||
|
# Association Preloads when preloading uses the original definitions from the relationships above.
|
||||||
|
# https://github.com/rails/rails/blob/75ac626c4e21129d8296d4206a1960563cc3d4aa/activerecord/lib/active_record/associations/preloader.rb#L158
|
||||||
|
# But after preloading, when they are called it is using the overriden methods below.
|
||||||
|
# So we are checking for `association_cached?(:association_name)` in the overridden methods and calling `super` which inturn fetches the preloaded values.
|
||||||
|
|
||||||
|
# Overriding association
|
||||||
|
def last_visible_deployable
|
||||||
|
return super if association_cached?(:last_visible_deployable) || ::Feature.disabled?(:environment_last_visible_pipeline_disable_joins, default_enabled: :yaml)
|
||||||
|
|
||||||
|
last_visible_deployment&.deployable
|
||||||
|
end
|
||||||
|
|
||||||
|
# Overriding association
|
||||||
|
def last_visible_pipeline
|
||||||
|
return super if association_cached?(:last_visible_pipeline) || ::Feature.disabled?(:environment_last_visible_pipeline_disable_joins, default_enabled: :yaml)
|
||||||
|
|
||||||
|
last_visible_deployable&.pipeline
|
||||||
|
end
|
||||||
|
|
||||||
def clear_prometheus_reactive_cache!(query_name)
|
def clear_prometheus_reactive_cache!(query_name)
|
||||||
cluster_prometheus_adapter&.clear_prometheus_reactive_cache!(query_name, self)
|
cluster_prometheus_adapter&.clear_prometheus_reactive_cache!(query_name, self)
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,7 +33,6 @@ class Release < ApplicationRecord
|
||||||
includes(:author, :evidences, :milestones, :links, :sorted_links,
|
includes(:author, :evidences, :milestones, :links, :sorted_links,
|
||||||
project: [:project_feature, :route, { namespace: :route }])
|
project: [:project_feature, :route, { namespace: :route }])
|
||||||
}
|
}
|
||||||
scope :with_project_and_namespace, -> { includes(project: :namespace) }
|
|
||||||
scope :recent, -> { sorted.limit(MAX_NUMBER_TO_DISPLAY) }
|
scope :recent, -> { sorted.limit(MAX_NUMBER_TO_DISPLAY) }
|
||||||
scope :without_evidence, -> { left_joins(:evidences).where(::Releases::Evidence.arel_table[:id].eq(nil)) }
|
scope :without_evidence, -> { left_joins(:evidences).where(::Releases::Evidence.arel_table[:id].eq(nil)) }
|
||||||
scope :released_within_2hrs, -> { where(released_at: Time.zone.now - 1.hour..Time.zone.now + 1.hour) }
|
scope :released_within_2hrs, -> { where(released_at: Time.zone.now - 1.hour..Time.zone.now + 1.hour) }
|
||||||
|
|
|
@ -191,8 +191,12 @@ class Repository
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_tag(name)
|
def find_tag(name)
|
||||||
|
if @tags.blank? && Feature.enabled?(:find_tag_via_gitaly, project, default_enabled: :yaml)
|
||||||
|
raw_repository.find_tag(name)
|
||||||
|
else
|
||||||
tags.find { |tag| tag.name == name }
|
tags.find { |tag| tag.name == name }
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def ambiguous_ref?(ref)
|
def ambiguous_ref?(ref)
|
||||||
tag_exists?(ref) && branch_exists?(ref)
|
tag_exists?(ref) && branch_exists?(ref)
|
||||||
|
|
|
@ -19,7 +19,11 @@ class ServiceDeskSetting < ApplicationRecord
|
||||||
strong_memoize(:issue_template_content) do
|
strong_memoize(:issue_template_content) do
|
||||||
next unless issue_template_key.present?
|
next unless issue_template_key.present?
|
||||||
|
|
||||||
Gitlab::Template::IssueTemplate.find(issue_template_key, project).content
|
TemplateFinder.new(
|
||||||
|
:issues, project,
|
||||||
|
name: issue_template_key,
|
||||||
|
source_template_project: source_template_project
|
||||||
|
).execute.content
|
||||||
rescue ::Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
|
rescue ::Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,6 +46,10 @@ class ServiceDeskSetting < ApplicationRecord
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def source_template_project
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
def projects_with_same_slug_and_key_exists?
|
def projects_with_same_slug_and_key_exists?
|
||||||
return false unless project_key
|
return false unless project_key
|
||||||
|
|
||||||
|
@ -53,3 +61,5 @@ class ServiceDeskSetting < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ServiceDeskSetting.prepend_mod
|
||||||
|
|
|
@ -1,56 +1,68 @@
|
||||||
= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-ip-limits-settings'), html: { class: 'fieldset-form' } do |f|
|
= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-ip-limits-settings'), html: { class: 'fieldset-form' } do |f|
|
||||||
= form_errors(@application_setting)
|
= form_errors(@application_setting)
|
||||||
|
|
||||||
%fieldset
|
%fieldset
|
||||||
%h5
|
%legend.h5.gl-border-none
|
||||||
= _('Unauthenticated request rate limit')
|
= _('Unauthenticated API request rate limit')
|
||||||
.form-group
|
.form-group
|
||||||
.form-check
|
= f.gitlab_ui_checkbox_component :throttle_unauthenticated_api_enabled,
|
||||||
= f.check_box :throttle_unauthenticated_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_unauthenticated_checkbox' }
|
_("Enable unauthenticated API request rate limit"),
|
||||||
= f.label :throttle_unauthenticated_enabled, class: 'form-check-label label-bold' do
|
help_text: _("Helps reduce request volume (e.g. from crawlers or abusive bots)"),
|
||||||
= _("Enable unauthenticated request rate limit")
|
checkbox_options: { data: { qa_selector: 'throttle_unauthenticated_api_checkbox' } }
|
||||||
%span.form-text.text-muted
|
|
||||||
= _("Helps reduce request volume (e.g. from crawlers or abusive bots)")
|
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :throttle_unauthenticated_requests_per_period, _('Max unauthenticated requests per period per IP'), class: 'label-bold'
|
= f.label :throttle_unauthenticated_api_requests_per_period, _('Max unauthenticated API requests per period per IP'), class: 'label-bold'
|
||||||
|
= f.number_field :throttle_unauthenticated_api_requests_per_period, class: 'form-control gl-form-input'
|
||||||
|
.form-group
|
||||||
|
= f.label :throttle_unauthenticated_api_period_in_seconds, _('Unauthenticated API rate limit period in seconds'), class: 'label-bold'
|
||||||
|
= f.number_field :throttle_unauthenticated_api_period_in_seconds, class: 'form-control gl-form-input'
|
||||||
|
|
||||||
|
%fieldset
|
||||||
|
%legend.h5.gl-border-none
|
||||||
|
= _('Unauthenticated web request rate limit')
|
||||||
|
.form-group
|
||||||
|
= f.gitlab_ui_checkbox_component :throttle_unauthenticated_enabled,
|
||||||
|
_("Enable unauthenticated web request rate limit"),
|
||||||
|
help_text: _("Helps reduce request volume (e.g. from crawlers or abusive bots)"),
|
||||||
|
checkbox_options: { data: { qa_selector: 'throttle_unauthenticated_web_checkbox' } }
|
||||||
|
.form-group
|
||||||
|
= f.label :throttle_unauthenticated_requests_per_period, _('Max unauthenticated web requests per period per IP'), class: 'label-bold'
|
||||||
= f.number_field :throttle_unauthenticated_requests_per_period, class: 'form-control gl-form-input'
|
= f.number_field :throttle_unauthenticated_requests_per_period, class: 'form-control gl-form-input'
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :throttle_unauthenticated_period_in_seconds, _('Unauthenticated rate limit period in seconds'), class: 'label-bold'
|
= f.label :throttle_unauthenticated_period_in_seconds, _('Unauthenticated web rate limit period in seconds'), class: 'label-bold'
|
||||||
= f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control gl-form-input'
|
= f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control gl-form-input'
|
||||||
%hr
|
|
||||||
%h5
|
%fieldset
|
||||||
|
%legend.h5.gl-border-none
|
||||||
= _('Authenticated API request rate limit')
|
= _('Authenticated API request rate limit')
|
||||||
.form-group
|
.form-group
|
||||||
.form-check
|
= f.gitlab_ui_checkbox_component :throttle_authenticated_api_enabled,
|
||||||
= f.check_box :throttle_authenticated_api_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_api_checkbox' }
|
_("Enable authenticated API request rate limit"),
|
||||||
= f.label :throttle_authenticated_api_enabled, class: 'form-check-label label-bold' do
|
help_text: _("Helps reduce request volume (e.g. from crawlers or abusive bots)"),
|
||||||
= _("Enable authenticated API request rate limit")
|
checkbox_options: { data: { qa_selector: 'throttle_authenticated_api_checkbox' }}
|
||||||
%span.form-text.text-muted
|
|
||||||
= _("Helps reduce request volume (e.g. from crawlers or abusive bots)")
|
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :throttle_authenticated_api_requests_per_period, _('Max authenticated API requests per period per user'), class: 'label-bold'
|
= f.label :throttle_authenticated_api_requests_per_period, _('Max authenticated API requests per period per user'), class: 'label-bold'
|
||||||
= f.number_field :throttle_authenticated_api_requests_per_period, class: 'form-control gl-form-input'
|
= f.number_field :throttle_authenticated_api_requests_per_period, class: 'form-control gl-form-input'
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :throttle_authenticated_api_period_in_seconds, _('Authenticated API rate limit period in seconds'), class: 'label-bold'
|
= f.label :throttle_authenticated_api_period_in_seconds, _('Authenticated API rate limit period in seconds'), class: 'label-bold'
|
||||||
= f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control gl-form-input'
|
= f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control gl-form-input'
|
||||||
%hr
|
|
||||||
%h5
|
%fieldset
|
||||||
|
%legend.h5.gl-border-none
|
||||||
= _('Authenticated web request rate limit')
|
= _('Authenticated web request rate limit')
|
||||||
.form-group
|
.form-group
|
||||||
.form-check
|
= f.gitlab_ui_checkbox_component :throttle_authenticated_web_enabled,
|
||||||
= f.check_box :throttle_authenticated_web_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_web_checkbox' }
|
_("Enable authenticated web request rate limit"),
|
||||||
= f.label :throttle_authenticated_web_enabled, class: 'form-check-label label-bold' do
|
help_text: _("Helps reduce request volume (e.g. from crawlers or abusive bots)"),
|
||||||
Enable authenticated web request rate limit
|
checkbox_options: { data: { qa_selector: 'throttle_authenticated_web_checkbox' } }
|
||||||
%span.form-text.text-muted
|
|
||||||
Helps reduce request volume (e.g. from crawlers or abusive bots)
|
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :throttle_authenticated_web_requests_per_period, _('Max authenticated web requests per period per user'), class: 'label-bold'
|
= f.label :throttle_authenticated_web_requests_per_period, _('Max authenticated web requests per period per user'), class: 'label-bold'
|
||||||
= f.number_field :throttle_authenticated_web_requests_per_period, class: 'form-control gl-form-input'
|
= f.number_field :throttle_authenticated_web_requests_per_period, class: 'form-control gl-form-input'
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :throttle_authenticated_web_period_in_seconds, _('Authenticated web rate limit period in seconds'), class: 'label-bold'
|
= f.label :throttle_authenticated_web_period_in_seconds, _('Authenticated web rate limit period in seconds'), class: 'label-bold'
|
||||||
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control gl-form-input'
|
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control gl-form-input'
|
||||||
%hr
|
|
||||||
%h5
|
%fieldset
|
||||||
|
%legend.h5.gl-border-none
|
||||||
= _('Response text')
|
= _('Response text')
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :rate_limiting_response_text, class: 'label-bold' do
|
= f.label :rate_limiting_response_text, class: 'label-bold' do
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: environment_last_visible_pipeline_disable_joins
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68870
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340283
|
||||||
|
milestone: '14.3'
|
||||||
|
type: development
|
||||||
|
group: group::release
|
||||||
|
default_enabled: true
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: get_tag_signatures
|
name: find_tag_via_gitaly
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67000
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70181
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337842
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340899
|
||||||
milestone: '14.2'
|
milestone: '14.3'
|
||||||
type: development
|
type: development
|
||||||
group: group::gitaly
|
group: group::source code
|
||||||
default_enabled: false
|
default_enabled: false
|
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SetDefaultJobTokenScopeFalse < Gitlab::Database::Migration[1.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
with_lock_retries do
|
||||||
|
change_column_default :project_ci_cd_settings, :job_token_scope_enabled, from: true, to: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
with_lock_retries do
|
||||||
|
change_column_default :project_ci_cd_settings, :job_token_scope_enabled, from: false, to: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DropTemporaryColumnsAndTriggersForCiBuildTraceChunks < Gitlab::Database::Migration[1.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
TABLE = 'ci_build_trace_chunks'
|
||||||
|
COLUMN = 'build_id'
|
||||||
|
|
||||||
|
# rubocop:disable Migration/WithLockRetriesDisallowedMethod
|
||||||
|
def up
|
||||||
|
with_lock_retries do
|
||||||
|
cleanup_conversion_of_integer_to_bigint(TABLE, COLUMN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# rubocop:enable Migration/WithLockRetriesDisallowedMethod
|
||||||
|
|
||||||
|
def down
|
||||||
|
restore_conversion_of_integer_to_bigint(TABLE, COLUMN)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,52 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class DisableJobTokenScopeWhenUnused < Gitlab::Database::Migration[1.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
class ProjectCiCdSetting < ApplicationRecord
|
||||||
|
include EachBatch
|
||||||
|
|
||||||
|
self.table_name = 'project_ci_cd_settings'
|
||||||
|
end
|
||||||
|
|
||||||
|
module Ci
|
||||||
|
module JobToken
|
||||||
|
class ProjectScopeLink < ApplicationRecord
|
||||||
|
self.table_name = 'ci_job_token_project_scope_links'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def up
|
||||||
|
# Disabling job token scope after db/migrate/20210902171808_set_default_job_token_scope_false.rb
|
||||||
|
# if users haven't configured it.
|
||||||
|
ProjectCiCdSetting.each_batch(of: 10_000) do |settings|
|
||||||
|
with_enabled_but_unused_scope(settings).each_batch(of: 500) do |settings_to_update|
|
||||||
|
settings_to_update.update_all(job_token_scope_enabled: false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# irreversible data migration
|
||||||
|
|
||||||
|
# The migration relies on the state of `job_token_scope_enabled` and
|
||||||
|
# updates it based on whether the feature is used or not.
|
||||||
|
#
|
||||||
|
# The inverse migration would be to set `job_token_scope_enabled: true`
|
||||||
|
# for those projects that have the feature disabled and unused. But there
|
||||||
|
# could be also existing cases where the feature is disabled and unused.
|
||||||
|
# For example, old projects.
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# The presence of ProjectScopeLinks means that the job token scope
|
||||||
|
# is configured and we need to leave it enabled. Unused job token scope
|
||||||
|
# can be disabled since they weren't configured.
|
||||||
|
def with_enabled_but_unused_scope(settings)
|
||||||
|
settings
|
||||||
|
.where(job_token_scope_enabled: true)
|
||||||
|
.where.not(project_id: Ci::JobToken::ProjectScopeLink.select(:source_project_id))
|
||||||
|
end
|
||||||
|
end
|
1
db/schema_migrations/20210902171808
Normal file
1
db/schema_migrations/20210902171808
Normal file
|
@ -0,0 +1 @@
|
||||||
|
09b482e4716a2b0808ad83770222baed8e863a8f94f85f77ed2d557eaa348df4
|
1
db/schema_migrations/20210906100316
Normal file
1
db/schema_migrations/20210906100316
Normal file
|
@ -0,0 +1 @@
|
||||||
|
b7329d4ff7ee651b56cb86c7091e0d933c4f43a77125323fb6c283eedcb737c2
|
1
db/schema_migrations/20210908132335
Normal file
1
db/schema_migrations/20210908132335
Normal file
|
@ -0,0 +1 @@
|
||||||
|
399e35197111c257786a2bdf5dac990a26f48d2cc8493de642dcfa47ddececd2
|
|
@ -108,15 +108,6 @@ BEGIN
|
||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
CREATE FUNCTION trigger_cf2f9e35f002() RETURNS trigger
|
|
||||||
LANGUAGE plpgsql
|
|
||||||
AS $$
|
|
||||||
BEGIN
|
|
||||||
NEW."build_id_convert_to_bigint" := NEW."build_id";
|
|
||||||
RETURN NEW;
|
|
||||||
END;
|
|
||||||
$$;
|
|
||||||
|
|
||||||
CREATE TABLE audit_events (
|
CREATE TABLE audit_events (
|
||||||
id bigint NOT NULL,
|
id bigint NOT NULL,
|
||||||
author_id integer NOT NULL,
|
author_id integer NOT NULL,
|
||||||
|
@ -11277,7 +11268,6 @@ ALTER SEQUENCE ci_build_report_results_build_id_seq OWNED BY ci_build_report_res
|
||||||
|
|
||||||
CREATE TABLE ci_build_trace_chunks (
|
CREATE TABLE ci_build_trace_chunks (
|
||||||
id bigint NOT NULL,
|
id bigint NOT NULL,
|
||||||
build_id_convert_to_bigint integer DEFAULT 0 NOT NULL,
|
|
||||||
chunk_index integer NOT NULL,
|
chunk_index integer NOT NULL,
|
||||||
data_store integer NOT NULL,
|
data_store integer NOT NULL,
|
||||||
raw_data bytea,
|
raw_data bytea,
|
||||||
|
@ -17729,7 +17719,7 @@ CREATE TABLE project_ci_cd_settings (
|
||||||
auto_rollback_enabled boolean DEFAULT false NOT NULL,
|
auto_rollback_enabled boolean DEFAULT false NOT NULL,
|
||||||
keep_latest_artifact boolean DEFAULT true NOT NULL,
|
keep_latest_artifact boolean DEFAULT true NOT NULL,
|
||||||
restrict_user_defined_variables boolean DEFAULT false NOT NULL,
|
restrict_user_defined_variables boolean DEFAULT false NOT NULL,
|
||||||
job_token_scope_enabled boolean DEFAULT true NOT NULL
|
job_token_scope_enabled boolean DEFAULT false NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE SEQUENCE project_ci_cd_settings_id_seq
|
CREATE SEQUENCE project_ci_cd_settings_id_seq
|
||||||
|
@ -27329,8 +27319,6 @@ CREATE TRIGGER trigger_91dc388a5fe6 BEFORE INSERT OR UPDATE ON dep_ci_build_trac
|
||||||
|
|
||||||
CREATE TRIGGER trigger_aebe8b822ad3 BEFORE INSERT OR UPDATE ON taggings FOR EACH ROW EXECUTE FUNCTION trigger_aebe8b822ad3();
|
CREATE TRIGGER trigger_aebe8b822ad3 BEFORE INSERT OR UPDATE ON taggings FOR EACH ROW EXECUTE FUNCTION trigger_aebe8b822ad3();
|
||||||
|
|
||||||
CREATE TRIGGER trigger_cf2f9e35f002 BEFORE INSERT OR UPDATE ON ci_build_trace_chunks FOR EACH ROW EXECUTE FUNCTION trigger_cf2f9e35f002();
|
|
||||||
|
|
||||||
CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON integrations FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
|
CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON integrations FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
|
||||||
|
|
||||||
CREATE TRIGGER trigger_has_external_issue_tracker_on_insert AFTER INSERT ON integrations FOR EACH ROW WHEN ((((new.category)::text = 'issue_tracker'::text) AND (new.active = true) AND (new.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
|
CREATE TRIGGER trigger_has_external_issue_tracker_on_insert AFTER INSERT ON integrations FOR EACH ROW WHEN ((((new.category)::text = 'issue_tracker'::text) AND (new.active = true) AND (new.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
|
||||||
|
|
|
@ -415,9 +415,15 @@ listed in the descriptions of the relevant settings.
|
||||||
| `throttle_authenticated_web_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_web_period_in_seconds` and `throttle_authenticated_web_requests_per_period`) Enable authenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
|
| `throttle_authenticated_web_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_web_period_in_seconds` and `throttle_authenticated_web_requests_per_period`) Enable authenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
|
||||||
| `throttle_authenticated_web_period_in_seconds` | integer | required by:<br>`throttle_authenticated_web_enabled` | Rate limit period in seconds. |
|
| `throttle_authenticated_web_period_in_seconds` | integer | required by:<br>`throttle_authenticated_web_enabled` | Rate limit period in seconds. |
|
||||||
| `throttle_authenticated_web_requests_per_period` | integer | required by:<br>`throttle_authenticated_web_enabled` | Max requests per period per user. |
|
| `throttle_authenticated_web_requests_per_period` | integer | required by:<br>`throttle_authenticated_web_enabled` | Max requests per period per user. |
|
||||||
| `throttle_unauthenticated_enabled` | boolean | no | (**If enabled, requires:** `throttle_unauthenticated_period_in_seconds` and `throttle_unauthenticated_requests_per_period`) Enable unauthenticated request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
|
| `throttle_unauthenticated_enabled` | boolean | no | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_enabled` or `throttle_unauthenticated_api_enabled` instead.) (**If enabled, requires:** `throttle_unauthenticated_period_in_seconds` and `throttle_unauthenticated_requests_per_period`) Enable unauthenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
|
||||||
| `throttle_unauthenticated_period_in_seconds` | integer | required by:<br>`throttle_unauthenticated_enabled` | Rate limit period in seconds. |
|
| `throttle_unauthenticated_period_in_seconds` | integer | required by:<br>`throttle_unauthenticated_enabled` | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_period_in_seconds` or `throttle_unauthenticated_api_period_in_seconds` instead.) Rate limit period in seconds. |
|
||||||
| `throttle_unauthenticated_requests_per_period` | integer | required by:<br>`throttle_unauthenticated_enabled` | Max requests per period per IP. |
|
| `throttle_unauthenticated_requests_per_period` | integer | required by:<br>`throttle_unauthenticated_enabled` | ([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_web_requests_per_period` or `throttle_unauthenticated_api_requests_per_period` instead.) Max requests per period per IP. |
|
||||||
|
| `throttle_unauthenticated_api_enabled` | boolean | no | (**If enabled, requires:** `throttle_unauthenticated_api_period_in_seconds` and `throttle_unauthenticated_api_requests_per_period`) Enable unauthenticated API request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
|
||||||
|
| `throttle_unauthenticated_api_period_in_seconds` | integer | required by:<br>`throttle_unauthenticated_api_enabled` | Rate limit period in seconds. |
|
||||||
|
| `throttle_unauthenticated_api_requests_per_period` | integer | required by:<br>`throttle_unauthenticated_api_enabled` | Max requests per period per IP. |
|
||||||
|
| `throttle_unauthenticated_web_enabled` | boolean | no | (**If enabled, requires:** `throttle_unauthenticated_web_period_in_seconds` and `throttle_unauthenticated_web_requests_per_period`) Enable unauthenticated web request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |
|
||||||
|
| `throttle_unauthenticated_web_period_in_seconds` | integer | required by:<br>`throttle_unauthenticated_web_enabled` | Rate limit period in seconds. |
|
||||||
|
| `throttle_unauthenticated_web_requests_per_period` | integer | required by:<br>`throttle_unauthenticated_web_enabled` | Max requests per period per IP. |
|
||||||
| `time_tracking_limit_to_hours` | boolean | no | Limit display of time tracking units to hours. Default is `false`. |
|
| `time_tracking_limit_to_hours` | boolean | no | Limit display of time tracking units to hours. Default is `false`. |
|
||||||
| `two_factor_grace_period` | integer | required by: `require_two_factor_authentication` | Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication. |
|
| `two_factor_grace_period` | integer | required by: `require_two_factor_authentication` | Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication. |
|
||||||
| `unique_ips_limit_enabled` | boolean | no | (**If enabled, requires:** `unique_ips_limit_per_user` and `unique_ips_limit_time_window`) Limit sign in from multiple IPs. |
|
| `unique_ips_limit_enabled` | boolean | no | (**If enabled, requires:** `unique_ips_limit_per_user` and `unique_ips_limit_time_window`) Limit sign in from multiple IPs. |
|
||||||
|
|
118
doc/update/package/convert_to_ee.md
Normal file
118
doc/update/package/convert_to_ee.md
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
---
|
||||||
|
stage: Enablement
|
||||||
|
group: Distribution
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||||
|
---
|
||||||
|
|
||||||
|
# Convert Community Edition to Enterprise Edition **(FREE SELF)**
|
||||||
|
|
||||||
|
To convert an existing GitLab Community Edition (CE) server installed using the Omnibus GitLab
|
||||||
|
packages to GitLab [Enterprise Edition](https://about.gitlab.com/pricing/) (EE), you install the EE
|
||||||
|
package on top of CE.
|
||||||
|
|
||||||
|
Converting from the same version of CE to EE is not explicitly necessary, and any standard upgrade
|
||||||
|
(for example, CE 12.0 to EE 12.1) should work. However, in the following steps we assume that
|
||||||
|
you are upgrading the same version (for example, CE 12.1 to EE 12.1), which is **recommended**.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
When updating to EE from CE, avoid reverting back to CE if you plan on going to EE again in the
|
||||||
|
future. Reverting back to CE can cause
|
||||||
|
[database issues](index.md#500-error-when-accessing-project--settings--repository)
|
||||||
|
that may require Support intervention.
|
||||||
|
|
||||||
|
The steps can be summed up to:
|
||||||
|
|
||||||
|
1. Find the currently installed GitLab version:
|
||||||
|
|
||||||
|
**For Debian/Ubuntu**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo apt-cache policy gitlab-ce | grep Installed
|
||||||
|
```
|
||||||
|
|
||||||
|
The output should be similar to: `Installed: 13.0.4-ce.0`. In that case,
|
||||||
|
the equivalent Enterprise Edition version will be: `13.0.4-ee.0`. Write this
|
||||||
|
value down.
|
||||||
|
|
||||||
|
**For CentOS/RHEL**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo rpm -q gitlab-ce
|
||||||
|
```
|
||||||
|
|
||||||
|
The output should be similar to: `gitlab-ce-13.0.4-ce.0.el8.x86_64`. In that
|
||||||
|
case, the equivalent Enterprise Edition version will be:
|
||||||
|
`gitlab-ee-13.0.4-ee.0.el8.x86_64`. Write this value down.
|
||||||
|
|
||||||
|
1. Add the `gitlab-ee` [Apt or Yum repository](https://packages.gitlab.com/gitlab/gitlab-ee/install):
|
||||||
|
|
||||||
|
**For Debian/Ubuntu**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh" | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
**For CentOS/RHEL**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh" | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
The above command will find your OS version and automatically set up the
|
||||||
|
repository. If you are not comfortable installing the repository through a
|
||||||
|
piped script, you can first
|
||||||
|
[check its contents](https://packages.gitlab.com/gitlab/gitlab-ee/install).
|
||||||
|
|
||||||
|
1. Next, install the `gitlab-ee` package. Note that this will automatically
|
||||||
|
uninstall the `gitlab-ce` package on your GitLab server. `reconfigure`
|
||||||
|
Omnibus right after the `gitlab-ee` package is installed. **Make sure that you
|
||||||
|
install the exact same GitLab version**:
|
||||||
|
|
||||||
|
**For Debian/Ubuntu**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
## Make sure the repositories are up-to-date
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
|
## Install the package using the version you wrote down from step 1
|
||||||
|
sudo apt-get install gitlab-ee=13.0.4-ee.0
|
||||||
|
|
||||||
|
## Reconfigure GitLab
|
||||||
|
sudo gitlab-ctl reconfigure
|
||||||
|
```
|
||||||
|
|
||||||
|
**For CentOS/RHEL**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
## Install the package using the version you wrote down from step 1
|
||||||
|
sudo yum install gitlab-ee-13.0.4-ee.0.el8.x86_64
|
||||||
|
|
||||||
|
## Reconfigure GitLab
|
||||||
|
sudo gitlab-ctl reconfigure
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Now go to the GitLab admin panel of your server (`/admin/license/new`) and
|
||||||
|
upload your license file.
|
||||||
|
|
||||||
|
1. After you confirm that GitLab is working as expected, you may remove the old
|
||||||
|
Community Edition repository:
|
||||||
|
|
||||||
|
**For Debian/Ubuntu**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo rm /etc/apt/sources.list.d/gitlab_gitlab-ce.list
|
||||||
|
```
|
||||||
|
|
||||||
|
**For CentOS/RHEL**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo rm /etc/yum.repos.d/gitlab_gitlab-ce.repo
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! You can now use GitLab Enterprise Edition! To update to a newer
|
||||||
|
version, follow [Update using the official repositories](index.md#upgrade-using-the-official-repositories).
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
If you want to use `dpkg`/`rpm` instead of `apt-get`/`yum`, go through the first
|
||||||
|
step to find the current GitLab version and then follow
|
||||||
|
[Update using a manually-downloaded package](index.md#upgrade-using-a-manually-downloaded-package).
|
83
doc/update/package/downgrade.md
Normal file
83
doc/update/package/downgrade.md
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
---
|
||||||
|
stage: Enablement
|
||||||
|
group: Distribution
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||||
|
---
|
||||||
|
|
||||||
|
# Downgrade **(FREE SELF)**
|
||||||
|
|
||||||
|
This section contains general information on how to revert to an earlier version
|
||||||
|
of a package.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
You must at least have a database backup created under the version you are
|
||||||
|
downgrading to. Ideally, you should have a
|
||||||
|
[full backup archive](../../raketasks/backup_restore.md#back-up-gitlab)
|
||||||
|
on hand.
|
||||||
|
|
||||||
|
The example below demonstrates the downgrade procedure when downgrading between minor
|
||||||
|
and patch versions (for example, from 13.0.6 to 13.0.5).
|
||||||
|
|
||||||
|
When downgrading between major versions, take into account the
|
||||||
|
[specific version changes](index.md#version-specific-changes) that occurred when you upgraded
|
||||||
|
to the major version you are downgrading from.
|
||||||
|
|
||||||
|
These steps consist of:
|
||||||
|
|
||||||
|
- Stopping GitLab
|
||||||
|
- Removing the current package
|
||||||
|
- Installing the old package
|
||||||
|
- Reconfiguring GitLab
|
||||||
|
- Restoring the backup
|
||||||
|
- Starting GitLab
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
|
||||||
|
1. Stop GitLab and remove the current package:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# If running Puma
|
||||||
|
sudo gitlab-ctl stop puma
|
||||||
|
|
||||||
|
# Stop sidekiq
|
||||||
|
sudo gitlab-ctl stop sidekiq
|
||||||
|
|
||||||
|
# If on Ubuntu: remove the current package
|
||||||
|
sudo dpkg -r gitlab-ee
|
||||||
|
|
||||||
|
# If on Centos: remove the current package
|
||||||
|
sudo yum remove gitlab-ee
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Identify the GitLab version you want to downgrade to:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# (Replace with gitlab-ce if you have GitLab FOSS installed)
|
||||||
|
|
||||||
|
# Ubuntu
|
||||||
|
sudo apt-cache madison gitlab-ee
|
||||||
|
|
||||||
|
# CentOS:
|
||||||
|
sudo yum --showduplicates list gitlab-ee
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Downgrade GitLab to the desired version (for example, to GitLab 13.0.5):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# (Replace with gitlab-ce if you have GitLab FOSS installed)
|
||||||
|
|
||||||
|
# Ubuntu
|
||||||
|
sudo apt install gitlab-ee=13.0.5-ee.0
|
||||||
|
|
||||||
|
# CentOS:
|
||||||
|
sudo yum install gitlab-ee-13.0.5-ee.0.el8
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Reconfigure GitLab:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo gitlab-ctl reconfigure
|
||||||
|
```
|
||||||
|
|
||||||
|
1. [Restore GitLab](../../raketasks/backup_restore.md#restore-for-omnibus-gitlab-installations)
|
||||||
|
to complete the downgrade.
|
278
doc/update/package/index.md
Normal file
278
doc/update/package/index.md
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
---
|
||||||
|
stage: Enablement
|
||||||
|
group: Distribution
|
||||||
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||||
|
---
|
||||||
|
|
||||||
|
# Upgrade GitLab using the GitLab Package **(FREE SELF)**
|
||||||
|
|
||||||
|
This section describes how to upgrade GitLab to a new version using the
|
||||||
|
GitLab package.
|
||||||
|
|
||||||
|
We recommend performing upgrades between major and minor releases no more than once per
|
||||||
|
week, to allow time for background migrations to finish. Decrease the time required to
|
||||||
|
complete these migrations by increasing the number of
|
||||||
|
[Sidekiq workers](../../administration/operations/extra_sidekiq_processes.md)
|
||||||
|
that can process jobs in the `background_migration` queue.
|
||||||
|
|
||||||
|
If you don't follow the steps in [zero downtime upgrades](../zero_downtime.md),
|
||||||
|
your GitLab application will not be available to users while an upgrade is in progress.
|
||||||
|
They either see a "Deploy in progress" message or a "502" error in their web browser.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Supported upgrade paths](../index.md#upgrade-paths)
|
||||||
|
has suggestions on when to upgrade. Upgrade paths are enforced for version upgrades by
|
||||||
|
default. This restricts performing direct upgrades that skip major versions (for
|
||||||
|
example 10.3 to 12.7 in one jump) that **can break GitLab
|
||||||
|
installations** due to multiple reasons like deprecated or removed configuration
|
||||||
|
settings, upgrade of internal tools and libraries, and so on.
|
||||||
|
- If you are upgrading from a non-Package installation to a GitLab Package installation, see
|
||||||
|
[Upgrading from a non-Package installation to a GitLab Package installation](https://docs.gitlab.com/omnibus/convert_to_omnibus.html).
|
||||||
|
- It's important to ensure that any
|
||||||
|
[background migrations](../index.md#checking-for-background-migrations-before-upgrading)
|
||||||
|
have been fully completed before upgrading to a new major version. Upgrading
|
||||||
|
before background migrations have finished may lead to data corruption.
|
||||||
|
- Gitaly servers must be upgraded to the newer version prior to upgrading the application server.
|
||||||
|
This prevents the gRPC client on the application server from sending RPCs that the old Gitaly version
|
||||||
|
does not support.
|
||||||
|
|
||||||
|
You can upgrade the GitLab Package using one of the following methods:
|
||||||
|
|
||||||
|
- [Using the official repositories](#upgrade-using-the-official-repositories).
|
||||||
|
- [Using a manually-downloaded package](#upgrade-using-a-manually-downloaded-package).
|
||||||
|
|
||||||
|
Both automatically back up the GitLab database before installing a newer
|
||||||
|
GitLab version. You may skip this automatic database backup by creating an empty file
|
||||||
|
at `/etc/gitlab/skip-auto-backup`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo touch /etc/gitlab/skip-auto-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
For safety reasons, you should maintain an up-to-date backup on your own if you plan to use this flag.
|
||||||
|
|
||||||
|
## Version-specific changes
|
||||||
|
|
||||||
|
Updating to major versions might need some manual intervention. For more information,
|
||||||
|
check the version your are upgrading to:
|
||||||
|
|
||||||
|
- [GitLab 14](https://docs.gitlab.com/omnibus/gitlab_14_changes.html)
|
||||||
|
- [GitLab 13](https://docs.gitlab.com/omnibus/gitlab_13_changes.html)
|
||||||
|
- [GitLab 12](https://docs.gitlab.com/omnibus/gitlab_12_changes.html)
|
||||||
|
- [GitLab 11](https://docs.gitlab.com/omnibus/gitlab_11_changes.html)
|
||||||
|
|
||||||
|
## Upgrade using the official repositories
|
||||||
|
|
||||||
|
All GitLab packages are posted to the GitLab [package server](https://packages.gitlab.com/gitlab/).
|
||||||
|
Five repositories are maintained:
|
||||||
|
|
||||||
|
- [GitLab EE](https://packages.gitlab.com/gitlab/gitlab-ee): for official
|
||||||
|
[Enterprise Edition](https://about.gitlab.com/pricing/) releases.
|
||||||
|
- [GitLab CE](https://packages.gitlab.com/gitlab/gitlab-ce): for official Community Edition releases.
|
||||||
|
- [Unstable](https://packages.gitlab.com/gitlab/unstable): for release candidates and other unstable versions.
|
||||||
|
- [Nighty Builds](https://packages.gitlab.com/gitlab/nightly-builds): for nightly builds.
|
||||||
|
- [Raspberry Pi](https://packages.gitlab.com/gitlab/raspberry-pi2): for official Community Edition releases built for [Raspberry Pi](https://www.raspberrypi.org) packages.
|
||||||
|
|
||||||
|
If you have installed Omnibus GitLab [Community Edition](https://about.gitlab.com/install/?version=ce)
|
||||||
|
or [Enterprise Edition](https://about.gitlab.com/install/), then the
|
||||||
|
official GitLab repository should have already been set up for you.
|
||||||
|
|
||||||
|
To upgrade to the newest GitLab version, run:
|
||||||
|
|
||||||
|
- For GitLab [Enterprise Edition](https://about.gitlab.com/pricing/):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Debian/Ubuntu
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install gitlab-ee
|
||||||
|
|
||||||
|
# Centos/RHEL
|
||||||
|
sudo yum install gitlab-ee
|
||||||
|
```
|
||||||
|
|
||||||
|
- For GitLab Community Edition:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Debian/Ubuntu
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install gitlab-ce
|
||||||
|
|
||||||
|
# Centos/RHEL
|
||||||
|
sudo yum install gitlab-ce
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upgrade to a specific version using the official repositories
|
||||||
|
|
||||||
|
Linux package managers default to installing the latest available version of a
|
||||||
|
package for installation and upgrades. Upgrading directly to the latest major
|
||||||
|
version can be problematic for older GitLab versions that require a multi-stage
|
||||||
|
[upgrade path](../index.md#upgrade-paths). An upgrade path can span multiple
|
||||||
|
versions, so you must specify the specific GitLab package with each upgrade.
|
||||||
|
|
||||||
|
To specify the intended GitLab version number in your package manager's install
|
||||||
|
or upgrade command:
|
||||||
|
|
||||||
|
1. First, identify the GitLab version number in your package manager:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt-cache madison gitlab-ee
|
||||||
|
# RHEL/CentOS 6 and 7
|
||||||
|
yum --showduplicates list gitlab-ee
|
||||||
|
# RHEL/CentOS 8
|
||||||
|
dnf search gitlab-ee*
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Then install the specific GitLab package:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install gitlab-ee=12.0.12-ee.0
|
||||||
|
# RHEL/CentOS 6 and 7
|
||||||
|
yum install gitlab-ee-12.0.12-ee.0.el7
|
||||||
|
# RHEL/CentOS 8
|
||||||
|
dnf install gitlab-ee-12.0.12-ee.0.el8
|
||||||
|
# SUSE
|
||||||
|
zypper install gitlab-ee=12.0.12-ee.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrade using a manually-downloaded package
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
The [package repository](#upgrade-using-the-official-repositories) is recommended over
|
||||||
|
a manual installation.
|
||||||
|
|
||||||
|
If for some reason you don't use the official repositories, you can
|
||||||
|
download the package and install it manually. This method can be used to either
|
||||||
|
install GitLab for the first time or update it.
|
||||||
|
|
||||||
|
To download and install GitLab:
|
||||||
|
|
||||||
|
1. Visit the [official repository](#upgrade-using-the-official-repositories) of your package.
|
||||||
|
1. Browse to the repository for the type of package you would like to see the
|
||||||
|
list of packages that are available. Multiple packages exist for a
|
||||||
|
single version, one for each supported distribution type. Next to the filename
|
||||||
|
is a label indicating the distribution, as the file names may be the same.
|
||||||
|
1. Find the package version you wish to install and click on it.
|
||||||
|
1. Click the **Download** button in the upper right corner to download the package.
|
||||||
|
1. After the GitLab package is downloaded, install it using the following commands:
|
||||||
|
|
||||||
|
- For GitLab [Enterprise Edition](https://about.gitlab.com/pricing/):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Debian/Ubuntu
|
||||||
|
dpkg -i gitlab-ee-<version>.deb
|
||||||
|
|
||||||
|
# CentOS/RHEL
|
||||||
|
rpm -Uvh gitlab-ee-<version>.rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
- For GitLab Community Edition:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# GitLab Community Edition
|
||||||
|
# Debian/Ubuntu
|
||||||
|
dpkg -i gitlab-ce-<version>.deb
|
||||||
|
|
||||||
|
# CentOS/RHEL
|
||||||
|
rpm -Uvh gitlab-ce-<version>.rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### GitLab 13.7 and later unavailable on Amazon Linux 2
|
||||||
|
|
||||||
|
Amazon Linux 2 is not an [officially supported operating system](https://docs.gitlab.com/omnibus/package-information/deprecated_os.html#supported-operating-systems).
|
||||||
|
However, in past the [official package installation script](https://packages.gitlab.com/gitlab/gitlab-ee/install)
|
||||||
|
installed the `el/6` package repository if run on Amazon Linux. From GitLab 13.7, we no longer
|
||||||
|
provide `el/6` packages so administrators must run the [installation script](https://packages.gitlab.com/gitlab/gitlab-ee/install)
|
||||||
|
again to update the repository to `el/7`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh" | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [epic on support for GitLab on Amazon Linux 2](https://gitlab.com/groups/gitlab-org/-/epics/2195) for the latest details on official Amazon Linux 2 support.
|
||||||
|
|
||||||
|
### Get the status of a GitLab installation
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo gitlab-ctl status
|
||||||
|
sudo gitlab-rake gitlab:check SANITIZE=true
|
||||||
|
```
|
||||||
|
|
||||||
|
- Information on using `gitlab-ctl` to perform [maintenance tasks](https://docs.gitlab.com/omnibus/maintenance/index.html).
|
||||||
|
- Information on using `gitlab-rake` to [check the configuration](../../administration/raketasks/maintenance.md#check-gitlab-configuration).
|
||||||
|
|
||||||
|
### RPM 'package is already installed' error
|
||||||
|
|
||||||
|
If you are using RPM and you are upgrading from GitLab Community Edition to GitLab Enterprise Edition you may get an error like this:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
package gitlab-7.5.2_omnibus.5.2.1.ci-1.el7.x86_64 (which is newer than gitlab-7.5.2_ee.omnibus.5.2.1.ci-1.el7.x86_64) is already installed
|
||||||
|
```
|
||||||
|
|
||||||
|
You can override this version check with the `--oldpackage` option:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo rpm -Uvh --oldpackage gitlab-7.5.2_ee.omnibus.5.2.1.ci-1.el7.x86_64.rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
### Package obsoleted by installed package
|
||||||
|
|
||||||
|
CE and EE packages are marked as obsoleting and replacing each other so that both aren't installed and running at the same time.
|
||||||
|
|
||||||
|
If you are using local RPM files to switch from CE to EE or vice versa, use `rpm` for installing the package rather than `yum`. If you try to use yum, then you may get an error like this:
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
Cannot install package gitlab-ee-11.8.3-ee.0.el6.x86_64. It is obsoleted by installed package gitlab-ce-11.8.3-ce.0.el6.x86_64
|
||||||
|
```
|
||||||
|
|
||||||
|
To avoid this issue, either:
|
||||||
|
|
||||||
|
- Use the same instructions provided in the
|
||||||
|
[Upgrade using a manually-downloaded package](#upgrade-using-a-manually-downloaded-package) section.
|
||||||
|
- Temporarily disable this checking in yum by adding `--setopt=obsoletes=0` to the options given to the command.
|
||||||
|
|
||||||
|
### 500 error when accessing Project > Settings > Repository
|
||||||
|
|
||||||
|
When GitLab is migrated from CE > EE > CE, and then back to EE, you
|
||||||
|
might get the following error when viewing a project's repository settings:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
Processing by Projects::Settings::RepositoryController#show as HTML
|
||||||
|
Parameters: {"namespace_id"=>"<namespace_id>", "project_id"=>"<project_id>"}
|
||||||
|
Completed 500 Internal Server Error in 62ms (ActiveRecord: 4.7ms | Elasticsearch: 0.0ms | Allocations: 14583)
|
||||||
|
|
||||||
|
NoMethodError (undefined method `commit_message_negative_regex' for #<PushRule:0x00007fbddf4229b8>
|
||||||
|
Did you mean? commit_message_regex_change):
|
||||||
|
```
|
||||||
|
|
||||||
|
This error is caused by an EE feature being added to a CE instance on the initial move to EE.
|
||||||
|
After the instance is moved back to CE and then is upgraded to EE again, the
|
||||||
|
`push_rules` table already exists in the database. Therefore, a migration is
|
||||||
|
unable to add the `commit_message_regex_change` column.
|
||||||
|
|
||||||
|
This results in the [backport migration of EE tables](https://gitlab.com/gitlab-org/gitlab/-/blob/cf00e431024018ddd82158f8a9210f113d0f4dbc/db/migrate/20190402150158_backport_enterprise_schema.rb#L1619) not working correctly.
|
||||||
|
The backport migration assumes that certain tables in the database do not exist when running CE.
|
||||||
|
|
||||||
|
To fix this issue, manually add the missing `commit_message_negative_regex` column and restart GitLab:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Access psql
|
||||||
|
sudo gitlab-rails dbconsole
|
||||||
|
|
||||||
|
# Add the missing column
|
||||||
|
ALTER TABLE push_rules ADD COLUMN commit_message_negative_regex VARCHAR;
|
||||||
|
|
||||||
|
# Exit psql
|
||||||
|
\q
|
||||||
|
|
||||||
|
# Restart GitLab
|
||||||
|
sudo gitlab-ctl restart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error `Failed to connect to the internal GitLab API` on a separate GitLab Pages server
|
||||||
|
|
||||||
|
Please see [GitLab Pages troubleshooting](../../administration/pages/index.md#failed-to-connect-to-the-internal-gitlab-api).
|
Binary file not shown.
Before Width: | Height: | Size: 36 KiB |
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
|
@ -13,7 +13,8 @@ of a web application. For more details, see
|
||||||
|
|
||||||
The following limits are disabled by default:
|
The following limits are disabled by default:
|
||||||
|
|
||||||
- Unauthenticated requests
|
- Unauthenticated API requests
|
||||||
|
- Unauthenticated web requests
|
||||||
- Authenticated API requests
|
- Authenticated API requests
|
||||||
- Authenticated web requests
|
- Authenticated web requests
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ To enforce any or all of them:
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Admin**.
|
1. On the top bar, select **Menu > Admin**.
|
||||||
1. On the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**:
|
1. On the left sidebar, select **Settings > Network**, and expand **User and IP rate limits**:
|
||||||
![user-and-ip-rate-limits](img/user_and_ip_rate_limits.png)
|
![user-and-ip-rate-limits](img/user_and_ip_rate_limits_v14_3.png)
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations
|
By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations
|
||||||
|
@ -129,6 +130,10 @@ a comma-separated list of throttle names.
|
||||||
The possible names are:
|
The possible names are:
|
||||||
|
|
||||||
- `throttle_unauthenticated`
|
- `throttle_unauthenticated`
|
||||||
|
- [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/335300) in GitLab 14.3. Use `throttle_unauthenticated_api` or `throttle_unauthenticated_web` instead.
|
||||||
|
`throttle_unauthenticated` is still supported and selects both of them.
|
||||||
|
- `throttle_unauthenticated_api`
|
||||||
|
- `throttle_unauthenticated_web`
|
||||||
- `throttle_authenticated_api`
|
- `throttle_authenticated_api`
|
||||||
- `throttle_authenticated_web`
|
- `throttle_authenticated_web`
|
||||||
- `throttle_unauthenticated_protected_paths`
|
- `throttle_unauthenticated_protected_paths`
|
||||||
|
|
|
@ -10,7 +10,7 @@ module API
|
||||||
# in the future we can only return the filename here without the leading
|
# in the future we can only return the filename here without the leading
|
||||||
# directory path.
|
# directory path.
|
||||||
# https://gitlab.com/gitlab-org/gitlab/issues/34521
|
# https://gitlab.com/gitlab-org/gitlab/issues/34521
|
||||||
expose :filename, &:path
|
expose :path, as: :filename
|
||||||
expose :id
|
expose :id
|
||||||
expose :ref
|
expose :ref
|
||||||
expose :startline
|
expose :startline
|
||||||
|
|
|
@ -127,6 +127,13 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_tag(name)
|
||||||
|
wrapped_gitaly_errors do
|
||||||
|
gitaly_ref_client.find_tag(name)
|
||||||
|
end
|
||||||
|
rescue CommandError
|
||||||
|
end
|
||||||
|
|
||||||
def local_branches(sort_by: nil, pagination_params: nil)
|
def local_branches(sort_by: nil, pagination_params: nil)
|
||||||
wrapped_gitaly_errors do
|
wrapped_gitaly_errors do
|
||||||
gitaly_ref_client.local_branches(sort_by: sort_by, pagination_params: pagination_params)
|
gitaly_ref_client.local_branches(sort_by: sort_by, pagination_params: pagination_params)
|
||||||
|
@ -604,10 +611,6 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_tag(name)
|
|
||||||
tags.find { |tag| tag.name == name }
|
|
||||||
end
|
|
||||||
|
|
||||||
def merge_to_ref(user, **kwargs)
|
def merge_to_ref(user, **kwargs)
|
||||||
wrapped_gitaly_errors do
|
wrapped_gitaly_errors do
|
||||||
gitaly_operation_client.user_merge_to_ref(user, **kwargs)
|
gitaly_operation_client.user_merge_to_ref(user, **kwargs)
|
||||||
|
|
|
@ -129,6 +129,21 @@ module Gitlab
|
||||||
Gitlab::Git::Branch.new(@repository, encode!(branch.name.dup), branch.target_commit.id, target_commit)
|
Gitlab::Git::Branch.new(@repository, encode!(branch.name.dup), branch.target_commit.id, target_commit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_tag(tag_name)
|
||||||
|
return if tag_name.blank?
|
||||||
|
|
||||||
|
request = Gitaly::FindTagRequest.new(
|
||||||
|
repository: @gitaly_repo,
|
||||||
|
tag_name: encode_binary(tag_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
response = GitalyClient.call(@repository.storage, :ref_service, :find_tag, request, timeout: GitalyClient.medium_timeout)
|
||||||
|
tag = response.tag
|
||||||
|
return unless tag
|
||||||
|
|
||||||
|
Gitlab::Git::Tag.new(@repository, tag)
|
||||||
|
end
|
||||||
|
|
||||||
def delete_refs(refs: [], except_with_prefixes: [])
|
def delete_refs(refs: [], except_with_prefixes: [])
|
||||||
request = Gitaly::DeleteRefsRequest.new(
|
request = Gitaly::DeleteRefsRequest.new(
|
||||||
repository: @gitaly_repo,
|
repository: @gitaly_repo,
|
||||||
|
|
|
@ -7,12 +7,7 @@ module Gitlab
|
||||||
def initialize(repository, tag)
|
def initialize(repository, tag)
|
||||||
@repository = repository
|
@repository = repository
|
||||||
@tag = tag
|
@tag = tag
|
||||||
|
|
||||||
if Feature.enabled?(:get_tag_signatures)
|
|
||||||
@signature_data = Gitlab::Git::Tag.extract_signature_lazily(repository, tag.id) if repository
|
@signature_data = Gitlab::Git::Tag.extract_signature_lazily(repository, tag.id) if repository
|
||||||
else
|
|
||||||
@signature_data = [signature_text_of_message.b, signed_text_of_message.b]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def signature
|
def signature
|
||||||
|
@ -26,22 +21,5 @@ module Gitlab
|
||||||
def signed_text
|
def signed_text
|
||||||
@signature_data&.fetch(1)
|
@signature_data&.fetch(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def signature_text_of_message
|
|
||||||
@tag.message.slice(@tag.message.index("-----BEGIN SIGNED MESSAGE-----")..-1)
|
|
||||||
rescue StandardError
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def signed_text_of_message
|
|
||||||
%{object #{@tag.target_commit.id}
|
|
||||||
type commit
|
|
||||||
tag #{@tag.name}
|
|
||||||
tagger #{@tag.tagger.name} <#{@tag.tagger.email}> #{@tag.tagger.date.seconds} #{@tag.tagger.timezone}
|
|
||||||
|
|
||||||
#{@tag.message.gsub(/-----BEGIN SIGNED MESSAGE-----(.*)-----END SIGNED MESSAGE-----/m, "")}}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12493,6 +12493,9 @@ msgstr ""
|
||||||
msgid "Enable authenticated Git LFS request rate limit"
|
msgid "Enable authenticated Git LFS request rate limit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Enable authenticated web request rate limit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Enable authentication"
|
msgid "Enable authentication"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -12598,7 +12601,7 @@ msgstr ""
|
||||||
msgid "Enable unauthenticated API request rate limit"
|
msgid "Enable unauthenticated API request rate limit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Enable unauthenticated request rate limit"
|
msgid "Enable unauthenticated web request rate limit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Enable user deactivation emails"
|
msgid "Enable user deactivation emails"
|
||||||
|
@ -18937,7 +18940,7 @@ msgstr ""
|
||||||
msgid "Iterations|Create cadence"
|
msgid "Iterations|Create cadence"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Create your first iteration"
|
msgid "Iterations|Create iteration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Delete cadence"
|
msgid "Iterations|Delete cadence"
|
||||||
|
@ -18982,12 +18985,18 @@ msgstr ""
|
||||||
msgid "Iterations|New iteration cadence"
|
msgid "Iterations|New iteration cadence"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|No closed iterations."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|No iteration cadences to show."
|
msgid "Iterations|No iteration cadences to show."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|No iterations in cadence."
|
msgid "Iterations|No iterations in cadence."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Iterations|No open iterations."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Iterations|Number of future iterations you would like to have scheduled"
|
msgid "Iterations|Number of future iterations you would like to have scheduled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -20726,7 +20735,10 @@ msgstr ""
|
||||||
msgid "Max session time"
|
msgid "Max session time"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Max unauthenticated requests per period per IP"
|
msgid "Max unauthenticated API requests per period per IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Max unauthenticated web requests per period per IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "MaxBuilds"
|
msgid "MaxBuilds"
|
||||||
|
@ -25291,6 +25303,9 @@ msgstr ""
|
||||||
msgid "Please set a new password before proceeding."
|
msgid "Please set a new password before proceeding."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Please set up a Service Desk email address in order to add a custom suffix. %{linkStart}Learn more%{linkEnd}."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Please share your feedback about %{featureName} %{linkStart}in this issue%{linkEnd} to help us improve the experience."
|
msgid "Please share your feedback about %{featureName} %{linkStart}in this issue%{linkEnd} to help us improve the experience."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -35927,18 +35942,21 @@ msgstr ""
|
||||||
msgid "Unassigned"
|
msgid "Unassigned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unauthenticated API rate limit period in seconds"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Unauthenticated API request rate limit"
|
msgid "Unauthenticated API request rate limit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Unauthenticated rate limit period in seconds"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Unauthenticated request rate limit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Unauthenticated requests"
|
msgid "Unauthenticated requests"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unauthenticated web rate limit period in seconds"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Unauthenticated web request rate limit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Undo"
|
msgid "Undo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,18 @@ module QA
|
||||||
module Component
|
module Component
|
||||||
class IpLimits < Page::Base
|
class IpLimits < Page::Base
|
||||||
view 'app/views/admin/application_settings/_ip_limits.html.haml' do
|
view 'app/views/admin/application_settings/_ip_limits.html.haml' do
|
||||||
element :throttle_unauthenticated_checkbox
|
element :throttle_unauthenticated_api_checkbox
|
||||||
|
element :throttle_unauthenticated_web_checkbox
|
||||||
element :throttle_authenticated_api_checkbox
|
element :throttle_authenticated_api_checkbox
|
||||||
element :throttle_authenticated_web_checkbox
|
element :throttle_authenticated_web_checkbox
|
||||||
element :save_changes_button
|
element :save_changes_button
|
||||||
end
|
end
|
||||||
|
|
||||||
def enable_throttles
|
def enable_throttles
|
||||||
check_element(:throttle_unauthenticated_checkbox)
|
check_element(:throttle_unauthenticated_api_checkbox, true)
|
||||||
check_element(:throttle_authenticated_api_checkbox)
|
check_element(:throttle_unauthenticated_web_checkbox, true)
|
||||||
check_element(:throttle_authenticated_web_checkbox)
|
check_element(:throttle_authenticated_api_checkbox, true)
|
||||||
|
check_element(:throttle_authenticated_web_checkbox, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_settings
|
def save_settings
|
||||||
|
|
|
@ -546,6 +546,50 @@ RSpec.describe 'Admin updates settings' do
|
||||||
expect(current_settings.dns_rebinding_protection_enabled).to be false
|
expect(current_settings.dns_rebinding_protection_enabled).to be false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'changes User and IP Rate Limits settings' do
|
||||||
|
visit network_admin_application_settings_path
|
||||||
|
|
||||||
|
page.within('.as-ip-limits') do
|
||||||
|
check 'Enable unauthenticated API request rate limit'
|
||||||
|
fill_in 'Max unauthenticated API requests per period per IP', with: 100
|
||||||
|
fill_in 'Unauthenticated API rate limit period in seconds', with: 200
|
||||||
|
|
||||||
|
check 'Enable unauthenticated web request rate limit'
|
||||||
|
fill_in 'Max unauthenticated web requests per period per IP', with: 300
|
||||||
|
fill_in 'Unauthenticated web rate limit period in seconds', with: 400
|
||||||
|
|
||||||
|
check 'Enable authenticated API request rate limit'
|
||||||
|
fill_in 'Max authenticated API requests per period per user', with: 500
|
||||||
|
fill_in 'Authenticated API rate limit period in seconds', with: 600
|
||||||
|
|
||||||
|
check 'Enable authenticated web request rate limit'
|
||||||
|
fill_in 'Max authenticated web requests per period per user', with: 700
|
||||||
|
fill_in 'Authenticated web rate limit period in seconds', with: 800
|
||||||
|
|
||||||
|
fill_in 'A plain-text response to show to clients that hit the rate limit.', with: 'Custom message'
|
||||||
|
|
||||||
|
click_button 'Save changes'
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_content "Application settings saved successfully"
|
||||||
|
|
||||||
|
expect(current_settings).to have_attributes(
|
||||||
|
throttle_unauthenticated_api_enabled: true,
|
||||||
|
throttle_unauthenticated_api_requests_per_period: 100,
|
||||||
|
throttle_unauthenticated_api_period_in_seconds: 200,
|
||||||
|
throttle_unauthenticated_enabled: true,
|
||||||
|
throttle_unauthenticated_requests_per_period: 300,
|
||||||
|
throttle_unauthenticated_period_in_seconds: 400,
|
||||||
|
throttle_authenticated_api_enabled: true,
|
||||||
|
throttle_authenticated_api_requests_per_period: 500,
|
||||||
|
throttle_authenticated_api_period_in_seconds: 600,
|
||||||
|
throttle_authenticated_web_enabled: true,
|
||||||
|
throttle_authenticated_web_requests_per_period: 700,
|
||||||
|
throttle_authenticated_web_period_in_seconds: 800,
|
||||||
|
rate_limiting_response_text: 'Custom message'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
it 'changes Issues rate limits settings' do
|
it 'changes Issues rate limits settings' do
|
||||||
visit network_admin_application_settings_path
|
visit network_admin_application_settings_path
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@ RSpec.describe 'Service Desk Setting', :js, :clean_gitlab_redis_cache do
|
||||||
expect(project.service_desk_enabled).to be_truthy
|
expect(project.service_desk_enabled).to be_truthy
|
||||||
expect(project.service_desk_address).to be_present
|
expect(project.service_desk_address).to be_present
|
||||||
expect(find('[data-testid="incoming-email"]').value).to eq(project.service_desk_incoming_address)
|
expect(find('[data-testid="incoming-email"]').value).to eq(project.service_desk_incoming_address)
|
||||||
expect(page).not_to have_selector('#service-desk-project-suffix')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,29 @@ describe('ServiceDeskSetting', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('project suffix', () => {
|
||||||
|
it('input is hidden', () => {
|
||||||
|
wrapper = createComponent({
|
||||||
|
props: { customEmailEnabled: false },
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = wrapper.findByTestId('project-suffix');
|
||||||
|
|
||||||
|
expect(input.exists()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('input is enabled', () => {
|
||||||
|
wrapper = createComponent({
|
||||||
|
props: { customEmailEnabled: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = wrapper.findByTestId('project-suffix');
|
||||||
|
|
||||||
|
expect(input.exists()).toBe(true);
|
||||||
|
expect(input.attributes('disabled')).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('customEmail is the same as incomingEmail', () => {
|
describe('customEmail is the same as incomingEmail', () => {
|
||||||
const email = 'foo@bar.com';
|
const email = 'foo@bar.com';
|
||||||
|
|
||||||
|
|
|
@ -56,32 +56,17 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do
|
||||||
let(:templates) do
|
let(:templates) do
|
||||||
{
|
{
|
||||||
"" => [
|
"" => [
|
||||||
{ name: "another_issue_template", id: "another_issue_template" },
|
{ name: "another_issue_template", id: "another_issue_template", project_id: project.id },
|
||||||
{ name: "custom_issue_template", id: "custom_issue_template" }
|
{ name: "custom_issue_template", id: "custom_issue_template", project_id: project.id }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns project templates only' do
|
it 'returns project templates' do
|
||||||
expect(helper.issuable_templates_names(Issue.new)).to eq(%w[another_issue_template custom_issue_template])
|
expect(helper.issuable_templates_names(Issue.new)).to eq(%w[another_issue_template custom_issue_template])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'without matching project templates' do
|
|
||||||
let(:templates) do
|
|
||||||
{
|
|
||||||
"Project Templates" => [
|
|
||||||
{ name: "another_issue_template", id: "another_issue_template", project_id: non_existing_record_id },
|
|
||||||
{ name: "custom_issue_template", id: "custom_issue_template", project_id: non_existing_record_id }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns empty array' do
|
|
||||||
expect(helper.issuable_templates_names(Issue.new)).to eq([])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when there are not templates in the project' do
|
context 'when there are not templates in the project' do
|
||||||
let(:templates) { {} }
|
let(:templates) { {} }
|
||||||
|
|
||||||
|
|
|
@ -353,13 +353,4 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
|
||||||
expect { receiver.execute rescue nil }.not_to change { Issue.count }
|
expect { receiver.execute rescue nil }.not_to change { Issue.count }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def email_fixture(path)
|
|
||||||
fixture_file(path).gsub('project_id', project.project_id.to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
def service_desk_fixture(path, slug: nil, key: 'mykey')
|
|
||||||
slug ||= project.full_path_slug.to_s
|
|
||||||
fixture_file(path).gsub('project_slug', slug).gsub('project_key', key)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,7 +38,7 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
|
||||||
it { expect(tag.tagger.timezone).to eq("+0200") }
|
it { expect(tag.tagger.timezone).to eq("+0200") }
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples 'signed tag' do
|
describe 'signed tag' do
|
||||||
let(:project) { create(:project, :repository) }
|
let(:project) { create(:project, :repository) }
|
||||||
let(:tag) { project.repository.find_tag('v1.1.1') }
|
let(:tag) { project.repository.find_tag('v1.1.1') }
|
||||||
|
|
||||||
|
@ -54,18 +54,6 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do
|
||||||
it { expect(tag.tagger.timezone).to eq("+0100") }
|
it { expect(tag.tagger.timezone).to eq("+0100") }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with :get_tag_signatures enabled' do
|
|
||||||
it_behaves_like 'signed tag'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with :get_tag_signatures disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(get_tag_signatures: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'signed tag'
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) }
|
it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,36 @@ RSpec.describe Gitlab::GitalyClient::RefService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#find_branch' do
|
||||||
|
it 'sends a find_branch message' do
|
||||||
|
expect_any_instance_of(Gitaly::RefService::Stub)
|
||||||
|
.to receive(:find_branch)
|
||||||
|
.with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
|
||||||
|
.and_return(double(branch: Gitaly::Branch.new(name: 'name', target_commit: build(:gitaly_commit))))
|
||||||
|
|
||||||
|
client.find_branch('name')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#find_tag' do
|
||||||
|
it 'sends a find_tag message' do
|
||||||
|
expect_any_instance_of(Gitaly::RefService::Stub)
|
||||||
|
.to receive(:find_tag)
|
||||||
|
.with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
|
||||||
|
.and_return(double(tag: Gitaly::Tag.new))
|
||||||
|
|
||||||
|
client.find_tag('name')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when tag is empty' do
|
||||||
|
it 'does not send a fing_tag message' do
|
||||||
|
expect_any_instance_of(Gitaly::RefService::Stub).not_to receive(:find_tag)
|
||||||
|
|
||||||
|
expect(client.find_tag('')).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#default_branch_name' do
|
describe '#default_branch_name' do
|
||||||
it 'sends a find_default_branch_name message' do
|
it 'sends a find_default_branch_name message' do
|
||||||
expect_any_instance_of(Gitaly::RefService::Stub)
|
expect_any_instance_of(Gitaly::RefService::Stub)
|
||||||
|
|
|
@ -771,3 +771,5 @@ push_rule:
|
||||||
- group
|
- group
|
||||||
bulk_import_export:
|
bulk_import_export:
|
||||||
- group
|
- group
|
||||||
|
service_desk_setting:
|
||||||
|
- file_template_project
|
||||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe Gitlab::X509::Tag do
|
||||||
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
|
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
|
||||||
let(:project) { create(:project, :repository) }
|
let(:project) { create(:project, :repository) }
|
||||||
|
|
||||||
shared_examples 'signed tag' do
|
describe 'signed tag' do
|
||||||
let(:tag) { project.repository.find_tag('v1.1.1') }
|
let(:tag) { project.repository.find_tag('v1.1.1') }
|
||||||
let(:certificate_attributes) do
|
let(:certificate_attributes) do
|
||||||
{
|
{
|
||||||
|
@ -33,24 +33,10 @@ RSpec.describe Gitlab::X509::Tag do
|
||||||
it { expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes) }
|
it { expect(signature.x509_certificate.x509_issuer).to have_attributes(issuer_attributes) }
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples 'unsigned tag' do
|
describe 'unsigned tag' do
|
||||||
let(:tag) { project.repository.find_tag('v1.0.0') }
|
let(:tag) { project.repository.find_tag('v1.0.0') }
|
||||||
|
|
||||||
it { expect(signature).to be_nil }
|
it { expect(signature).to be_nil }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with :get_tag_signatures enabled' do
|
|
||||||
it_behaves_like 'signed tag'
|
|
||||||
it_behaves_like 'unsigned tag'
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with :get_tag_signatures disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(get_tag_signatures: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'signed tag'
|
|
||||||
it_behaves_like 'unsigned tag'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require_migration!('drop_temporary_columns_and_triggers_for_ci_build_trace_chunks')
|
||||||
|
|
||||||
|
RSpec.describe DropTemporaryColumnsAndTriggersForCiBuildTraceChunks do
|
||||||
|
let(:ci_build_trace_chunks_table) { table(:ci_build_trace_chunks) }
|
||||||
|
|
||||||
|
it 'correctly migrates up and down' do
|
||||||
|
reversible_migration do |migration|
|
||||||
|
migration.before -> {
|
||||||
|
expect(ci_build_trace_chunks_table.column_names).to include('build_id_convert_to_bigint')
|
||||||
|
}
|
||||||
|
|
||||||
|
migration.after -> {
|
||||||
|
ci_build_trace_chunks_table.reset_column_information
|
||||||
|
expect(ci_build_trace_chunks_table.column_names).not_to include('build_id_convert_to_bigint')
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
44
spec/migrations/disable_job_token_scope_when_unused_spec.rb
Normal file
44
spec/migrations/disable_job_token_scope_when_unused_spec.rb
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require_migration!
|
||||||
|
|
||||||
|
RSpec.describe DisableJobTokenScopeWhenUnused do
|
||||||
|
let(:ci_cd_settings) { table(:project_ci_cd_settings) }
|
||||||
|
let(:links) { table(:ci_job_token_project_scope_links) }
|
||||||
|
let(:namespaces) { table(:namespaces) }
|
||||||
|
let(:projects) { table(:projects) }
|
||||||
|
|
||||||
|
let(:namespace) { namespaces.create!(name: 'test', path: 'path', type: 'Group') }
|
||||||
|
|
||||||
|
let(:project_with_used_scope) { projects.create!(namespace_id: namespace.id) }
|
||||||
|
let!(:used_scope_settings) { ci_cd_settings.create!(project_id: project_with_used_scope.id, job_token_scope_enabled: true) }
|
||||||
|
let(:target_project) { projects.create!(namespace_id: namespace.id) }
|
||||||
|
let!(:link) { links.create!(source_project_id: project_with_used_scope.id, target_project_id: target_project.id) }
|
||||||
|
|
||||||
|
let(:project_with_unused_scope) { projects.create!(namespace_id: namespace.id) }
|
||||||
|
let!(:unused_scope_settings) { ci_cd_settings.create!(project_id: project_with_unused_scope.id, job_token_scope_enabled: true) }
|
||||||
|
|
||||||
|
let(:project_with_disabled_scope) { projects.create!(namespace_id: namespace.id) }
|
||||||
|
let!(:disabled_scope_settings) { ci_cd_settings.create!(project_id: project_with_disabled_scope.id, job_token_scope_enabled: false) }
|
||||||
|
|
||||||
|
describe '#up' do
|
||||||
|
it 'sets job_token_scope_enabled to false for projects not having job token scope configured' do
|
||||||
|
migrate!
|
||||||
|
|
||||||
|
expect(unused_scope_settings.reload.job_token_scope_enabled).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'keeps the scope enabled for projects that are using it' do
|
||||||
|
migrate!
|
||||||
|
|
||||||
|
expect(used_scope_settings.reload.job_token_scope_enabled).to be_truthy
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'keeps the scope disabled for projects having it disabled' do
|
||||||
|
migrate!
|
||||||
|
|
||||||
|
expect(disabled_scope_settings.reload.job_token_scope_enabled).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -912,8 +912,8 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
|
||||||
subject { cluster.kubernetes_namespace_for(environment, deployable: build) }
|
subject { cluster.kubernetes_namespace_for(environment, deployable: build) }
|
||||||
|
|
||||||
let(:environment_name) { 'the-environment-name' }
|
let(:environment_name) { 'the-environment-name' }
|
||||||
let(:environment) { create(:environment, name: environment_name, project: cluster.project, last_deployable: build) }
|
let(:environment) { create(:environment, name: environment_name, project: cluster.project) }
|
||||||
let(:build) { create(:ci_build, environment: environment_name, project: cluster.project) }
|
let(:build) { create(:ci_build, environment: environment, project: cluster.project) }
|
||||||
let(:cluster) { create(:cluster, :project, managed: managed_cluster) }
|
let(:cluster) { create(:cluster, :project, managed: managed_cluster) }
|
||||||
let(:managed_cluster) { true }
|
let(:managed_cluster) { true }
|
||||||
let(:default_namespace) { Gitlab::Kubernetes::DefaultNamespace.new(cluster, project: cluster.project).from_environment_slug(environment.slug) }
|
let(:default_namespace) { Gitlab::Kubernetes::DefaultNamespace.new(cluster, project: cluster.project).from_environment_slug(environment.slug) }
|
||||||
|
|
|
@ -691,6 +691,28 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#last_deployable' do
|
||||||
|
subject { environment.last_deployable }
|
||||||
|
|
||||||
|
context 'does not join across databases' do
|
||||||
|
let(:pipeline_a) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:pipeline_b) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:ci_build_a) { create(:ci_build, project: project, pipeline: pipeline_a) }
|
||||||
|
let(:ci_build_b) { create(:ci_build, project: project, pipeline: pipeline_b) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
create(:deployment, :success, project: project, environment: environment, deployable: ci_build_a)
|
||||||
|
create(:deployment, :failed, project: project, environment: environment, deployable: ci_build_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'when called' do
|
||||||
|
with_cross_joins_prevented do
|
||||||
|
expect(subject.id).to eq(ci_build_a.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#last_visible_deployment' do
|
describe '#last_visible_deployment' do
|
||||||
subject { environment.last_visible_deployment }
|
subject { environment.last_visible_deployment }
|
||||||
|
|
||||||
|
@ -733,6 +755,86 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#last_visible_deployable' do
|
||||||
|
subject { environment.last_visible_deployable }
|
||||||
|
|
||||||
|
context 'does not join across databases' do
|
||||||
|
let(:pipeline_a) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:pipeline_b) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:ci_build_a) { create(:ci_build, project: project, pipeline: pipeline_a) }
|
||||||
|
let(:ci_build_b) { create(:ci_build, project: project, pipeline: pipeline_b) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
create(:deployment, :success, project: project, environment: environment, deployable: ci_build_a)
|
||||||
|
create(:deployment, :failed, project: project, environment: environment, deployable: ci_build_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'for direct call' do
|
||||||
|
with_cross_joins_prevented do
|
||||||
|
expect(subject.id).to eq(ci_build_b.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'for preload' do
|
||||||
|
environment.reload
|
||||||
|
|
||||||
|
with_cross_joins_prevented do
|
||||||
|
ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_deployable: []])
|
||||||
|
expect(subject.id).to eq(ci_build_b.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'call after preload' do
|
||||||
|
it 'fetches from association cache' do
|
||||||
|
pipeline = create(:ci_pipeline, project: project)
|
||||||
|
ci_build = create(:ci_build, project: project, pipeline: pipeline)
|
||||||
|
create(:deployment, :failed, project: project, environment: environment, deployable: ci_build)
|
||||||
|
|
||||||
|
environment.reload
|
||||||
|
ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_deployable: []])
|
||||||
|
|
||||||
|
query_count = ActiveRecord::QueryRecorder.new do
|
||||||
|
expect(subject.id).to eq(ci_build.id)
|
||||||
|
end.count
|
||||||
|
|
||||||
|
expect(query_count).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the feature for disable_join is disabled' do
|
||||||
|
let(:pipeline) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:ci_build) { create(:ci_build, project: project, pipeline: pipeline) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_feature_flags(environment_last_visible_pipeline_disable_joins: false)
|
||||||
|
create(:deployment, :failed, project: project, environment: environment, deployable: ci_build)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for preload' do
|
||||||
|
it 'executes the original association instead of override' do
|
||||||
|
environment.reload
|
||||||
|
ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_deployable: []])
|
||||||
|
|
||||||
|
expect_any_instance_of(Deployment).not_to receive(:deployable)
|
||||||
|
|
||||||
|
query_count = ActiveRecord::QueryRecorder.new do
|
||||||
|
expect(subject.id).to eq(ci_build.id)
|
||||||
|
end.count
|
||||||
|
|
||||||
|
expect(query_count).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for direct call' do
|
||||||
|
it 'executes the original association instead of override' do
|
||||||
|
expect_any_instance_of(Deployment).not_to receive(:deployable)
|
||||||
|
expect(subject.id).to eq(ci_build.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#last_visible_pipeline' do
|
describe '#last_visible_pipeline' do
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
let_it_be(:project) { create(:project, :repository) }
|
let_it_be(:project) { create(:project, :repository) }
|
||||||
|
@ -777,6 +879,35 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
|
||||||
expect(last_pipeline).to eq(failed_pipeline)
|
expect(last_pipeline).to eq(failed_pipeline)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'does not join across databases' do
|
||||||
|
let(:pipeline_a) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:pipeline_b) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:ci_build_a) { create(:ci_build, project: project, pipeline: pipeline_a) }
|
||||||
|
let(:ci_build_b) { create(:ci_build, project: project, pipeline: pipeline_b) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
create(:deployment, :success, project: project, environment: environment, deployable: ci_build_a)
|
||||||
|
create(:deployment, :failed, project: project, environment: environment, deployable: ci_build_b)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { environment.last_visible_pipeline }
|
||||||
|
|
||||||
|
it 'for direct call' do
|
||||||
|
with_cross_joins_prevented do
|
||||||
|
expect(subject.id).to eq(pipeline_b.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'for preload' do
|
||||||
|
environment.reload
|
||||||
|
|
||||||
|
with_cross_joins_prevented do
|
||||||
|
ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_pipeline: []])
|
||||||
|
expect(subject.id).to eq(pipeline_b.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'for the environment' do
|
context 'for the environment' do
|
||||||
it 'returns the last pipeline' do
|
it 'returns the last pipeline' do
|
||||||
pipeline = create(:ci_pipeline, project: project, user: user, sha: commit.sha)
|
pipeline = create(:ci_pipeline, project: project, user: user, sha: commit.sha)
|
||||||
|
@ -815,6 +946,57 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'call after preload' do
|
||||||
|
it 'fetches from association cache' do
|
||||||
|
pipeline = create(:ci_pipeline, project: project)
|
||||||
|
ci_build = create(:ci_build, project: project, pipeline: pipeline)
|
||||||
|
create(:deployment, :failed, project: project, environment: environment, deployable: ci_build)
|
||||||
|
|
||||||
|
environment.reload
|
||||||
|
ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_pipeline: []])
|
||||||
|
|
||||||
|
query_count = ActiveRecord::QueryRecorder.new do
|
||||||
|
expect(environment.last_visible_pipeline.id).to eq(pipeline.id)
|
||||||
|
end.count
|
||||||
|
|
||||||
|
expect(query_count).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the feature for disable_join is disabled' do
|
||||||
|
let(:pipeline) { create(:ci_pipeline, project: project) }
|
||||||
|
let(:ci_build) { create(:ci_build, project: project, pipeline: pipeline) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_feature_flags(environment_last_visible_pipeline_disable_joins: false)
|
||||||
|
create(:deployment, :failed, project: project, environment: environment, deployable: ci_build)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { environment.last_visible_pipeline }
|
||||||
|
|
||||||
|
context 'for preload' do
|
||||||
|
it 'executes the original association instead of override' do
|
||||||
|
environment.reload
|
||||||
|
ActiveRecord::Associations::Preloader.new.preload(environment, [last_visible_pipeline: []])
|
||||||
|
|
||||||
|
expect_any_instance_of(Ci::Build).not_to receive(:pipeline)
|
||||||
|
|
||||||
|
query_count = ActiveRecord::QueryRecorder.new do
|
||||||
|
expect(subject.id).to eq(pipeline.id)
|
||||||
|
end.count
|
||||||
|
|
||||||
|
expect(query_count).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for direct call' do
|
||||||
|
it 'executes the original association instead of override' do
|
||||||
|
expect_any_instance_of(Ci::Build).not_to receive(:pipeline)
|
||||||
|
expect(subject.id).to eq(pipeline.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#upcoming_deployment' do
|
describe '#upcoming_deployment' do
|
||||||
|
|
|
@ -21,12 +21,6 @@ RSpec.describe ProjectCiCdSetting do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#job_token_scope_enabled' do
|
|
||||||
it 'is true by default' do
|
|
||||||
expect(described_class.new.job_token_scope_enabled).to be_truthy
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#default_git_depth' do
|
describe '#default_git_depth' do
|
||||||
let(:default_value) { described_class::DEFAULT_GIT_DEPTH }
|
let(:default_value) { described_class::DEFAULT_GIT_DEPTH }
|
||||||
|
|
||||||
|
|
|
@ -2366,6 +2366,42 @@ RSpec.describe Repository do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#find_tag' do
|
||||||
|
before do
|
||||||
|
allow(Gitlab::GitalyClient).to receive(:call).and_call_original
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'finds a tag with specified name by performing FindTag request' do
|
||||||
|
expect(Gitlab::GitalyClient)
|
||||||
|
.to receive(:call).with(anything, :ref_service, :find_tag, anything, anything).and_call_original
|
||||||
|
|
||||||
|
expect(repository.find_tag('v1.1.0').name).to eq('v1.1.0')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not perform Gitaly call when tags are preloaded' do
|
||||||
|
repository.tags
|
||||||
|
|
||||||
|
expect(Gitlab::GitalyClient).not_to receive(:call)
|
||||||
|
|
||||||
|
expect(repository.find_tag('v1.1.0').name).to eq('v1.1.0')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns nil when tag does not exists' do
|
||||||
|
expect(repository.find_tag('does-not-exist')).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when find_tag_via_gitaly is disabled' do
|
||||||
|
it 'fetches all tags' do
|
||||||
|
stub_feature_flags(find_tag_via_gitaly: false)
|
||||||
|
|
||||||
|
expect(Gitlab::GitalyClient)
|
||||||
|
.to receive(:call).with(anything, :ref_service, :find_all_tags, anything, anything).and_call_original
|
||||||
|
|
||||||
|
expect(repository.find_tag('v1.1.0').name).to eq('v1.1.0')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#avatar' do
|
describe '#avatar' do
|
||||||
it 'returns nil if repo does not exist' do
|
it 'returns nil if repo does not exist' do
|
||||||
allow(repository).to receive(:root_ref).and_raise(Gitlab::Git::Repository::NoRepository)
|
allow(repository).to receive(:root_ref).and_raise(Gitlab::Git::Repository::NoRepository)
|
||||||
|
|
|
@ -18,6 +18,15 @@ RSpec.shared_context :email_shared_context do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def email_fixture(path)
|
||||||
|
fixture_file(path).gsub('project_id', project.project_id.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
def service_desk_fixture(path, slug: nil, key: 'mykey')
|
||||||
|
slug ||= project.full_path_slug.to_s
|
||||||
|
fixture_file(path).gsub('project_slug', slug).gsub('project_key', key)
|
||||||
|
end
|
||||||
|
|
||||||
RSpec.shared_examples :reply_processing_shared_examples do
|
RSpec.shared_examples :reply_processing_shared_examples do
|
||||||
context 'when the user could not be found' do
|
context 'when the user could not be found' do
|
||||||
before do
|
before do
|
||||||
|
|
Loading…
Reference in a new issue