diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-15 12:09:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-09-15 12:09:47 +0300 |
commit | 33f96e8df089c2291010598c50ec6868ab8cb1ef (patch) | |
tree | 1c9276a56a62e464fc68fa58780647c93f0045cf | |
parent | 034e7d969a591605267c0e5ddbe6f2228bf8e43d (diff) |
Add latest changes from gitlab-org/gitlab@master
49 files changed, 1210 insertions, 192 deletions
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION index e4eccd4e6cd..6dfe8b1298c 100644 --- a/GITLAB_KAS_VERSION +++ b/GITLAB_KAS_VERSION @@ -1 +1 @@ -14.2.2 +14.3.1 @@ -120,7 +120,7 @@ gem 'carrierwave', '~> 1.3' gem 'mini_magick', '~> 4.10.1' # 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. # Also see config/initializers/fog_core_patch.rb. gem 'fog-core', '= 2.1.0' diff --git a/Gemfile.lock b/Gemfile.lock index dcc34698053..87f78455ee0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -395,7 +395,7 @@ GEM fog-json ipaddress (~> 0.8) xml-simple (~> 1.1) - fog-aws (3.9.0) + fog-aws (3.12.0) fog-core (~> 2.1) fog-json (~> 1.1) fog-xml (~> 0.1) @@ -1452,7 +1452,7 @@ DEPENDENCIES flipper-active_support_cache_store (~> 0.21.0) flowdock (~> 0.7) fog-aliyun (~> 0.3) - fog-aws (~> 3.9) + fog-aws (~> 3.12) fog-core (= 2.1.0) fog-google (~> 1.15) fog-local (~> 0.6) diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue index efa1ef2107a..ced76eb4843 100644 --- a/app/assets/javascripts/design_management/components/design_sidebar.vue +++ b/app/assets/javascripts/design_management/components/design_sidebar.vue @@ -202,7 +202,7 @@ export default { data-testid="resolved-discussion" @error="$emit('onDesignDiscussionError', $event)" @updateNoteError="$emit('updateNoteError', $event)" - @openForm="updateDiscussionWithOpenForm" + @open-form="updateDiscussionWithOpenForm" @click.native.stop="updateActiveDiscussion(discussion.notes[0].id)" /> </gl-collapse> diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue index 34d53e2de0c..5f70a9b9664 100644 --- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue +++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue @@ -1,5 +1,13 @@ <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 ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; @@ -14,6 +22,8 @@ export default { GlToggle, GlLoadingIcon, GlSprintf, + GlFormInput, + GlLink, }, props: { isEnabled: { @@ -148,17 +158,37 @@ export default { <span class="sr-only">{{ __('Fetching incoming email') }}</span> </template> - <template v-if="hasProjectKeySupport"> - <label for="service-desk-project-suffix" class="mt-3"> - {{ __('Project name suffix') }} - </label> - <input id="service-desk-project-suffix" v-model.trim="projectKey" class="form-control" /> - <span class="form-text text-muted"> - {{ - __('A string appended to the project path to form the Service Desk email address.') - }} - </span> - </template> + <label for="service-desk-project-suffix" class="mt-3"> + {{ __('Project name suffix') }} + </label> + <gl-form-input + v-if="hasProjectKeySupport" + id="service-desk-project-suffix" + 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 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> + </gl-sprintf> + </span> <label for="service-desk-template-select" class="mt-3"> {{ __('Template to append to all Service Desk issues') }} diff --git a/app/controllers/projects/service_desk_controller.rb b/app/controllers/projects/service_desk_controller.rb index f7c0a54fb9e..1fb07c3a903 100644 --- a/app/controllers/projects/service_desk_controller.rb +++ b/app/controllers/projects/service_desk_controller.rb @@ -24,24 +24,31 @@ class Projects::ServiceDeskController < Projects::ApplicationController private def setting_params - params.permit(:issue_template_key, :outgoing_name, :project_key) + params.permit(*allowed_update_attributes) + end + + def allowed_update_attributes + %i(issue_template_key outgoing_name project_key) + end + + def service_desk_attributes + service_desk_settings = project.service_desk_setting + + { + service_desk_address: project.service_desk_address, + service_desk_enabled: project.service_desk_enabled, + issue_template_key: service_desk_settings&.issue_template_key, + template_file_missing: service_desk_settings&.issue_template_missing?, + outgoing_name: service_desk_settings&.outgoing_name, + project_key: service_desk_settings&.project_key + } end def json_response respond_to do |format| - service_desk_settings = project.service_desk_setting - - service_desk_attributes = - { - service_desk_address: project.service_desk_address, - service_desk_enabled: project.service_desk_enabled, - issue_template_key: service_desk_settings&.issue_template_key, - template_file_missing: service_desk_settings&.issue_template_missing?, - outgoing_name: service_desk_settings&.outgoing_name, - project_key: service_desk_settings&.project_key - } - format.json { render json: service_desk_attributes } end end end + +Projects::ServiceDeskController.prepend_mod diff --git a/app/models/environment.rb b/app/models/environment.rb index a4084565579..48522a23068 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -27,11 +27,10 @@ class Environment < ApplicationRecord 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_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_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus' - has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline' + 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', 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 :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 + 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) cluster_prometheus_adapter&.clear_prometheus_reactive_cache!(query_name, self) end diff --git a/app/models/release.rb b/app/models/release.rb index aad1cbeabdb..0dd71c6ebfb 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -33,7 +33,6 @@ class Release < ApplicationRecord includes(:author, :evidences, :milestones, :links, :sorted_links, project: [:project_feature, :route, { namespace: :route }]) } - scope :with_project_and_namespace, -> { includes(project: :namespace) } scope :recent, -> { sorted.limit(MAX_NUMBER_TO_DISPLAY) } 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) } diff --git a/app/models/repository.rb b/app/models/repository.rb index 33225e51abc..f20b306c806 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -191,7 +191,11 @@ class Repository end def find_tag(name) - tags.find { |tag| tag.name == 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 } + end end def ambiguous_ref?(ref) diff --git a/app/models/service_desk_setting.rb b/app/models/service_desk_setting.rb index 1c854cc9941..6dd7415d928 100644 --- a/app/models/service_desk_setting.rb +++ b/app/models/service_desk_setting.rb @@ -19,7 +19,11 @@ class ServiceDeskSetting < ApplicationRecord strong_memoize(:issue_template_content) do 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 end end @@ -42,6 +46,10 @@ class ServiceDeskSetting < ApplicationRecord private + def source_template_project + nil + end + def projects_with_same_slug_and_key_exists? return false unless project_key @@ -53,3 +61,5 @@ class ServiceDeskSetting < ApplicationRecord end end end + +ServiceDeskSetting.prepend_mod diff --git a/app/views/admin/application_settings/_ip_limits.html.haml b/app/views/admin/application_settings/_ip_limits.html.haml index e584aaf9880..511d628cb79 100644 --- a/app/views/admin/application_settings/_ip_limits.html.haml +++ b/app/views/admin/application_settings/_ip_limits.html.haml @@ -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) %fieldset - %h5 - = _('Unauthenticated request rate limit') + %legend.h5.gl-border-none + = _('Unauthenticated API request rate limit') .form-group - .form-check - = f.check_box :throttle_unauthenticated_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_unauthenticated_checkbox' } - = f.label :throttle_unauthenticated_enabled, class: 'form-check-label label-bold' do - = _("Enable unauthenticated request rate limit") - %span.form-text.text-muted - = _("Helps reduce request volume (e.g. from crawlers or abusive bots)") + = f.gitlab_ui_checkbox_component :throttle_unauthenticated_api_enabled, + _("Enable unauthenticated API request rate limit"), + help_text: _("Helps reduce request volume (e.g. from crawlers or abusive bots)"), + checkbox_options: { data: { qa_selector: 'throttle_unauthenticated_api_checkbox' } } .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' .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' - %hr - %h5 + + %fieldset + %legend.h5.gl-border-none = _('Authenticated API request rate limit') .form-group - .form-check - = f.check_box :throttle_authenticated_api_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_api_checkbox' } - = f.label :throttle_authenticated_api_enabled, class: 'form-check-label label-bold' do - = _("Enable authenticated API request rate limit") - %span.form-text.text-muted - = _("Helps reduce request volume (e.g. from crawlers or abusive bots)") + = f.gitlab_ui_checkbox_component :throttle_authenticated_api_enabled, + _("Enable authenticated API request rate limit"), + help_text: _("Helps reduce request volume (e.g. from crawlers or abusive bots)"), + checkbox_options: { data: { qa_selector: 'throttle_authenticated_api_checkbox' }} .form-group = 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' .form-group = 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' - %hr - %h5 + + %fieldset + %legend.h5.gl-border-none = _('Authenticated web request rate limit') .form-group - .form-check - = f.check_box :throttle_authenticated_web_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_web_checkbox' } - = f.label :throttle_authenticated_web_enabled, class: 'form-check-label label-bold' do - Enable authenticated web request rate limit - %span.form-text.text-muted - Helps reduce request volume (e.g. from crawlers or abusive bots) + = f.gitlab_ui_checkbox_component :throttle_authenticated_web_enabled, + _("Enable authenticated web request rate limit"), + help_text: _("Helps reduce request volume (e.g. from crawlers or abusive bots)"), + checkbox_options: { data: { qa_selector: 'throttle_authenticated_web_checkbox' } } .form-group = 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' .form-group = 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' - %hr - %h5 + + %fieldset + %legend.h5.gl-border-none = _('Response text') .form-group = f.label :rate_limiting_response_text, class: 'label-bold' do diff --git a/config/feature_flags/development/environment_last_visible_pipeline_disable_joins.yml b/config/feature_flags/development/environment_last_visible_pipeline_disable_joins.yml new file mode 100644 index 00000000000..7667542506a --- /dev/null +++ b/config/feature_flags/development/environment_last_visible_pipeline_disable_joins.yml @@ -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 diff --git a/config/feature_flags/development/get_tag_signatures.yml b/config/feature_flags/development/find_tag_via_gitaly.yml index e0d7d5d6dcf..217eac464ad 100644 --- a/config/feature_flags/development/get_tag_signatures.yml +++ b/config/feature_flags/development/find_tag_via_gitaly.yml @@ -1,8 +1,8 @@ --- -name: get_tag_signatures -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67000 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337842 -milestone: '14.2' +name: find_tag_via_gitaly +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70181 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340899 +milestone: '14.3' type: development -group: group::gitaly +group: group::source code default_enabled: false diff --git a/db/migrate/20210902171808_set_default_job_token_scope_false.rb b/db/migrate/20210902171808_set_default_job_token_scope_false.rb new file mode 100644 index 00000000000..0680382094f --- /dev/null +++ b/db/migrate/20210902171808_set_default_job_token_scope_false.rb @@ -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 diff --git a/db/post_migrate/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks.rb b/db/post_migrate/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks.rb new file mode 100644 index 00000000000..44bec402cae --- /dev/null +++ b/db/post_migrate/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks.rb @@ -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 diff --git a/db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb b/db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb new file mode 100644 index 00000000000..2e6ad12f928 --- /dev/null +++ b/db/post_migrate/20210908132335_disable_job_token_scope_when_unused.rb @@ -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 diff --git a/db/schema_migrations/20210902171808 b/db/schema_migrations/20210902171808 new file mode 100644 index 00000000000..1398c2db4b6 --- /dev/null +++ b/db/schema_migrations/20210902171808 @@ -0,0 +1 @@ +09b482e4716a2b0808ad83770222baed8e863a8f94f85f77ed2d557eaa348df4
\ No newline at end of file diff --git a/db/schema_migrations/20210906100316 b/db/schema_migrations/20210906100316 new file mode 100644 index 00000000000..4ce17059b07 --- /dev/null +++ b/db/schema_migrations/20210906100316 @@ -0,0 +1 @@ +b7329d4ff7ee651b56cb86c7091e0d933c4f43a77125323fb6c283eedcb737c2
\ No newline at end of file diff --git a/db/schema_migrations/20210908132335 b/db/schema_migrations/20210908132335 new file mode 100644 index 00000000000..864d6ccc942 --- /dev/null +++ b/db/schema_migrations/20210908132335 @@ -0,0 +1 @@ +399e35197111c257786a2bdf5dac990a26f48d2cc8493de642dcfa47ddececd2
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 34b7d38383f..44800192952 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -108,15 +108,6 @@ BEGIN 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 ( id bigint 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 ( id bigint NOT NULL, - build_id_convert_to_bigint integer DEFAULT 0 NOT NULL, chunk_index integer NOT NULL, data_store integer NOT NULL, raw_data bytea, @@ -17729,7 +17719,7 @@ CREATE TABLE project_ci_cd_settings ( auto_rollback_enabled boolean DEFAULT false NOT NULL, keep_latest_artifact boolean DEFAULT true 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 @@ -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_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_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(); diff --git a/doc/api/settings.md b/doc/api/settings.md index 6b549ecc71c..6b1faa0402f 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -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_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_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_period_in_seconds` | integer | required by:<br>`throttle_unauthenticated_enabled` | 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_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` | ([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` | ([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`. | | `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. | diff --git a/doc/update/package/convert_to_ee.md b/doc/update/package/convert_to_ee.md new file mode 100644 index 00000000000..2cc54e2c8cf --- /dev/null +++ b/doc/update/package/convert_to_ee.md @@ -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). diff --git a/doc/update/package/downgrade.md b/doc/update/package/downgrade.md new file mode 100644 index 00000000000..9a528f5ee44 --- /dev/null +++ b/doc/update/package/downgrade.md @@ -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. diff --git a/doc/update/package/index.md b/doc/update/package/index.md new file mode 100644 index 00000000000..d0b1e46597c --- /dev/null +++ b/doc/update/package/index.md @@ -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). diff --git a/doc/user/admin_area/settings/img/user_and_ip_rate_limits.png b/doc/user/admin_area/settings/img/user_and_ip_rate_limits.png Binary files differdeleted file mode 100644 index 5056e8354a9..00000000000 --- a/doc/user/admin_area/settings/img/user_and_ip_rate_limits.png +++ /dev/null diff --git a/doc/user/admin_area/settings/img/user_and_ip_rate_limits_v14_3.png b/doc/user/admin_area/settings/img/user_and_ip_rate_limits_v14_3.png Binary files differnew file mode 100644 index 00000000000..36f27c4025a --- /dev/null +++ b/doc/user/admin_area/settings/img/user_and_ip_rate_limits_v14_3.png diff --git a/doc/user/admin_area/settings/user_and_ip_rate_limits.md b/doc/user/admin_area/settings/user_and_ip_rate_limits.md index 28c78fd8837..0cf6a0a1b82 100644 --- a/doc/user/admin_area/settings/user_and_ip_rate_limits.md +++ b/doc/user/admin_area/settings/user_and_ip_rate_limits.md @@ -13,7 +13,8 @@ of a web application. For more details, see The following limits are disabled by default: -- Unauthenticated requests +- Unauthenticated API requests +- Unauthenticated web requests - Authenticated API 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 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: 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: - `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_web` - `throttle_unauthenticated_protected_paths` diff --git a/lib/api/entities/blob.rb b/lib/api/entities/blob.rb index b14ef127b68..12700d99865 100644 --- a/lib/api/entities/blob.rb +++ b/lib/api/entities/blob.rb @@ -10,7 +10,7 @@ module API # in the future we can only return the filename here without the leading # directory path. # https://gitlab.com/gitlab-org/gitlab/issues/34521 - expose :filename, &:path + expose :path, as: :filename expose :id expose :ref expose :startline diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 4e588ee9db8..bc15bd367d8 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -127,6 +127,13 @@ module Gitlab 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) wrapped_gitaly_errors do gitaly_ref_client.local_branches(sort_by: sort_by, pagination_params: pagination_params) @@ -604,10 +611,6 @@ module Gitlab end end - def find_tag(name) - tags.find { |tag| tag.name == name } - end - def merge_to_ref(user, **kwargs) wrapped_gitaly_errors do gitaly_operation_client.user_merge_to_ref(user, **kwargs) diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb index 6ba68a92dcd..2dafe0e12ba 100644 --- a/lib/gitlab/gitaly_client/ref_service.rb +++ b/lib/gitlab/gitaly_client/ref_service.rb @@ -129,6 +129,21 @@ module Gitlab Gitlab::Git::Branch.new(@repository, encode!(branch.name.dup), branch.target_commit.id, target_commit) 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: []) request = Gitaly::DeleteRefsRequest.new( repository: @gitaly_repo, diff --git a/lib/gitlab/signed_tag.rb b/lib/gitlab/signed_tag.rb index 3b22cb7622d..49194300a39 100644 --- a/lib/gitlab/signed_tag.rb +++ b/lib/gitlab/signed_tag.rb @@ -7,12 +7,7 @@ module Gitlab def initialize(repository, tag) @repository = repository @tag = tag - - if Feature.enabled?(:get_tag_signatures) - @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 + @signature_data = Gitlab::Git::Tag.extract_signature_lazily(repository, tag.id) if repository end def signature @@ -26,22 +21,5 @@ module Gitlab def signed_text @signature_data&.fetch(1) 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 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b99b4c66722..b58dd6bed68 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -12493,6 +12493,9 @@ msgstr "" msgid "Enable authenticated Git LFS request rate limit" msgstr "" +msgid "Enable authenticated web request rate limit" +msgstr "" + msgid "Enable authentication" msgstr "" @@ -12598,7 +12601,7 @@ msgstr "" msgid "Enable unauthenticated API request rate limit" msgstr "" -msgid "Enable unauthenticated request rate limit" +msgid "Enable unauthenticated web request rate limit" msgstr "" msgid "Enable user deactivation emails" @@ -18937,7 +18940,7 @@ msgstr "" msgid "Iterations|Create cadence" msgstr "" -msgid "Iterations|Create your first iteration" +msgid "Iterations|Create iteration" msgstr "" msgid "Iterations|Delete cadence" @@ -18982,12 +18985,18 @@ msgstr "" msgid "Iterations|New iteration cadence" msgstr "" +msgid "Iterations|No closed iterations." +msgstr "" + msgid "Iterations|No iteration cadences to show." msgstr "" msgid "Iterations|No iterations in cadence." msgstr "" +msgid "Iterations|No open iterations." +msgstr "" + msgid "Iterations|Number of future iterations you would like to have scheduled" msgstr "" @@ -20726,7 +20735,10 @@ msgstr "" msgid "Max session time" 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 "" msgid "MaxBuilds" @@ -25291,6 +25303,9 @@ msgstr "" msgid "Please set a new password before proceeding." 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." msgstr "" @@ -35927,16 +35942,19 @@ msgstr "" msgid "Unassigned" msgstr "" +msgid "Unauthenticated API rate limit period in seconds" +msgstr "" + msgid "Unauthenticated API request rate limit" msgstr "" -msgid "Unauthenticated rate limit period in seconds" +msgid "Unauthenticated requests" msgstr "" -msgid "Unauthenticated request rate limit" +msgid "Unauthenticated web rate limit period in seconds" msgstr "" -msgid "Unauthenticated requests" +msgid "Unauthenticated web request rate limit" msgstr "" msgid "Undo" diff --git a/qa/qa/page/admin/settings/component/ip_limits.rb b/qa/qa/page/admin/settings/component/ip_limits.rb index 1f9bd113cab..a85b96014b3 100644 --- a/qa/qa/page/admin/settings/component/ip_limits.rb +++ b/qa/qa/page/admin/settings/component/ip_limits.rb @@ -7,16 +7,18 @@ module QA module Component class IpLimits < Page::Base 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_web_checkbox element :save_changes_button end def enable_throttles - check_element(:throttle_unauthenticated_checkbox) - check_element(:throttle_authenticated_api_checkbox) - check_element(:throttle_authenticated_web_checkbox) + check_element(:throttle_unauthenticated_api_checkbox, true) + check_element(:throttle_unauthenticated_web_checkbox, true) + check_element(:throttle_authenticated_api_checkbox, true) + check_element(:throttle_authenticated_web_checkbox, true) end def save_settings diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index df4e71c06de..f40905415e0 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -546,6 +546,50 @@ RSpec.describe 'Admin updates settings' do expect(current_settings.dns_rebinding_protection_enabled).to be false 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 visit network_admin_application_settings_path diff --git a/spec/features/projects/settings/service_desk_setting_spec.rb b/spec/features/projects/settings/service_desk_setting_spec.rb index 91355d8f625..0924f8320e1 100644 --- a/spec/features/projects/settings/service_desk_setting_spec.rb +++ b/spec/features/projects/settings/service_desk_setting_spec.rb @@ -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_address).to be_present 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 diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js index 5323c1afbb5..eacf858f22c 100644 --- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js +++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js @@ -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', () => { const email = 'foo@bar.com'; diff --git a/spec/helpers/issuables_description_templates_helper_spec.rb b/spec/helpers/issuables_description_templates_helper_spec.rb index 638dd201fc8..55649e9087a 100644 --- a/spec/helpers/issuables_description_templates_helper_spec.rb +++ b/spec/helpers/issuables_description_templates_helper_spec.rb @@ -56,32 +56,17 @@ RSpec.describe IssuablesDescriptionTemplatesHelper, :clean_gitlab_redis_cache do let(:templates) do { "" => [ - { name: "another_issue_template", id: "another_issue_template" }, - { name: "custom_issue_template", id: "custom_issue_template" } + { name: "another_issue_template", id: "another_issue_template", project_id: project.id }, + { name: "custom_issue_template", id: "custom_issue_template", project_id: project.id } ] } 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]) 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 let(:templates) { {} } diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb index 2ef3b324db8..2916e65528f 100644 --- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb @@ -353,13 +353,4 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do expect { receiver.execute rescue nil }.not_to change { Issue.count } 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 diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb index 79ae47f8a7b..4f56595d7d2 100644 --- a/spec/lib/gitlab/git/tag_spec.rb +++ b/spec/lib/gitlab/git/tag_spec.rb @@ -38,7 +38,7 @@ RSpec.describe Gitlab::Git::Tag, :seed_helper do it { expect(tag.tagger.timezone).to eq("+0200") } end - shared_examples 'signed tag' do + describe 'signed tag' do let(:project) { create(:project, :repository) } 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") } 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) } end diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb index 09e3692626c..df2506b87dd 100644 --- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb @@ -92,6 +92,36 @@ RSpec.describe Gitlab::GitalyClient::RefService do 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 it 'sends a find_default_branch_name message' do expect_any_instance_of(Gitaly::RefService::Stub) diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 410fb4ac125..59b75d9626f 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -771,3 +771,5 @@ push_rule: - group bulk_import_export: - group +service_desk_setting: + - file_template_project diff --git a/spec/lib/gitlab/x509/tag_spec.rb b/spec/lib/gitlab/x509/tag_spec.rb index be120aaf16a..f52880cfc52 100644 --- a/spec/lib/gitlab/x509/tag_spec.rb +++ b/spec/lib/gitlab/x509/tag_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Gitlab::X509::Tag do let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') } let(:project) { create(:project, :repository) } - shared_examples 'signed tag' do + describe 'signed tag' do let(:tag) { project.repository.find_tag('v1.1.1') } 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) } end - shared_examples 'unsigned tag' do + describe 'unsigned tag' do let(:tag) { project.repository.find_tag('v1.0.0') } it { expect(signature).to be_nil } 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 diff --git a/spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb b/spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb new file mode 100644 index 00000000000..8d46ba7eb58 --- /dev/null +++ b/spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb @@ -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 diff --git a/spec/migrations/disable_job_token_scope_when_unused_spec.rb b/spec/migrations/disable_job_token_scope_when_unused_spec.rb new file mode 100644 index 00000000000..d969c98aa0f --- /dev/null +++ b/spec/migrations/disable_job_token_scope_when_unused_spec.rb @@ -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 diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index 4dc47a7efc1..9d305e31bad 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -912,8 +912,8 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do subject { cluster.kubernetes_namespace_for(environment, deployable: build) } let(:environment_name) { 'the-environment-name' } - let(:environment) { create(:environment, name: environment_name, project: cluster.project, last_deployable: build) } - let(:build) { create(:ci_build, environment: environment_name, project: cluster.project) } + let(:environment) { create(:environment, name: environment_name, project: cluster.project) } + let(:build) { create(:ci_build, environment: environment, project: cluster.project) } let(:cluster) { create(:cluster, :project, managed: managed_cluster) } let(:managed_cluster) { true } let(:default_namespace) { Gitlab::Kubernetes::DefaultNamespace.new(cluster, project: cluster.project).from_environment_slug(environment.slug) } diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 7fb6de8b77e..e3e9d1f7a71 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -691,6 +691,28 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do 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 subject { environment.last_visible_deployment } @@ -733,6 +755,86 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do 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 let(:user) { create(:user) } 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) 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 it 'returns the last pipeline' do 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 + + 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 describe '#upcoming_deployment' do diff --git a/spec/models/project_ci_cd_setting_spec.rb b/spec/models/project_ci_cd_setting_spec.rb index c206ba27ec1..406485d8cc8 100644 --- a/spec/models/project_ci_cd_setting_spec.rb +++ b/spec/models/project_ci_cd_setting_spec.rb @@ -21,12 +21,6 @@ RSpec.describe ProjectCiCdSetting do 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 let(:default_value) { described_class::DEFAULT_GIT_DEPTH } diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 047e1ac93e2..9c2f269de46 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2366,6 +2366,42 @@ RSpec.describe Repository do 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 it 'returns nil if repo does not exist' do allow(repository).to receive(:root_ref).and_raise(Gitlab::Git::Repository::NoRepository) diff --git a/spec/support/shared_contexts/email_shared_context.rb b/spec/support/shared_contexts/email_shared_context.rb index 14c6c85cc43..0dc66eeb2ee 100644 --- a/spec/support/shared_contexts/email_shared_context.rb +++ b/spec/support/shared_contexts/email_shared_context.rb @@ -18,6 +18,15 @@ RSpec.shared_context :email_shared_context do 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 context 'when the user could not be found' do before do |