diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-17 21:09:20 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-17 21:09:20 +0300 |
commit | 6f05d35c3160e3a442b40d6af1e8e584747080b3 (patch) | |
tree | f70f90e1ae24f2366a538972c5520f524663ad86 | |
parent | d88ab3545c27cd674f5fb8bff5fb64a9eeed590f (diff) |
Add latest changes from gitlab-org/gitlab@master
81 files changed, 457 insertions, 763 deletions
diff --git a/.gitlab/issue_templates/Feature Flag Cleanup.md b/.gitlab/issue_templates/Feature Flag Cleanup.md index 7e0462a5cba..d32b0c874d4 100644 --- a/.gitlab/issue_templates/Feature Flag Cleanup.md +++ b/.gitlab/issue_templates/Feature Flag Cleanup.md @@ -49,4 +49,3 @@ Are there any other stages or teams involved that need to be kept in the loop? /label ~"feature flag" ~"type::feature" ~"feature::addition" -/assign DRI diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml index d8d79d9fa90..7ac7915b325 100644 --- a/.rubocop_todo/layout/argument_alignment.yml +++ b/.rubocop_todo/layout/argument_alignment.yml @@ -475,7 +475,6 @@ Layout/ArgumentAlignment: - 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb' - 'ee/spec/services/ee/protected_branches/create_service_spec.rb' - 'ee/spec/services/epics/update_service_spec.rb' - - 'ee/spec/services/geo/file_download_service_spec.rb' - 'ee/spec/services/geo/file_registry_removal_service_spec.rb' - 'ee/spec/services/geo/repository_verification_primary_service_spec.rb' - 'ee/spec/services/groups/recent_merge_requests_count_service_spec.rb' diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index 345bf1bff92..a9200ee9fba 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -2887,7 +2887,6 @@ Layout/LineLength: - 'ee/spec/services/geo/blob_download_service_spec.rb' - 'ee/spec/services/geo/blob_upload_service_spec.rb' - 'ee/spec/services/geo/container_repository_sync_spec.rb' - - 'ee/spec/services/geo/file_download_service_spec.rb' - 'ee/spec/services/geo/framework_repository_sync_service_spec.rb' - 'ee/spec/services/geo/hashed_storage_attachments_event_store_spec.rb' - 'ee/spec/services/geo/hashed_storage_migration_service_spec.rb' @@ -3131,7 +3130,6 @@ Layout/LineLength: - 'ee/spec/workers/geo/batch/project_registry_scheduler_worker_spec.rb' - 'ee/spec/workers/geo/container_repository_sync_dispatch_worker_spec.rb' - 'ee/spec/workers/geo/destroy_worker_spec.rb' - - 'ee/spec/workers/geo/file_download_dispatch_worker_spec.rb' - 'ee/spec/workers/geo/project_sync_worker_spec.rb' - 'ee/spec/workers/geo/prune_event_log_worker_spec.rb' - 'ee/spec/workers/geo/registry_sync_worker_spec.rb' diff --git a/.rubocop_todo/rspec/any_instance_of.yml b/.rubocop_todo/rspec/any_instance_of.yml index 00f4a3982e8..32bf03b18ad 100644 --- a/.rubocop_todo/rspec/any_instance_of.yml +++ b/.rubocop_todo/rspec/any_instance_of.yml @@ -122,7 +122,6 @@ RSpec/AnyInstanceOf: - ee/spec/workers/concerns/elastic/indexing_control_spec.rb - ee/spec/workers/elastic_commit_indexer_worker_spec.rb - ee/spec/workers/geo/design_repository_shard_sync_worker_spec.rb - - ee/spec/workers/geo/file_download_dispatch_worker_spec.rb - ee/spec/workers/geo/registry_sync_worker_spec.rb - ee/spec/workers/geo/repository_cleanup_worker_spec.rb - ee/spec/workers/geo/repository_shard_sync_worker_spec.rb diff --git a/.rubocop_todo/rspec/verified_doubles.yml b/.rubocop_todo/rspec/verified_doubles.yml index 2a4ee9f31f1..26b82a3f473 100644 --- a/.rubocop_todo/rspec/verified_doubles.yml +++ b/.rubocop_todo/rspec/verified_doubles.yml @@ -178,7 +178,6 @@ RSpec/VerifiedDoubles: - ee/spec/services/ee/service_ping/permit_data_categories_service_spec.rb - ee/spec/services/ee/service_ping/service_ping_settings_spec.rb - ee/spec/services/geo/blob_download_service_spec.rb - - ee/spec/services/geo/file_download_service_spec.rb - ee/spec/services/geo/graphql_request_service_spec.rb - ee/spec/services/geo/node_status_request_service_spec.rb - ee/spec/services/geo/replication_toggle_request_service_spec.rb @@ -225,8 +224,6 @@ RSpec/VerifiedDoubles: - ee/spec/workers/geo/design_repository_sync_worker_spec.rb - ee/spec/workers/geo/destroy_worker_spec.rb - ee/spec/workers/geo/event_worker_spec.rb - - ee/spec/workers/geo/file_download_dispatch_worker_spec.rb - - ee/spec/workers/geo/file_download_worker_spec.rb - ee/spec/workers/geo/metrics_update_worker_spec.rb - ee/spec/workers/geo/prune_event_log_worker_spec.rb - ee/spec/workers/geo/registry_sync_worker_spec.rb @@ -544,4 +544,4 @@ gem 'ipaddress', '~> 0.8.3' gem 'parslet', '~> 1.8' -gem 'ipynbdiff', '0.4.6' +gem 'ipynbdiff', '0.4.7' diff --git a/Gemfile.lock b/Gemfile.lock index 3344feae54b..87bb6167b65 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -665,7 +665,7 @@ GEM invisible_captcha (1.1.0) rails (>= 4.2) ipaddress (0.8.3) - ipynbdiff (0.4.6) + ipynbdiff (0.4.7) diffy (~> 3.3) json (~> 2.5, >= 2.5.1) jaeger-client (1.1.0) @@ -1543,7 +1543,7 @@ DEPENDENCIES icalendar invisible_captcha (~> 1.1.0) ipaddress (~> 0.8.3) - ipynbdiff (= 0.4.6) + ipynbdiff (= 0.4.7) jira-ruby (~> 2.1.4) js_regex (~> 3.7) json (~> 2.5.1) diff --git a/app/assets/javascripts/blob/file_template_selector.js b/app/assets/javascripts/blob/file_template_selector.js index e02217d0deb..4f970d657c2 100644 --- a/app/assets/javascripts/blob/file_template_selector.js +++ b/app/assets/javascripts/blob/file_template_selector.js @@ -1,10 +1,14 @@ import $ from 'jquery'; +import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js'; export default class FileTemplateSelector { constructor(mediator) { this.mediator = mediator; this.$dropdown = null; this.$wrapper = null; + + this.dropdown = null; + this.wrapper = null; } init() { @@ -12,18 +16,21 @@ export default class FileTemplateSelector { this.$dropdown = $(cfg.dropdown); this.$wrapper = $(cfg.wrapper); - this.$dropdownIcon = this.$wrapper.find('.dropdown-menu-toggle-icon'); - this.$loadingIcon = $( - '<div class="gl-spinner gl-spinner-orange gl-spinner-sm gl-absolute gl-top-3 gl-right-3 gl-display-none"></div>', - ).insertAfter(this.$dropdownIcon); - this.$dropdownToggleText = this.$wrapper.find('.dropdown-toggle-text'); + + this.dropdown = document.querySelector(cfg.dropdown); + this.wrapper = document.querySelector(cfg.wrapper); + + this.dropdownIcon = this.wrapper.querySelector('.dropdown-menu-toggle-icon'); + this.loadingIcon = loadingIconForLegacyJS({ classes: ['gl-display-none'] }); + this.dropdown.appendChild(this.loadingIcon); + this.dropdownToggleText = this.wrapper.querySelector('.dropdown-toggle-text'); this.initDropdown(); this.selectInitialTemplate(); } selectInitialTemplate() { - const template = this.$dropdown.data('selected'); + const template = this.dropdown.dataset.selected; if (!template) { return; @@ -33,11 +40,11 @@ export default class FileTemplateSelector { } show() { - if (this.$dropdown === null) { + if (this.dropdown === null) { this.init(); } - this.$wrapper.removeClass('hidden'); + this.wrapper.classList.remove('hidden'); /** * We set the focus on the dropdown that was just shown. This is done so that, after selecting @@ -49,36 +56,36 @@ export default class FileTemplateSelector { * closed anymore. */ setTimeout(() => { - this.$dropdown.focus(); + this.dropdown.focus(); }, 0); } hide() { - if (this.$dropdown !== null) { - this.$wrapper.addClass('hidden'); + if (this.dropdown !== null) { + this.wrapper.classList.add('hidden'); } } isHidden() { - return !this.$wrapper || this.$wrapper.hasClass('hidden'); + return !this.wrapper || this.wrapper.classList.contains('hidden'); } getToggleText() { - return this.$dropdownToggleText.text(); + return this.dropdownToggleText.textContent; } setToggleText(text) { - this.$dropdownToggleText.text(text); + this.dropdownToggleText.textContent = text; } renderLoading() { - this.$loadingIcon.removeClass('gl-display-none'); - this.$dropdownIcon.addClass('gl-display-none'); + this.loadingIcon.classList.remove('gl-display-none'); + this.dropdownIcon.classList.add('gl-display-none'); } renderLoaded() { - this.$loadingIcon.addClass('gl-display-none'); - this.$dropdownIcon.removeClass('gl-display-none'); + this.loadingIcon.classList.add('gl-display-none'); + this.dropdownIcon.classList.remove('gl-display-none'); } reportSelection(options) { diff --git a/app/assets/javascripts/issuable/components/status_box.vue b/app/assets/javascripts/issuable/components/status_box.vue index cd4f98ba505..498dc859186 100644 --- a/app/assets/javascripts/issuable/components/status_box.vue +++ b/app/assets/javascripts/issuable/components/status_box.vue @@ -1,6 +1,7 @@ <script> import { GlBadge, GlIcon } from '@gitlab/ui'; import Vue from 'vue'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { fetchPolicies } from '~/lib/graphql'; import { __ } from '~/locale'; import { IssuableType } from '~/issues/constants'; @@ -43,6 +44,7 @@ export default { GlBadge, GlIcon, }, + mixins: [glFeatureFlagMixin()], inject: { query: { default: null }, projectPath: { default: null }, @@ -69,7 +71,13 @@ export default { }, computed: { badgeClass() { - return CLASSES[this.state]; + return [ + CLASSES[this.state], + { + 'gl-vertical-align-bottom': + this.issuableType === IssuableType.MergeRequest && this.glFeatures.updatedMrHeader, + }, + ]; }, badgeVariant() { if (this.state === IssuableStates.Opened) { diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue index f1f8022845e..9f76d4cec50 100644 --- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue +++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue @@ -30,7 +30,11 @@ export default { GlLoadingIcon, GlTooltip, }, - actionSizeClasses: ['gl-h-7 gl-w-7'], + styles: { + actionSizeClasses: ['gl-h-7 gl-w-7'], + flatLeftBorder: ['gl-rounded-bottom-left-none!', 'gl-rounded-top-left-none!'], + flatRightBorder: ['gl-rounded-bottom-right-none!', 'gl-rounded-top-right-none!'], + }, mixins: [glFeatureFlagMixin()], props: { columnTitle: { @@ -80,14 +84,18 @@ export default { return {}; }, - buttonBorderClass() { - return this.isUpstream ? 'gl-border-r-1!' : 'gl-border-l-1!'; + buttonBorderClasses() { + return this.isUpstream + ? ['gl-border-r-0!', ...this.$options.styles.flatRightBorder] + : ['gl-border-l-0!', ...this.$options.styles.flatLeftBorder]; }, buttonId() { return `js-linked-pipeline-${this.pipeline.id}`; }, - cardSpacingClass() { - return this.isDownstream ? 'gl-pr-0' : ''; + cardClasses() { + return this.isDownstream + ? this.$options.styles.flatRightBorder + : this.$options.styles.flatLeftBorder; }, expandedIcon() { if (this.isUpstream) { @@ -213,7 +221,7 @@ export default { <template> <div ref="linkedPipeline" - class="gl-h-full gl-display-flex! gl-border-solid gl-border-gray-100 gl-border-1" + class="gl-h-full gl-display-flex!" :class="flexDirection" data-qa-selector="linked_pipeline_container" @mouseover="onDownstreamHovered" @@ -222,21 +230,21 @@ export default { <gl-tooltip v-if="showCardTooltip" :target="() => $refs.linkedPipeline"> {{ cardTooltipText }} </gl-tooltip> - <div class="gl-w-full gl-bg-white gl-p-3" :class="cardSpacingClass"> - <div class="gl-display-flex gl-pr-3"> - <ci-status - v-if="!pipelineIsLoading" - :status="pipelineStatus" - :size="24" - css-classes="gl-top-0 gl-pr-2" - /> + <div class="gl-bg-white gl-border gl-p-3 gl-rounded-lg gl-w-full" :class="cardClasses"> + <div class="gl-display-flex gl-gap-x-3"> + <ci-status v-if="!pipelineIsLoading" :status="pipelineStatus" :size="24" css-classes="" /> <div v-else class="gl-pr-3"><gl-loading-icon size="sm" inline /></div> - <div class="gl-display-flex gl-flex-direction-column gl-downstream-pipeline-job-width"> + <div + class="gl-display-flex gl-downstream-pipeline-job-width gl-flex-direction-column gl-line-height-normal" + > <span class="gl-text-truncate" data-testid="downstream-title"> {{ downstreamTitle }} </span> <div class="gl-text-truncate"> - <gl-link class="gl-text-blue-500!" :href="pipeline.path" data-testid="pipelineLink" + <gl-link + class="gl-text-blue-500! gl-font-sm" + :href="pipeline.path" + data-testid="pipelineLink" >#{{ pipeline.id }}</gl-link > </div> @@ -248,13 +256,13 @@ export default { :loading="isActionLoading" :icon="action.icon" class="gl-rounded-full!" - :class="$options.actionSizeClasses" + :class="$options.styles.actionSizeClasses" :aria-label="action.ariaLabel" @click="action.method" @mouseover="setActionTooltip(true)" @mouseout="setActionTooltip(false)" /> - <div v-else :class="$options.actionSizeClasses"></div> + <div v-else :class="$options.styles.actionSizeClasses"></div> </div> <div class="gl-pt-2"> <gl-badge size="sm" variant="info" data-testid="downstream-pipeline-label"> @@ -265,8 +273,8 @@ export default { <div class="gl-display-flex"> <gl-button :id="buttonId" - class="gl-shadow-none! gl-rounded-0!" - :class="`js-pipeline-expand-${pipeline.id} ${buttonBorderClass}`" + class="gl-border! gl-shadow-none! gl-rounded-lg!" + :class="[`js-pipeline-expand-${pipeline.id}`, buttonBorderClasses]" :icon="expandedIcon" :aria-label="__('Expand pipeline')" data-testid="expand-pipeline-button" diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue index 0595f2ec245..b06c2f15042 100644 --- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue +++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue @@ -66,14 +66,13 @@ export default { columnClass() { const positionValues = { right: 'gl-ml-6', - left: 'gl-mr-6', + left: 'gl-mx-6', }; + return `graph-position-${this.graphPosition} ${positionValues[this.graphPosition]}`; }, computedTitleClasses() { - const positionalClasses = this.isUpstream - ? ['gl-w-full', 'gl-text-right', 'gl-linked-pipeline-padding'] - : []; + const positionalClasses = this.isUpstream ? ['gl-w-full', 'gl-linked-pipeline-padding'] : []; return [...this.$options.titleClasses, ...positionalClasses]; }, @@ -202,7 +201,7 @@ export default { <li v-for="pipeline in linkedPipelines" :key="pipeline.id" - class="gl-display-flex gl-mb-4" + class="gl-display-flex gl-mb-3" :class="{ 'gl-flex-direction-row-reverse': isUpstream }" > <linked-pipeline diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue index b0502202b0e..699d1bebea1 100644 --- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue +++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue @@ -1,7 +1,9 @@ <script> import { GlIcon, GlTooltipDirective } from '@gitlab/ui'; -import { mapGetters } from 'vuex'; -import { __ } from '~/locale'; +import { mapGetters, mapActions } from 'vuex'; +import { __, sprintf } from '~/locale'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import createFlash from '~/flash'; import eventHub from '~/sidebar/event_hub'; import editForm from './edit_form.vue'; @@ -23,11 +25,11 @@ export default { editForm, GlIcon, }, - directives: { GlTooltip: GlTooltipDirective, }, - + mixins: [glFeatureFlagMixin()], + inject: ['fullPath'], props: { isEditable: { required: true, @@ -41,6 +43,9 @@ export default { }, computed: { ...mapGetters(['getNoteableData']), + isMergeRequest() { + return this.getNoteableData.targetType === 'merge_request' && this.glFeatures.movedMrSidebar; + }, issuableDisplayName() { const isInIssuePage = this.getNoteableData.targetType === this.$options.issue; return isInIssuePage ? __('issue') : __('merge request'); @@ -66,17 +71,49 @@ export default { }, methods: { + ...mapActions(['updateLockedAttribute']), toggleForm() { if (this.isEditable) { this.isLockDialogOpen = !this.isLockDialogOpen; } }, + toggleLocked() { + this.isLoading = true; + + this.updateLockedAttribute({ + locked: !this.isLocked, + fullPath: this.fullPath, + }) + .catch(() => { + const flashMessage = __( + 'Something went wrong trying to change the locked state of this %{issuableDisplayName}', + ); + createFlash({ + message: sprintf(flashMessage, { issuableDisplayName: this.issuableDisplayName }), + }); + }) + .finally(() => { + this.isLoading = false; + }); + }, }, }; </script> <template> - <div class="block issuable-sidebar-item lock"> + <li v-if="isMergeRequest" class="gl-new-dropdown-item"> + <button type="button" class="dropdown-item" @click="toggleLocked"> + <span class="gl-new-dropdown-item-text-wrapper"> + <template v-if="isLocked"> + {{ __('Unlock merge request') }} + </template> + <template v-else> + {{ __('Lock merge request') }} + </template> + </span> + </button> + </li> + <div v-else class="block issuable-sidebar-item lock"> <div v-gl-tooltip.left.viewport="{ title: tooltipLabel }" class="sidebar-collapsed-icon" diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js index d76782b0cec..351bb50d941 100644 --- a/app/assets/javascripts/sidebar/mount_sidebar.js +++ b/app/assets/javascripts/sidebar/mount_sidebar.js @@ -431,10 +431,7 @@ function mountLockComponent(store) { return; } - const { fullPath } = getSidebarOptions(); - - const dataNode = document.getElementById('js-lock-issue-data'); - const initialData = JSON.parse(dataNode.innerHTML); + const { fullPath, editable } = getSidebarOptions(); // eslint-disable-next-line no-new new Vue({ @@ -447,7 +444,7 @@ function mountLockComponent(store) { render: (createElement) => createElement(IssuableLockForm, { props: { - isEditable: initialData.is_editable, + isEditable: editable, }, }), }); diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue index bbe15f659f5..0bc17de638b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue @@ -254,7 +254,7 @@ export default { class="media-body gl-display-flex gl-flex-direction-row! gl-align-self-center" data-testid="widget-extension-top-level" > - <div class="gl-flex-grow-1"> + <div class="gl-flex-grow-1" data-testid="widget-extension-top-level-summary"> <template v-if="isLoadingSummary">{{ widgetLoadingText }}</template> <template v-else-if="hasFetchError">{{ widgetErrorText }}</template> <div v-else> diff --git a/app/assets/stylesheets/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss index cbb6d68bf35..e6afc70acbb 100644 --- a/app/assets/stylesheets/page_bundles/pipeline.scss +++ b/app/assets/stylesheets/page_bundles/pipeline.scss @@ -139,7 +139,7 @@ } .gl-downstream-pipeline-job-width { - width: 170px; + width: 8rem; } .gl-linked-pipeline-padding { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 5b8366e91bf..4093ef087dc 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -125,6 +125,7 @@ background-color: $white; z-index: 200; overflow: hidden; + } .right-sidebar { @@ -196,7 +197,6 @@ .issuable-sidebar-header { @include clearfix; padding: $gl-padding 0; - border-bottom: 1px solid $border-gray-normal; // This prevents the mess when resizing the sidebar // of elements repositioning themselves.. width: $gutter-inner-width; diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index c1c4a110aae..927b50245a4 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -9,7 +9,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController after_action :verify_known_sign_in - protect_from_forgery except: [:saml, :cas3, :failure] + AuthHelper.saml_providers, with: :exception, prepend: true + protect_from_forgery except: [:cas3, :failure] + AuthHelper.saml_providers, with: :exception, prepend: true feature_category :authentication_and_authorization diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb index e61d357ce4e..c5778ba15f2 100644 --- a/app/controllers/projects/prometheus/metrics_controller.rb +++ b/app/controllers/projects/prometheus/metrics_controller.rb @@ -74,9 +74,9 @@ module Projects end def update - @metric = update_metrics_service(prometheus_metric).execute + @metric = prometheus_metric - if @metric.persisted? + if @metric.update(metrics_params) redirect_to edit_project_integration_path(project, ::Integrations::Prometheus), notice: _('Metric was successfully updated.') else diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index 6ac4a12bcd5..07152133402 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -91,7 +91,9 @@ module AuthHelper end def saml_providers - auth_providers.select { |provider| auth_strategy_class(provider) == 'OmniAuth::Strategies::SAML' } + auth_providers.select do |provider| + provider == :saml || auth_strategy_class(provider) == 'OmniAuth::Strategies::SAML' + end end def auth_strategy_class(provider) diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb index 5a30f55595b..427034edb79 100644 --- a/app/models/integrations/prometheus.rb +++ b/app/models/integrations/prometheus.rb @@ -27,8 +27,6 @@ module Integrations after_commit :track_events - after_create_commit :create_default_alerts - scope :preload_project, -> { preload(:project) } def show_active_box? @@ -168,12 +166,6 @@ module Integrations manual_configuration_changed? && !manual_configuration? end - def create_default_alerts - return unless project_id - - ::Prometheus::CreateDefaultAlertsWorker.perform_async(project_id) - end - def behind_iap? manual_configuration? && google_iap_audience_client_id.present? && google_iap_service_account_json.present? end diff --git a/app/services/projects/prometheus/metrics/base_service.rb b/app/services/projects/prometheus/metrics/base_service.rb index be1783dde70..15247d45776 100644 --- a/app/services/projects/prometheus/metrics/base_service.rb +++ b/app/services/projects/prometheus/metrics/base_service.rb @@ -8,40 +8,12 @@ module Projects def initialize(metric, params = {}) @metric = metric - @project = metric.project @params = params.dup end protected - attr_reader :metric, :project, :params - - def application - alert.environment.cluster_prometheus_adapter - end - - def schedule_alert_update - return unless alert - return unless alert.environment - - ::Clusters::Applications::ScheduleUpdateService.new( - alert.environment.cluster_prometheus_adapter, project).execute - end - - def alert - strong_memoize(:alert) { find_alert(metric) } - end - - def find_alert(metric) - Projects::Prometheus::AlertsFinder - .new(project: project, metric: metric) - .execute - .first - end - - def has_alert? - alert.present? - end + attr_reader :metric, :params end end end diff --git a/app/services/projects/prometheus/metrics/destroy_service.rb b/app/services/projects/prometheus/metrics/destroy_service.rb index 6a46eb5516c..d85499dc4ae 100644 --- a/app/services/projects/prometheus/metrics/destroy_service.rb +++ b/app/services/projects/prometheus/metrics/destroy_service.rb @@ -5,7 +5,6 @@ module Projects module Metrics class DestroyService < Metrics::BaseService def execute - schedule_alert_update if has_alert? metric.destroy end end diff --git a/app/services/projects/prometheus/metrics/update_service.rb b/app/services/projects/prometheus/metrics/update_service.rb deleted file mode 100644 index 9b51f4ab47d..00000000000 --- a/app/services/projects/prometheus/metrics/update_service.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module Projects - module Prometheus - module Metrics - class UpdateService < Metrics::BaseService - def execute - metric.update!(params) - schedule_alert_update if requires_alert_update? - metric - end - - private - - def requires_alert_update? - has_alert? && (changing_title? || changing_query?) - end - - def changing_title? - metric.previous_changes.include?(:title) - end - - def changing_query? - metric.previous_changes.include?(:query) - end - end - end - end -end diff --git a/app/services/prometheus/create_default_alerts_service.rb b/app/services/prometheus/create_default_alerts_service.rb deleted file mode 100644 index eb8a9d45658..00000000000 --- a/app/services/prometheus/create_default_alerts_service.rb +++ /dev/null @@ -1,105 +0,0 @@ -# frozen_string_literal: true - -# DEPRECATED: To be removed as part of https://gitlab.com/groups/gitlab-org/-/epics/5877 -module Prometheus - class CreateDefaultAlertsService < BaseService - include Gitlab::Utils::StrongMemoize - - attr_reader :project - - DEFAULT_ALERTS = [ - { - identifier: 'response_metrics_nginx_ingress_16_http_error_rate', - operator: 'gt', - threshold: 0.1 - }, - { - identifier: 'response_metrics_nginx_ingress_http_error_rate', - operator: 'gt', - threshold: 0.1 - }, - { - identifier: 'response_metrics_nginx_http_error_percentage', - operator: 'gt', - threshold: 0.1 - } - ].freeze - - def initialize(project:) - @project = project - end - - def execute - return ServiceResponse.error(message: 'Invalid project') unless project - return ServiceResponse.error(message: 'Invalid environment') unless environment - - create_alerts - schedule_prometheus_update - - ServiceResponse.success - end - - private - - def create_alerts - DEFAULT_ALERTS.each do |alert_hash| - identifier = alert_hash[:identifier] - next if alerts_by_identifier(environment).key?(identifier) - - metric = metrics_by_identifier[identifier] - next unless metric - - create_alert(alert: alert_hash, metric: metric) - end - end - - def schedule_prometheus_update - return unless prometheus_adapter - - ::Clusters::Applications::ScheduleUpdateService.new(prometheus_adapter, project).execute - end - - def prometheus_adapter - environment.cluster_prometheus_adapter - end - - def metrics_by_identifier - strong_memoize(:metrics_by_identifier) do - metric_identifiers = DEFAULT_ALERTS.map { |alert| alert[:identifier] } - - PrometheusMetricsFinder - .new(identifier: metric_identifiers, common: true) - .execute - .index_by(&:identifier) - end - end - - def alerts_by_identifier(environment) - strong_memoize(:alerts_by_identifier) do - Projects::Prometheus::AlertsFinder - .new(project: project, metric: metrics_by_identifier.values, environment: environment) - .execute - .index_by { |alert| alert.prometheus_metric.identifier } - end - end - - def environment - strong_memoize(:environment) do - Environments::EnvironmentsFinder.new(project, nil, name: 'production').execute.first || - project.environments.first - end - end - - def create_alert(alert:, metric:) - PrometheusAlert.create!( - project: project, - prometheus_metric: metric, - environment: environment, - threshold: alert[:threshold], - operator: alert[:operator] - ) - rescue ActiveRecord::RecordNotUnique - # Ignore duplicate creations although it unlikely to happen - end - end -end diff --git a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml index d4e8893407c..282faf7714e 100644 --- a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml +++ b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml @@ -33,12 +33,14 @@ = _('Reopen') = display_issuable_type + - if current_user && moved_mr_sidebar_enabled? + %li.gl-new-dropdown-divider + %hr.dropdown-divider + %li.gl-new-dropdown-item.js-sidebar-subscriptions-entry-point - unless issuable_author_is_current_user(@merge_request) %li.gl-new-dropdown-item = link_to new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'dropdown-item' do .gl-new-dropdown-item-text-wrapper = _('Report abuse') - - if current_user && moved_mr_sidebar_enabled? - %li.gl-new-dropdown-divider - %hr.dropdown-divider - %li.gl-new-dropdown-item.js-sidebar-subscriptions-entry-point + - if moved_mr_sidebar_enabled? + %li.gl-new-dropdown-item#js-lock-entry-point diff --git a/app/views/projects/merge_requests/_mr_box.html.haml b/app/views/projects/merge_requests/_mr_box.html.haml index 1ccb8dff7e7..e16631b4943 100644 --- a/app/views/projects/merge_requests/_mr_box.html.haml +++ b/app/views/projects/merge_requests/_mr_box.html.haml @@ -1,8 +1,7 @@ .detail-page-description.py-2 - if Feature.enabled?(:updated_mr_header, @project) = render 'shared/issuable/status_box', issuable: @merge_request - .gl-display-inline.gl-vertical-align-top - = merge_request_header(@project, @merge_request) + = merge_request_header(@project, @merge_request) - else %h2.title.mb-0{ data: { qa_selector: 'title_content' } } = markdown_field(@merge_request, :title) diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 4317c77eb89..feffc7eb011 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -8,18 +8,25 @@ - add_page_startup_api_call "#{issuable_sidebar[:issuable_json_path]}?serializer=sidebar_extras" - reviewers = local_assigns.fetch(:reviewers, nil) - in_group_context_with_iterations = @project.group.present? && issuable_sidebar[:supports_iterations] -- moved_sidebar_enabled = moved_mr_sidebar_enabled? && issuable_type === 'merge_request' +- is_merge_request = issuable_type === 'merge_request' +- moved_sidebar_enabled = moved_mr_sidebar_enabled? && is_merge_request %aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class} #{'right-sidebar-merge-requests' if moved_sidebar_enabled}", 'aria-live' => 'polite', 'aria-label': issuable_type } .issuable-sidebar{ class: "#{'is-merge-request' if moved_sidebar_enabled}" } - .issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end' if moved_sidebar_enabled}" } - %a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", class: "#{'gl-display-block gl-md-display-none!' if moved_sidebar_enabled}", href: "#", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } } + .issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end gl-md-display-none!' if moved_sidebar_enabled}" } + %a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", class: "#{'gl-display-block' if moved_sidebar_enabled}", href: "#", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } } = sidebar_gutter_toggle_icon - - if signed_in + - if signed_in && !moved_sidebar_enabled .js-issuable-todo{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } } = form_for issuable_type, url: issuable_sidebar[:issuable_json_path], remote: true, html: { class: 'issuable-context-form inline-update js-issuable-update' } do |f| - .block.assignee.qa-assignee-block + - if signed_in && moved_sidebar_enabled + .block.to-do + .title.hide-collapsed.gl-font-weight-bold.gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mt-2{ class: 'gl-mb-0!' } + = _('To-Do') + .js-issuable-todo{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } } + + .block.assignee.qa-assignee-block{ class: "#{'gl-mt-3' if !signed_in && moved_sidebar_enabled}" } = render "shared/issuable/sidebar_assignees", issuable_sidebar: issuable_sidebar, assignees: assignees, signed_in: signed_in - if reviewers @@ -73,12 +80,10 @@ = render_if_exists 'shared/issuable/sidebar_cve_id_request', issuable_sidebar: issuable_sidebar - -# haml-lint:disable InlineJavaScript - %script#js-lock-issue-data{ type: "application/json" }= { is_locked: !!issuable_sidebar[:discussion_locked], is_editable: can_edit_issuable }.to_json.html_safe - #js-lock-entry-point - - - if signed_in && !moved_sidebar_enabled - .js-sidebar-subscriptions-entry-point + - if !moved_sidebar_enabled + #js-lock-entry-point + - if signed_in + .js-sidebar-subscriptions-entry-point .js-sidebar-participants-entry-point diff --git a/app/views/shared/issuable/_status_box.html.haml b/app/views/shared/issuable/_status_box.html.haml index fd7e720cf1e..4fda1f11545 100644 --- a/app/views/shared/issuable/_status_box.html.haml +++ b/app/views/shared/issuable/_status_box.html.haml @@ -2,7 +2,8 @@ - badge_icon = state_name_with_icon(issuable)[1] - badge_variant = issuable.open? ? :success : issuable.merged? ? :info : :danger - badge_status_class = issuable.open? ? 'issuable-status-badge-open' : issuable.merged? ? 'issuable-status-badge-merged' : 'issuable-status-badge-closed' -- badge_classes = "js-mr-status-box issuable-status-badge gl-mr-3 #{badge_status_class}" +- updated_mr_header_enabled = Feature.enabled?(:updated_mr_header, @project) && issuable.is_a?(MergeRequest) +- badge_classes = "js-mr-status-box issuable-status-badge gl-mr-3 #{badge_status_class} #{'gl-vertical-align-bottom' if updated_mr_header_enabled}" = gl_badge_tag({ variant: badge_variant, icon: badge_icon, icon_classes: 'gl-mr-0!' }, { class: badge_classes, data: { project_path: issuable.project.path_with_namespace, iid: issuable.iid, issuable_type: 'merge_request', state: issuable.state } }) do %span.gl-display-none.gl-sm-display-block.gl-ml-2 diff --git a/app/workers/concerns/reenqueuer.rb b/app/workers/concerns/reenqueuer.rb index 641ca691868..9c0f8f94a24 100644 --- a/app/workers/concerns/reenqueuer.rb +++ b/app/workers/concerns/reenqueuer.rb @@ -41,6 +41,8 @@ module Reenqueuer end def perform(*args) + set_custom_lease_key(*args) if self.respond_to?(:set_custom_lease_key) + try_obtain_lease do reenqueue(*args) do ensure_minimum_duration(minimum_duration) do diff --git a/app/workers/prometheus/create_default_alerts_worker.rb b/app/workers/prometheus/create_default_alerts_worker.rb index 94ac02c4c04..1a0fe7e8d56 100644 --- a/app/workers/prometheus/create_default_alerts_worker.rb +++ b/app/workers/prometheus/create_default_alerts_worker.rb @@ -13,19 +13,7 @@ module Prometheus idempotent! def perform(project_id) - project = Project.find_by_id(project_id) - - return unless project - - result = ::Prometheus::CreateDefaultAlertsService.new(project: project).execute - - log_info(result.message) if result.error? - end - - private - - def log_info(message) - logger.info(structured_payload(message: message)) + # No-op Will be removed in https://gitlab.com/gitlab-org/gitlab/-/issues/360756 end end end diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index eba67ffa205..54a92f5b8b4 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -582,11 +582,6 @@ production: &base geo_secondary_registry_consistency_worker: cron: "* * * * *" - # GitLab Geo file download dispatch worker - # NOTE: This will only take effect if Geo is enabled (secondary nodes only) - geo_file_download_dispatch_worker: - cron: "*/1 * * * *" - # GitLab Geo registry sync worker (for backfilling) # NOTE: This will only take effect if Geo is enabled (secondary nodes only) geo_registry_sync_worker: diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 5b15b119b3a..05d480f267e 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -664,9 +664,6 @@ Gitlab.ee do Settings.cron_jobs['geo_secondary_usage_data_cron_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['geo_secondary_usage_data_cron_worker']['cron'] ||= '0 0 * * 0' Settings.cron_jobs['geo_secondary_usage_data_cron_worker']['job_class'] ||= 'Geo::SecondaryUsageDataCronWorker' - Settings.cron_jobs['geo_file_download_dispatch_worker'] ||= Settingslogic.new({}) - Settings.cron_jobs['geo_file_download_dispatch_worker']['cron'] ||= '*/1 * * * *' - Settings.cron_jobs['geo_file_download_dispatch_worker']['job_class'] ||= 'Geo::FileDownloadDispatchWorker' Settings.cron_jobs['geo_registry_sync_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['geo_registry_sync_worker']['cron'] ||= '*/1 * * * *' Settings.cron_jobs['geo_registry_sync_worker']['job_class'] ||= 'Geo::RegistrySyncWorker' diff --git a/data/removals/14_0/removal_enablement_pg11.yml b/data/removals/14_0/removal_enablement_pg11.yml index 6f9c7718268..d409a1bc9d3 100644 --- a/data/removals/14_0/removal_enablement_pg11.yml +++ b/data/removals/14_0/removal_enablement_pg11.yml @@ -4,6 +4,6 @@ reporter: joshlambert breaking_change: true body: | - PostgreSQL 12 will be the minimum required version in GitLab 14.0. It offers [significant improvements](https://www.postgresql.org/about/news/postgresql-12-released-1976/) to indexing, partitioning, and general performance benefits. + GitLab 14.0 requires PostgreSQL 12 or later. It offers [significant improvements](https://www.postgresql.org/about/news/postgresql-12-released-1976/) to indexing, partitioning, and general performance benefits. - Starting in GitLab 13.7, all new installations default to version 12. From GitLab 13.8, single-node instances are automatically upgraded as well. If you aren't ready to upgrade, you can [opt out of automatic upgrades](https://docs.gitlab.com/omnibus/settings/database.html#opt-out-of-automatic-postgresql-upgrades). + Starting in GitLab 13.7, all new installations default to PostgreSQL version 12. From GitLab 13.8, single-node instances are automatically upgraded as well. If you aren't ready to upgrade, you can [opt out of automatic upgrades](https://docs.gitlab.com/omnibus/settings/database.html#opt-out-of-automatic-postgresql-upgrades). diff --git a/db/docs/ci_build_needs.yml b/db/docs/ci_build_needs.yml index 976d834c884..f9367124ed2 100644 --- a/db/docs/ci_build_needs.yml +++ b/db/docs/ci_build_needs.yml @@ -4,6 +4,6 @@ classes: - Ci::BuildNeed feature_categories: - pipeline_authoring -description: TODO -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/e7ee84aad4237eaa16f2aba75b4d2c7860625c9d +description: Dependencies for a specific CI/CD job. +introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31328 milestone: '12.2' diff --git a/db/docs/geo_job_artifact_deleted_events.yml b/db/docs/geo_job_artifact_deleted_events.yml deleted file mode 100644 index d58b0b83924..00000000000 --- a/db/docs/geo_job_artifact_deleted_events.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -table_name: geo_job_artifact_deleted_events -classes: -- Geo::JobArtifactDeletedEvent -feature_categories: -- geo_replication -description: TODO -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3935 -milestone: '10.4' diff --git a/db/post_migrate/20220415124802_remove_job_artifact_deprecated_geo_fields.rb b/db/post_migrate/20220415124802_remove_job_artifact_deprecated_geo_fields.rb new file mode 100644 index 00000000000..65432ba3ce1 --- /dev/null +++ b/db/post_migrate/20220415124802_remove_job_artifact_deprecated_geo_fields.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class RemoveJobArtifactDeprecatedGeoFields < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + def up + with_lock_retries do + remove_column :geo_event_log, :job_artifact_deleted_event_id, :bigint + end + end + + def down + with_lock_retries do + unless column_exists?(:geo_event_log, :job_artifact_deleted_event_id) + add_column(:geo_event_log, :job_artifact_deleted_event_id, :bigint) + end + end + + add_concurrent_foreign_key :geo_event_log, :geo_job_artifact_deleted_events, + column: :job_artifact_deleted_event_id, + name: 'fk_176d3fbb5d', + on_delete: :cascade + + add_concurrent_index :geo_event_log, + :job_artifact_deleted_event_id, + name: 'index_geo_event_log_on_job_artifact_deleted_event_id', + where: "(job_artifact_deleted_event_id IS NOT NULL)" + end +end diff --git a/db/post_migrate/20220415124804_remove_job_artifact_deleted_event_table.rb b/db/post_migrate/20220415124804_remove_job_artifact_deleted_event_table.rb new file mode 100644 index 00000000000..05b716f26ab --- /dev/null +++ b/db/post_migrate/20220415124804_remove_job_artifact_deleted_event_table.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class RemoveJobArtifactDeletedEventTable < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + def up + drop_table :geo_job_artifact_deleted_events + end + + def down + create_table :geo_job_artifact_deleted_events, id: :bigserial do |t| + t.bigint :job_artifact_id, null: false, index: true + t.string :file_path, null: false + end + end +end diff --git a/db/schema_migrations/20220415124802 b/db/schema_migrations/20220415124802 new file mode 100644 index 00000000000..3f5c99b675b --- /dev/null +++ b/db/schema_migrations/20220415124802 @@ -0,0 +1 @@ +aaf55d3f4a82789695ce1107d045a6230e111d5058733f72ccf4a1e5563a2636
\ No newline at end of file diff --git a/db/schema_migrations/20220415124804 b/db/schema_migrations/20220415124804 new file mode 100644 index 00000000000..1c325f0fdbc --- /dev/null +++ b/db/schema_migrations/20220415124804 @@ -0,0 +1 @@ +728ce5b9d0986fa55a43841b2a5961f9716b3e2933d1e77e3ac00e30244c6f8e
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 2d052a0a4d0..fa9d9e8f778 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -15181,7 +15181,6 @@ CREATE TABLE geo_event_log ( hashed_storage_migrated_event_id bigint, lfs_object_deleted_event_id bigint, hashed_storage_attachments_event_id bigint, - job_artifact_deleted_event_id bigint, reset_checksum_event_id bigint, cache_invalidation_event_id bigint, container_repository_updated_event_id bigint, @@ -15253,21 +15252,6 @@ CREATE SEQUENCE geo_hashed_storage_migrated_events_id_seq ALTER SEQUENCE geo_hashed_storage_migrated_events_id_seq OWNED BY geo_hashed_storage_migrated_events.id; -CREATE TABLE geo_job_artifact_deleted_events ( - id bigint NOT NULL, - file_path character varying NOT NULL, - job_artifact_id bigint NOT NULL -); - -CREATE SEQUENCE geo_job_artifact_deleted_events_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - -ALTER SEQUENCE geo_job_artifact_deleted_events_id_seq OWNED BY geo_job_artifact_deleted_events.id; - CREATE TABLE geo_lfs_object_deleted_events ( id bigint NOT NULL, lfs_object_id integer NOT NULL, @@ -22742,8 +22726,6 @@ ALTER TABLE ONLY geo_hashed_storage_attachments_events ALTER COLUMN id SET DEFAU ALTER TABLE ONLY geo_hashed_storage_migrated_events ALTER COLUMN id SET DEFAULT nextval('geo_hashed_storage_migrated_events_id_seq'::regclass); -ALTER TABLE ONLY geo_job_artifact_deleted_events ALTER COLUMN id SET DEFAULT nextval('geo_job_artifact_deleted_events_id_seq'::regclass); - ALTER TABLE ONLY geo_lfs_object_deleted_events ALTER COLUMN id SET DEFAULT nextval('geo_lfs_object_deleted_events_id_seq'::regclass); ALTER TABLE ONLY geo_node_namespace_links ALTER COLUMN id SET DEFAULT nextval('geo_node_namespace_links_id_seq'::regclass); @@ -24583,9 +24565,6 @@ ALTER TABLE ONLY geo_hashed_storage_attachments_events ALTER TABLE ONLY geo_hashed_storage_migrated_events ADD CONSTRAINT geo_hashed_storage_migrated_events_pkey PRIMARY KEY (id); -ALTER TABLE ONLY geo_job_artifact_deleted_events - ADD CONSTRAINT geo_job_artifact_deleted_events_pkey PRIMARY KEY (id); - ALTER TABLE ONLY geo_lfs_object_deleted_events ADD CONSTRAINT geo_lfs_object_deleted_events_pkey PRIMARY KEY (id); @@ -27792,8 +27771,6 @@ CREATE INDEX index_geo_event_log_on_hashed_storage_attachments_event_id ON geo_e CREATE INDEX index_geo_event_log_on_hashed_storage_migrated_event_id ON geo_event_log USING btree (hashed_storage_migrated_event_id) WHERE (hashed_storage_migrated_event_id IS NOT NULL); -CREATE INDEX index_geo_event_log_on_job_artifact_deleted_event_id ON geo_event_log USING btree (job_artifact_deleted_event_id) WHERE (job_artifact_deleted_event_id IS NOT NULL); - CREATE INDEX index_geo_event_log_on_lfs_object_deleted_event_id ON geo_event_log USING btree (lfs_object_deleted_event_id) WHERE (lfs_object_deleted_event_id IS NOT NULL); CREATE INDEX index_geo_event_log_on_repositories_changed_event_id ON geo_event_log USING btree (repositories_changed_event_id) WHERE (repositories_changed_event_id IS NOT NULL); @@ -27812,8 +27789,6 @@ CREATE INDEX index_geo_hashed_storage_attachments_events_on_project_id ON geo_ha CREATE INDEX index_geo_hashed_storage_migrated_events_on_project_id ON geo_hashed_storage_migrated_events USING btree (project_id); -CREATE INDEX index_geo_job_artifact_deleted_events_on_job_artifact_id ON geo_job_artifact_deleted_events USING btree (job_artifact_id); - CREATE INDEX index_geo_lfs_object_deleted_events_on_lfs_object_id ON geo_lfs_object_deleted_events USING btree (lfs_object_id); CREATE INDEX index_geo_node_namespace_links_on_geo_node_id ON geo_node_namespace_links USING btree (geo_node_id); @@ -31214,9 +31189,6 @@ ALTER TABLE ONLY protected_branch_push_access_levels ALTER TABLE ONLY internal_ids ADD CONSTRAINT fk_162941d509 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; -ALTER TABLE ONLY geo_event_log - ADD CONSTRAINT fk_176d3fbb5d FOREIGN KEY (job_artifact_deleted_event_id) REFERENCES geo_job_artifact_deleted_events(id) ON DELETE CASCADE; - ALTER TABLE ONLY incident_management_timeline_events ADD CONSTRAINT fk_17a5fafbd4 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE; diff --git a/doc/administration/inactive_project_deletion.md b/doc/administration/inactive_project_deletion.md index a623e01a593..a2d2093c57b 100644 --- a/doc/administration/inactive_project_deletion.md +++ b/doc/administration/inactive_project_deletion.md @@ -11,8 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w FLAG: On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `inactive_projects_deletion`. -On GitLab.com, this feature is not available. -This feature is not ready for production use. +On GitLab.com, this feature is not available. This feature is not ready for production use. Administrators of large GitLab instances can find that over time, projects become inactive and are no longer used. These projects take up unnecessary disk space. With inactive project deletion, you can identify these projects, warn @@ -24,37 +23,35 @@ deleted, the action generates an audit event that it was performed by the first You can configure inactive projects deletion or turn it off using the [Application settings API](../api/settings.md#change-application-settings). -## Inactive project deletion options - The following options are available: -- **Delete inactive projects**: Enable or disable inactive project deletion. -- **Delete inactive projects that exceed**: Minimum size (MB) of inactive projects to be considered for deletion. +- `delete_inactive_projects`: Enable or disable inactive project deletion. +- `inactive_projects_min_size_mb`: Minimum size (MB) of inactive projects to be considered for deletion. Projects smaller in size than this threshold aren't considered inactive. -- **Delete project after**: Minimum duration (months) after which a project is scheduled for deletion if it continues -be inactive. -- **Send warning email**: Minimum duration (months) after which a deletion warning email is sent if a project continues -to be inactive. The warning email is sent to users with the Owner and Maintainer roles of the inactive project. -This duration should be greater than the **Delete project after** duration. +- `inactive_projects_delete_after_months`: Minimum duration (months) after which a project is scheduled for deletion if + it continues be inactive. +- `inactive_projects_send_warning_email_after_months`: Minimum duration (months) after which a deletion warning email is + sent if a project continues to be inactive. The warning email is sent to users with the Owner and Maintainer roles of + the inactive project. This duration should be less than the `inactive_projects_delete_after_months` duration. For example: -- Delete inactive projects: enabled. -- Delete inactive projects that exceed: 50. -- Delete project after: 12. -- Send warning email: 6. +- `delete_inactive_projects` enabled. +- `inactive_projects_min_size_mb` set to `50`. +- `inactive_projects_delete_after_months` set to `12`. +- `inactive_projects_send_warning_email_after_months` set to `6`. In this scenario, when a project's size is: - Less than 50 MB, the project is not considered inactive. - Greater than 50 MB and it is inactive for: - - More than 6 months, a deletion warning is email is sent to users with the Owner and Maintainer role on the project -with the scheduled date of deletion. + - More than 6 months, a deletion warning is email is sent to users with the Owner and Maintainer role on the project + with the scheduled date of deletion. - More than 12 months, the project is scheduled for deletion. ## Determine when a project was last active -There are several ways to view the project's activities and determine when project was last active: +You can view a project's activities and determine when the project was last active in the following ways: 1. Go to the [activity page](../user/project/working_with_projects.md#view-project-activity) for the project and view the date of the latest event. diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md index 1d6e917e147..34481582d8b 100644 --- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md +++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md @@ -1239,12 +1239,6 @@ This content has been converted to a Rake task, see [verify database values can Geo::JobArtifactRegistry.failed ``` -#### Download artifact - -```ruby -Gitlab::Geo::JobArtifactDownloader.new(:job_artifact, <artifact_id>).execute -``` - #### Get a count of the synced artifacts ```ruby diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 8d7ca8a84b1..97ef81b8bfa 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -19555,8 +19555,6 @@ Vulnerability sort values. | <a id="vulnerabilitysortseverity_desc"></a>`severity_desc` | Severity in descending order. | | <a id="vulnerabilitysortstate_asc"></a>`state_asc` | State in ascending order. | | <a id="vulnerabilitysortstate_desc"></a>`state_desc` | State in descending order. | -| <a id="vulnerabilitysorttitle_asc"></a>`title_asc` **{warning-solid}** | **Deprecated** in 14.2. Deprecated due to performance issues. | -| <a id="vulnerabilitysorttitle_desc"></a>`title_desc` **{warning-solid}** | **Deprecated** in 14.2. Deprecated due to performance issues. | ### `VulnerabilityState` diff --git a/doc/api/integrations.md b/doc/api/integrations.md index e1e1ad1dc2a..eaa826b3686 100644 --- a/doc/api/integrations.md +++ b/doc/api/integrations.md @@ -92,7 +92,6 @@ Parameters: | --------- | ---- | -------- | ----------- | | `api_key` | string | true | User API token. User must have access to task. All comments are attributed to this user. | | `restrict_to_branch` | string | false | Comma-separated list of branches to be are automatically inspected. Leave blank to include all branches. | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Asana integration @@ -128,7 +127,6 @@ Parameters: | --------- | ---- | -------- | ----------- | | `token` | string | true | The authentication token | `subdomain` | string | false | The subdomain setting | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Assembla integration @@ -169,7 +167,6 @@ Parameters: | `build_key` | string | true | Bamboo build plan key like KEY | | `username` | string | true | A user with API access, if applicable | | `password` | string | true | Password of the user | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Atlassian Bamboo CI integration @@ -206,7 +203,6 @@ Parameters: | `new_issue_url` | string | true | New Issue URL | | `issues_url` | string | true | Issue URL | | `project_url` | string | true | Project URL | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Bugzilla integration @@ -244,6 +240,8 @@ Parameters: | `project_url` | string | true | Pipeline URL. For example, `https://buildkite.com/example/pipeline` | | `enable_ssl_verification` | boolean | false | DEPRECATED: This parameter has no effect since SSL verification is always enabled | | `push_events` | boolean | false | Enable notifications for push events | +| `merge_requests_events` | boolean | false | Enable notifications for merge request events | +| `tag_push_events` | boolean | false | Enable notifications for tag push events | ### Disable Buildkite integration @@ -281,7 +279,6 @@ Parameters: | `token` | string | true | Campfire API token. To find it, log into Campfire and select **My info**. | | `subdomain` | string | false | Campfire subdomain. Text between `https://` and `.campfirenow.com` when you're logged in. | | `room` | string | false | Campfire room. The last part of the URL when you're in a room. | -| `push_events` | boolean | false | Enable notifications for push events. | ### Disable Campfire integration @@ -450,7 +447,6 @@ Parameters: | `new_issue_url` | string | true | New Issue URL | | `issues_url` | string | true | Issue URL | | `project_url` | string | true | Project URL | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Custom Issue Tracker integration @@ -705,7 +701,6 @@ Parameters: | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `token` | string | true | Flowdock Git source token | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Flowdock integration @@ -828,7 +823,6 @@ Parameters: | `server_host` | string | false | localhost | | `server_port` | integer | false | 6659 | | `colorize_messages` | boolean | false | Colorize messages | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Irker (IRC gateway) integration @@ -1081,7 +1075,6 @@ Parameters: | --------- | ---- | -------- | ----------- | | `token` | string | true | The Pivotal Tracker token | | `restrict_to_branch` | boolean | false | Comma-separated list of branches to automatically inspect. Leave blank to include all branches. | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Pivotal Tracker integration @@ -1156,7 +1149,6 @@ Parameters: | `priority` | string | true | The priority | | `device` | string | false | Leave blank for all active devices | | `sound` | string | false | The sound of the notification | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Pushover integration @@ -1193,7 +1185,6 @@ Parameters: | `new_issue_url` | string | true | New Issue URL | | `project_url` | string | true | Project URL | | `issues_url` | string | true | Issue URL | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable Redmine integration @@ -1399,6 +1390,7 @@ Parameters: | `username` | string | true | A user with permissions to trigger a manual build | | `password` | string | true | The password of the user | | `push_events` | boolean | false | Enable notifications for push events | +| `merge_requests_events` | boolean | false | Enable notifications for merge request events | ### Disable JetBrains TeamCity CI integration @@ -1549,7 +1541,6 @@ Parameters: | --------- | ---- | -------- | ----------- | | `issues_url` | string | true | Issue URL | | `project_url` | string | true | Project URL | -| `push_events` | boolean | false | Enable notifications for push events | ### Disable YouTrack integration diff --git a/doc/api/settings.md b/doc/api/settings.md index 422576826b0..193f18779f5 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -279,7 +279,7 @@ listed in the descriptions of the relevant settings. | `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. | | `delayed_project_deletion` **(PREMIUM SELF)** | boolean | no | Enable delayed project deletion by default in new groups. Default is `false`. | | `delayed_group_deletion` **(PREMIUM SELF)** | boolean | no | Enable delayed group deletion by default in new groups. Requires both `delayed_group_deletion` to be true and `deletion_adjourned_period` to be greater than 0. Default is `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352959) in GitLab 15.0. | -| `delete_inactive_projects` | boolean | no | Enable inactive project deletion feature. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. | +| `delete_inactive_projects` | boolean | no | Enable inactive project deletion feature. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0 (with feature flag `inactive_projects_deletion`, disabled by default). | | `deletion_adjourned_period` **(PREMIUM SELF)** | integer | no | The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90. On every update, a hook on `deletion_adjourned_period` sets the value of `delayed_group_deletion` to `true` if `deletion_adjourned_period` is greater than 0 and `false` if `deletion_adjourned_period` is 0. | `diff_max_patch_bytes` | integer | no | Maximum [diff patch size](../user/admin_area/diff_limits.md), in bytes. | | `diff_max_files` | integer | no | Maximum [files in a diff](../user/admin_area/diff_limits.md). | @@ -356,9 +356,9 @@ listed in the descriptions of the relevant settings. | `html_emails_enabled` | boolean | no | Enable HTML emails. | | `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `bitbucket_server`, `gitlab`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. | | `in_product_marketing_emails_enabled` | boolean | no | Enable [in-product marketing emails](../user/profile/notifications.md#global-notification-settings). Enabled by default. | -| `inactive_projects_delete_after_months` | integer | no | If `delete_inactive_projects` is `true`, the time (in months) to wait before deleting inactive projects. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. | -| `inactive_projects_min_size_mb` | integer | no | If `delete_inactive_projects` is `true`, the minimum repository size for projects to be checked for inactivity. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. | -| `inactive_projects_send_warning_email_after_months` | integer | no | If `delete_inactive_projects` is `true`, sets the time (in months) to wait before emailing maintainers that the project will be deleted because it is inactive. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. | +| `inactive_projects_delete_after_months` | integer | no | If `delete_inactive_projects` is `true`, the time (in months) to wait before deleting inactive projects. Default is `2`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. | +| `inactive_projects_min_size_mb` | integer | no | If `delete_inactive_projects` is `true`, the minimum repository size for projects to be checked for inactivity. Default is `0`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. | +| `inactive_projects_send_warning_email_after_months` | integer | no | If `delete_inactive_projects` is `true`, sets the time (in months) to wait before emailing maintainers that the project is scheduled be deleted because it is inactive. Default is `1`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. [Became operational](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0. | | `invisible_captcha_enabled` | boolean | no | Enable Invisible CAPTCHA spam detection during sign-up. Disabled by default. | | `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.| | `keep_latest_artifact` | boolean | no | Prevent the deletion of the artifacts from the most recent successful jobs, regardless of the expiry time. Enabled by default. | diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md index d340e6afb64..e35a042a320 100644 --- a/doc/ci/quick_start/index.md +++ b/doc/ci/quick_start/index.md @@ -27,6 +27,8 @@ If you are migrating from another CI/CD tool, view this documentation: To use GitLab CI/CD: 1. [Ensure you have runners available](#ensure-you-have-runners-available) to run your jobs. + GitLab SaaS provides runners, so if you're using GitLab.com, you can skip this step. + If you don't have a runner, [install GitLab Runner](https://docs.gitlab.com/runner/install/) and [register a runner](https://docs.gitlab.com/runner/register/) for your instance, project, or group. 1. [Create a `.gitlab-ci.yml` file](#create-a-gitlab-ciyml-file) diff --git a/doc/development/geo.md b/doc/development/geo.md index 60d7b101fcd..f62b2de30db 100644 --- a/doc/development/geo.md +++ b/doc/development/geo.md @@ -118,17 +118,6 @@ CI Job Artifacts and LFS objects are synced in a similar way as uploads, but they are tracked by `Geo::JobArtifactRegistry`, and `Geo::LfsObjectRegistry` models respectively. -#### File Download Dispatch worker - -Also similar to the [Repository Sync worker](#repository-sync-worker), -there is a `Geo::FileDownloadDispatchWorker` class that is run -periodically to sync all uploads that aren't synced to the Geo -**secondary** site yet. - -Files are copied via HTTP(s) and initiated via the -`/api/v4/geo/transfers/:type/:id` endpoint, -for example, `/api/v4/geo/transfers/lfs/123`. - ## Authentication To authenticate file transfers, each `GeoNode` record has two fields: diff --git a/doc/development/maintenance_mode.md b/doc/development/maintenance_mode.md index c2fd4bab605..a118d9cf0ad 100644 --- a/doc/development/maintenance_mode.md +++ b/doc/development/maintenance_mode.md @@ -11,8 +11,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w GitLab Maintenance Mode **only** blocks writes from HTTP and SSH requests at the application level in a few key places within the rails application. [Search the codebase for `maintenance_mode?`.](https://gitlab.com/search?search=maintenance_mode%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=) -- [the read-only database method](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/database.rb#L13), which toggles special behavior when we are not allowed to write to the database. [Search the codebase for `Gitlab::Database.read_only?`.](https://gitlab.com/search?search=Gitlab%3A%3ADatabase.read_only%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=) -- [the read-only middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/middleware/read_only/controller.rb), where HTTP requests that cause database writes are blocked, unless explicitly allowed. +- [the read-only database method](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/database.rb#L13), which toggles special behavior when we are not allowed to write to the database. We use this method for possible places where writes could occur in GET requests. [Search the codebase for `Gitlab::Database.read_only?`.](https://gitlab.com/search?search=Gitlab%3A%3ADatabase.read_only%3F&group_id=9970&project_id=278964&scope=blobs&search_code=false&snippets=false&repository_ref=) +- [the read-only middleware](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/middleware/read_only/controller.rb), where HTTP requests that cause database writes are blocked, unless explicitly allowed (for example, GET requests). - [Git push access via SSH is denied](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/lib/ee/gitlab/git_access.rb#L13) by returning 401 when `gitlab-shell` POSTs to [`/internal/allowed`](internal_api/index.md) to [check if access is allowed](internal_api/index.md#git-authentication). - [Container registry authentication service](https://gitlab.com/gitlab-org/gitlab/-/blob/2425e9de50c678413ceaad6ee3bf66f42b7e228c/ee/app/services/ee/auth/container_registry_authentication_service.rb#L12), where updates to the container registry are blocked. diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md index 97fee094d6c..5e7fe9cc8fb 100644 --- a/doc/development/merge_request_performance_guidelines.md +++ b/doc/development/merge_request_performance_guidelines.md @@ -206,7 +206,7 @@ By default, this `Gitlab::SQL::CTE` class forces materialization through adding (this behavior is implemented using a custom Arel node `Gitlab::Database::AsWithMaterialized` under the surface). WARNING: -We plan to drop the support for PostgreSQL 11. Upgrading to GitLab 14.0 requires PostgreSQL 12 or higher. +Upgrading to GitLab 14.0 requires PostgreSQL 12 or higher. ## Cached Queries diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index a7a7b5f9eed..d91c53823e2 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -466,18 +466,22 @@ it('waits for an Ajax call', () => { #### Vue rendering -To wait until a Vue component is re-rendered, use either of the equivalent -[`Vue.nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick) or `vm.$nextTick()`. +Use [`nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick) to wait until a Vue component is +re-rendered. **in Jest:** ```javascript -it('renders something', () => { +import { nextTick } from 'vue'; + +// ... + +it('renders something', async () => { wrapper.setProps({ value: 'new value' }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.text()).toBe('new value'); - }); + await nextTick(); + + expect(wrapper.text()).toBe('new value'); }); ``` diff --git a/doc/install/requirements.md b/doc/install/requirements.md index b2899063cb4..83fce2f00f6 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -121,6 +121,8 @@ the following table) as these were used for development and testing: |----------------|----------------------------| | 13.0 | 11 | | 14.0 | 12.10 | +| 15.0 | 12.0 | +| 16.0 (planned) | 13.0 | You must also ensure the following extensions are loaded into every GitLab database. [Read more about this requirement, and troubleshooting](postgresql_extensions.md). diff --git a/doc/update/index.md b/doc/update/index.md index 9a8e1e2a38b..0273b8dd2e9 100644 --- a/doc/update/index.md +++ b/doc/update/index.md @@ -197,6 +197,8 @@ GitLab 14.2 introduced an issue where a background migration named `BackfillDraf GitLab 14.4 introduced an issue where a background migration named `PopulateTopicsTotalProjectsCountCache` can be permanently stuck in a **pending** state across upgrades when the instance lacks records that match the migration's target. To clean up this stuck migration, see the [14.4.0 version-specific instructions](#1440). +GitLab 14.5 introduced an issue where a background migration named `UpdateVulnerabilityOccurrencesLocation` can be permanently stuck in a **pending** state across upgrades when the instance lacks records that match the migration's target. To clean up this stuck migration, see the [14.5.0 version-specific instructions](#1450). + GitLab 14.8 introduced an issue where a background migration named `PopulateTopicsNonPrivateProjectsCount` can be permanently stuck in a **pending** state across upgrades. To clean up this stuck migration, see the [14.8.0 version-specific instructions](#1480). GitLab 14.9 introduced an issue where a background migration named `ResetDuplicateCiRunnersTokenValuesOnProjects` can be permanently stuck in a **pending** state across upgrades when the instance lacks records that match the migration's target. To clean up this stuck migration, see the [14.9.0 version-specific instructions](#1490). @@ -545,6 +547,18 @@ or [init scripts](upgrading_from_source.md#configure-sysv-init-script) by [follo For more information, refer to [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/331823). +- GitLab 14.5.0 includes a + [background migration `UpdateVulnerabilityOccurrencesLocation`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72788) + that may remain stuck permanently in a **pending** state when the instance lacks records that match the migration's target. + + To clean up this stuck job, run the following in the [GitLab Rails Console](../administration/operations/rails_console.md): + + ```ruby + Gitlab::Database::BackgroundMigrationJob.pending.where(class_name: "UpdateVulnerabilityOccurrencesLocation").find_each do |job| + puts Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded("UpdateVulnerabilityOccurrencesLocation", job.arguments) + end + ``` + ### 14.4.4 - For [zero-downtime upgrades](zero_downtime.md) on a GitLab cluster with separate Web and API nodes, you need to enable the `paginated_tree_graphql_query` [feature flag](../administration/feature_flags.md#enable-or-disable-the-feature) _before_ upgrading GitLab Web nodes to 14.4. diff --git a/doc/update/removals.md b/doc/update/removals.md index 79e03f5b5eb..73f89be8c4f 100644 --- a/doc/update/removals.md +++ b/doc/update/removals.md @@ -1162,9 +1162,9 @@ as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#brea Before updating GitLab, review the details carefully to determine if you need to make any changes to your code, settings, or workflow. -PostgreSQL 12 will be the minimum required version in GitLab 14.0. It offers [significant improvements](https://www.postgresql.org/about/news/postgresql-12-released-1976/) to indexing, partitioning, and general performance benefits. +GitLab 14.0 requires PostgreSQL 12 or later. It offers [significant improvements](https://www.postgresql.org/about/news/postgresql-12-released-1976/) to indexing, partitioning, and general performance benefits. -Starting in GitLab 13.7, all new installations default to version 12. From GitLab 13.8, single-node instances are automatically upgraded as well. If you aren't ready to upgrade, you can [opt out of automatic upgrades](https://docs.gitlab.com/omnibus/settings/database.html#opt-out-of-automatic-postgresql-upgrades). +Starting in GitLab 13.7, all new installations default to PostgreSQL version 12. From GitLab 13.8, single-node instances are automatically upgraded as well. If you aren't ready to upgrade, you can [opt out of automatic upgrades](https://docs.gitlab.com/omnibus/settings/database.html#opt-out-of-automatic-postgresql-upgrades). ### Redundant timestamp field from DORA metrics API payload diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md index e239ce6ae63..485dbc1b0bc 100644 --- a/doc/update/upgrading_from_source.md +++ b/doc/update/upgrading_from_source.md @@ -146,7 +146,7 @@ Remember to set `git -> bin_path` to `/usr/local/bin/git` in `config/gitlab.yml` ### 7. Update PostgreSQL WARNING: -From GitLab 14.0, you must use at least PostgreSQL 12. +GitLab 14.0 requires at least PostgreSQL 12. The latest version of GitLab might depend on a more recent PostgreSQL version than what you are running. You may also have to enable some diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md index d0487dc57ba..2828b56a5d1 100644 --- a/doc/user/application_security/container_scanning/index.md +++ b/doc/user/application_security/container_scanning/index.md @@ -260,6 +260,7 @@ Support depends on which scanner is used: | Distribution | Grype | Trivy | | -------------- | ----- | ----- | | Alma Linux | | ✅ | +| Alpine Linux | ✅ | | | Amazon Linux | ✅ | ✅ | | BusyBox | ✅ | | | CentOS | ✅ | ✅ | diff --git a/doc/user/clusters/agent/ci_cd_workflow.md b/doc/user/clusters/agent/ci_cd_workflow.md index 95e00a2970e..644a753e282 100644 --- a/doc/user/clusters/agent/ci_cd_workflow.md +++ b/doc/user/clusters/agent/ci_cd_workflow.md @@ -61,7 +61,7 @@ so all projects within have access. For added security, you can also To authorize the agent to access the GitLab project where you keep Kubernetes manifests: 1. On the top bar, select **Menu > Projects** and find the project that contains the agent configuration file (`config.yaml`). -1. Edit the file. Under the `ci_access` keyword, add the `projects` attribute. +1. Edit the `config.yaml` file. Under the `ci_access` keyword, add the `projects` attribute. 1. For the `id`, add the path: ```yaml @@ -84,7 +84,7 @@ Choose the context to run `kubectl` commands from your CI/CD scripts. To authorize the agent to access all of the GitLab projects in a group or subgroup: 1. On the top bar, select **Menu > Projects** and find the project that contains the agent configuration file (`config.yaml`). -1. Edit the file. Under the `ci_access` keyword, add the `groups` attribute. +1. Edit the `config.yaml` file. Under the `ci_access` keyword, add the `groups` attribute. 1. For the `id`, add the path: ```yaml @@ -210,7 +210,7 @@ impersonation credentials in the following way: | `agent.gitlab.com/username` | Contains the username of the user the CI job is running as. | | `agent.gitlab.com/environment_slug` | Contains the slug of the environment. Only set if running in an environment. | -Example to restrict access by the CI/CD job's identity: +Example `config.yaml` to restrict access by the CI/CD job's identity: ```yaml ci_access: diff --git a/lib/gitlab/auth/saml/config.rb b/lib/gitlab/auth/saml/config.rb index 3f13a264b0a..815130aeee2 100644 --- a/lib/gitlab/auth/saml/config.rb +++ b/lib/gitlab/auth/saml/config.rb @@ -5,6 +5,10 @@ module Gitlab module Saml class Config class << self + def enabled? + ::AuthHelper.saml_providers.any? + end + def options Gitlab::Auth::OAuth::Provider.config_for('saml') end diff --git a/lib/gitlab/auth/saml/identity_linker.rb b/lib/gitlab/auth/saml/identity_linker.rb index 93195c3189f..a44a9c2fca5 100644 --- a/lib/gitlab/auth/saml/identity_linker.rb +++ b/lib/gitlab/auth/saml/identity_linker.rb @@ -32,3 +32,5 @@ module Gitlab end end end + +Gitlab::Auth::Saml::IdentityLinker.prepend_mod diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml index 900ba1e5b36..036ce7d7631 100644 --- a/lib/gitlab/database/gitlab_schemas.yml +++ b/lib/gitlab/database/gitlab_schemas.yml @@ -217,7 +217,6 @@ geo_event_log: :gitlab_main geo_events: :gitlab_main geo_hashed_storage_attachments_events: :gitlab_main geo_hashed_storage_migrated_events: :gitlab_main -geo_job_artifact_deleted_events: :gitlab_main geo_lfs_object_deleted_events: :gitlab_main geo_node_namespace_links: :gitlab_main geo_nodes: :gitlab_main diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index f5e4aa1b19d..0453b81d67d 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -959,7 +959,7 @@ module Gitlab return if migration.finished? - Gitlab::Database::BackgroundMigration::BatchedMigrationRunner.finalize(job_class_name, table_name, column_name, job_arguments, connection: connection) if finalize + finalize_batched_background_migration(job_class_name: job_class_name, table_name: table_name, column_name: column_name, job_arguments: job_arguments) if finalize unless migration.reload.finished? # rubocop:disable Cop/ActiveRecordAssociationReload raise "Expected batched background migration for the given configuration to be marked as 'finished', " \ diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb index 75dc4da4bb9..7113c3686f1 100644 --- a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb +++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb @@ -124,6 +124,14 @@ module Gitlab end def finalize_batched_background_migration(job_class_name:, table_name:, column_name:, job_arguments:) + database_name = Gitlab::Database.db_config_name(connection) + + unless ActiveRecord::Base.configurations.primary?(database_name) + raise 'The `#finalize_background_migration` is currently not supported when running in decomposed database, ' \ + 'and this database is not `main:`. For more information visit: ' \ + 'https://docs.gitlab.com/ee/development/database/migrations_for_multiple_databases.html' + end + migration = Gitlab::Database::BackgroundMigration::BatchedMigration.find_for_configuration(job_class_name, table_name, column_name, job_arguments) raise 'Could not find batched background migration' if migration.nil? diff --git a/lib/gitlab/diff/rendered/notebook/diff_file.rb b/lib/gitlab/diff/rendered/notebook/diff_file.rb index e8b4523d40e..1f064d8af50 100644 --- a/lib/gitlab/diff/rendered/notebook/diff_file.rb +++ b/lib/gitlab/diff/rendered/notebook/diff_file.rb @@ -68,7 +68,9 @@ module Gitlab Timeout.timeout(timeout_time) do IpynbDiff.diff(source_diff.old_blob&.data, source_diff.new_blob&.data, - raise_if_invalid_nb: true, diffy_opts: { include_diff_info: true })&.tap do + raise_if_invalid_nb: true, + hide_images: true, + diffy_opts: { include_diff_info: true })&.tap do log_event(LOG_IPYNBDIFF_GENERATED) end end diff --git a/lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb b/lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb index 8a176be30a2..e2b43798b22 100644 --- a/lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb +++ b/lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb @@ -33,7 +33,6 @@ module Gitlab def import delete_stale_metrics create_or_update_metrics - update_prometheus_environments end # rubocop: disable CodeReuse/ActiveRecord @@ -47,8 +46,6 @@ module Gitlab affected_metric_ids << prometheus_metric.id end - - @affected_environment_ids += find_alerts(affected_metric_ids).get_environment_id end # rubocop: enable CodeReuse/ActiveRecord @@ -62,24 +59,9 @@ module Gitlab return unless stale_metrics.exists? - delete_stale_alerts(stale_metrics) stale_metrics.each_batch { |batch| batch.delete_all } end - def delete_stale_alerts(stale_metrics) - stale_alerts = find_alerts(stale_metrics) - - affected_environment_ids = stale_alerts.get_environment_id - return unless affected_environment_ids.present? - - @affected_environment_ids += affected_environment_ids - stale_alerts.each_batch { |batch| batch.delete_all } - end - - def find_alerts(metrics) - Projects::Prometheus::AlertsFinder.new(project: project, metric: metrics).execute - end - def prometheus_metrics_attributes @prometheus_metrics_attributes ||= begin Dashboard::Transformers::Yml::V1::PrometheusMetrics.new( @@ -89,19 +71,6 @@ module Gitlab ).execute end end - - def update_prometheus_environments - affected_environments = ::Environment.for_id(@affected_environment_ids.flatten.uniq).for_project(project) - - return unless affected_environments.exists? - - affected_environments.each do |affected_environment| - ::Clusters::Applications::ScheduleUpdateService.new( - affected_environment.cluster_prometheus_adapter, - project - ).execute - end - end end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c23f8e37410..ac085946e36 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -787,6 +787,9 @@ msgstr "" msgid "%{milliseconds}ms" msgstr "" +msgid "%{minutesUsed} minutes" +msgstr "" + msgid "%{model_name} not found" msgstr "" @@ -855,6 +858,9 @@ msgstr "" msgid "%{openedIssues} open, %{closedIssues} closed" msgstr "" +msgid "%{percentageUsed}%% used" +msgstr "" + msgid "%{percentage}%% issues closed" msgstr "" @@ -21807,12 +21813,6 @@ msgstr "" msgid "Job Failed #%{build_id}" msgstr "" -msgid "Job artifact" -msgstr "" - -msgid "Job artifacts" -msgstr "" - msgid "Job has been erased" msgstr "" @@ -23030,6 +23030,9 @@ msgstr "" msgid "Lock memberships to LDAP synchronization" msgstr "" +msgid "Lock merge request" +msgstr "" + msgid "Lock not found" msgstr "" @@ -39583,6 +39586,9 @@ msgstr "" msgid "To widen your search, change or remove filters above." msgstr "" +msgid "To-Do" +msgstr "" + msgid "To-Do List" msgstr "" @@ -40369,6 +40375,9 @@ msgstr "" msgid "Unlock account" msgstr "" +msgid "Unlock merge request" +msgstr "" + msgid "Unlock more features with GitLab Ultimate" msgstr "" @@ -40813,6 +40822,9 @@ msgstr "" msgid "UsageQuota|Usage quotas help link" msgstr "" +msgid "UsageQuota|Usage since %{usageSince}" +msgstr "" + msgid "UsageQuota|When you purchase additional storage, we automatically unlock projects that were locked when you reached the %{actualRepositorySizeLimit} limit." msgstr "" @@ -44405,6 +44417,9 @@ msgstr "" msgid "ciReport|Found %{issuesWithCount}" msgstr "" +msgid "ciReport|Full Report" +msgstr "" + msgid "ciReport|IaC Scanning" msgstr "" @@ -44443,6 +44458,9 @@ msgstr "" msgid "ciReport|Loading Code Quality report" msgstr "" +msgid "ciReport|Manage Licenses" +msgstr "" + msgid "ciReport|Manage licenses" msgstr "" diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index b38a15e4c94..e21c73976a8 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -47,7 +47,6 @@ RSpec.describe 'Database schema' do events: %w[target_id], forked_project_links: %w[forked_from_project_id], geo_event_log: %w[hashed_storage_attachments_event_id], - geo_job_artifact_deleted_events: %w[job_artifact_id], geo_lfs_object_deleted_events: %w[lfs_object_id], geo_node_statuses: %w[last_event_id cursor_last_event_id], geo_nodes: %w[oauth_application_id], diff --git a/spec/features/merge_request/merge_request_discussion_lock_spec.rb b/spec/features/merge_request/merge_request_discussion_lock_spec.rb index 4e0265839f6..a7bc2a062af 100644 --- a/spec/features/merge_request/merge_request_discussion_lock_spec.rb +++ b/spec/features/merge_request/merge_request_discussion_lock_spec.rb @@ -8,59 +8,91 @@ RSpec.describe 'Merge Request Discussion Lock', :js do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, source_project: project, author: user) } + let(:moved_mr_sidebar_enabled) { false } before do + stub_feature_flags(moved_mr_sidebar: moved_mr_sidebar_enabled) sign_in(user) end - context 'when a user is a team member' do - before do - project.add_developer(user) - end + context 'moved sidebar flag disabled' do + context 'when a user is a team member' do + before do + project.add_developer(user) + end - context 'when the discussion is unlocked' do - it 'the user can lock the merge_request' do - visit project_merge_request_path(merge_request.project, merge_request) + context 'when the discussion is unlocked' do + it 'the user can lock the merge_request' do + visit project_merge_request_path(merge_request.project, merge_request) + + expect(find('.issuable-sidebar')).to have_content('Unlocked') - expect(find('.issuable-sidebar')).to have_content('Unlocked') + page.within('.issuable-sidebar') do + find('.lock-edit').click + click_button('Lock') + end - page.within('.issuable-sidebar') do - find('.lock-edit').click - click_button('Lock') + expect(find('[data-testid="lock-status"]')).to have_content('Locked') end + end + + context 'when the discussion is locked' do + before do + merge_request.update_attribute(:discussion_locked, true) + visit project_merge_request_path(merge_request.project, merge_request) + end + + it 'the user can unlock the merge_request' do + expect(find('.issuable-sidebar')).to have_content('Locked') - expect(find('[data-testid="lock-status"]')).to have_content('Locked') + page.within('.issuable-sidebar') do + find('.lock-edit').click + click_button('Unlock') + end + + expect(find('[data-testid="lock-status"]')).to have_content('Unlocked') + end end end - context 'when the discussion is locked' do - before do - merge_request.update_attribute(:discussion_locked, true) - visit project_merge_request_path(merge_request.project, merge_request) - end + context 'when a user is not a team member' do + context 'when the discussion is unlocked' do + before do + visit project_merge_request_path(merge_request.project, merge_request) + end - it 'the user can unlock the merge_request' do - expect(find('.issuable-sidebar')).to have_content('Locked') + it 'the user can not lock the merge_request' do + expect(find('.issuable-sidebar')).to have_content('Unlocked') + expect(find('.issuable-sidebar')).not_to have_selector('.lock-edit') + end + end - page.within('.issuable-sidebar') do - find('.lock-edit').click - click_button('Unlock') + context 'when the discussion is locked' do + before do + merge_request.update_attribute(:discussion_locked, true) + visit project_merge_request_path(merge_request.project, merge_request) end - expect(find('[data-testid="lock-status"]')).to have_content('Unlocked') + it 'the user can not unlock the merge_request' do + expect(find('.issuable-sidebar')).to have_content('Locked') + expect(find('.issuable-sidebar')).not_to have_selector('.lock-edit') + end end end end - context 'when a user is not a team member' do + context 'moved sidebar flag enabled' do + let(:moved_mr_sidebar_enabled) { true } + context 'when the discussion is unlocked' do before do visit project_merge_request_path(merge_request.project, merge_request) end - it 'the user can not lock the merge_request' do - expect(find('.issuable-sidebar')).to have_content('Unlocked') - expect(find('.issuable-sidebar')).not_to have_selector('.lock-edit') + it 'the user can lock the merge_request' do + click_button 'Toggle dropdown' + + expect(page).to have_content('Lock merge request') end end @@ -70,9 +102,10 @@ RSpec.describe 'Merge Request Discussion Lock', :js do visit project_merge_request_path(merge_request.project, merge_request) end - it 'the user can not unlock the merge_request' do - expect(find('.issuable-sidebar')).to have_content('Locked') - expect(find('.issuable-sidebar')).not_to have_selector('.lock-edit') + it 'the user can unlock the merge_request' do + click_button 'Toggle dropdown' + + expect(page).to have_content('Unlock merge request') end end end diff --git a/spec/frontend/blob/file_template_selector_spec.js b/spec/frontend/blob/file_template_selector_spec.js index 2ab3b3ebc82..65444e86efd 100644 --- a/spec/frontend/blob/file_template_selector_spec.js +++ b/spec/frontend/blob/file_template_selector_spec.js @@ -1,10 +1,11 @@ -import $ from 'jquery'; import FileTemplateSelector from '~/blob/file_template_selector'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; describe('FileTemplateSelector', () => { let subject; - let dropdown; - let wrapper; + + const dropdown = '.dropdown'; + const wrapper = '.wrapper'; const createSubject = () => { subject = new FileTemplateSelector({}); @@ -17,13 +18,16 @@ describe('FileTemplateSelector', () => { afterEach(() => { subject = null; + resetHTMLFixture(); }); describe('show method', () => { beforeEach(() => { - dropdown = document.createElement('div'); - wrapper = document.createElement('div'); - wrapper.classList.add('hidden'); + setHTMLFixture(` + <div class="wrapper hidden"> + <div class="dropdown"></div> + </div> + `); createSubject(); }); @@ -37,25 +41,24 @@ describe('FileTemplateSelector', () => { it('does not call init on subsequent calls', () => { jest.spyOn(subject, 'init'); subject.show(); - subject.show(); expect(subject.init).toHaveBeenCalledTimes(1); }); - it('removes hidden class from $wrapper', () => { - expect($(wrapper).hasClass('hidden')).toBe(true); + it('removes hidden class from wrapper', () => { + subject.init(); + expect(subject.wrapper.classList.contains('hidden')).toBe(true); subject.show(); - - expect($(wrapper).hasClass('hidden')).toBe(false); + expect(subject.wrapper.classList.contains('hidden')).toBe(false); }); it('sets the focus on the dropdown', async () => { subject.show(); - jest.spyOn(subject.$dropdown, 'focus'); + jest.spyOn(subject.dropdown, 'focus'); jest.runAllTimers(); - expect(subject.$dropdown.focus).toHaveBeenCalled(); + expect(subject.dropdown.focus).toHaveBeenCalled(); }); }); }); diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js index 570731764d3..06fd970778c 100644 --- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js +++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js @@ -365,17 +365,17 @@ describe('Linked pipeline', () => { describe('expand button', () => { it.each` - pipelineType | anglePosition | borderClass | expanded - ${downstreamProps} | ${'angle-right'} | ${'gl-border-l-1!'} | ${false} - ${downstreamProps} | ${'angle-left'} | ${'gl-border-l-1!'} | ${true} - ${upstreamProps} | ${'angle-left'} | ${'gl-border-r-1!'} | ${false} - ${upstreamProps} | ${'angle-right'} | ${'gl-border-r-1!'} | ${true} + pipelineType | anglePosition | buttonBorderClasses | expanded + ${downstreamProps} | ${'angle-right'} | ${'gl-border-l-0!'} | ${false} + ${downstreamProps} | ${'angle-left'} | ${'gl-border-l-0!'} | ${true} + ${upstreamProps} | ${'angle-left'} | ${'gl-border-r-0!'} | ${false} + ${upstreamProps} | ${'angle-right'} | ${'gl-border-r-0!'} | ${true} `( - '$pipelineType.columnTitle pipeline button icon should be $anglePosition with $borderClass if expanded state is $expanded', - ({ pipelineType, anglePosition, borderClass, expanded }) => { + '$pipelineType.columnTitle pipeline button icon should be $anglePosition with $buttonBorderClasses if expanded state is $expanded', + ({ pipelineType, anglePosition, buttonBorderClasses, expanded }) => { createWrapper({ propsData: { ...pipelineType, expanded } }); expect(findExpandButton().props('icon')).toBe(anglePosition); - expect(findExpandButton().classes()).toContain(borderClass); + expect(findExpandButton().classes()).toContain(buttonBorderClasses); }, ); }); diff --git a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js index 7bf7e563a01..8478d3d674d 100644 --- a/spec/frontend/sidebar/lock/issuable_lock_form_spec.js +++ b/spec/frontend/sidebar/lock/issuable_lock_form_spec.js @@ -37,6 +37,9 @@ describe('IssuableLockForm', () => { const createComponent = ({ props = {} }) => { wrapper = shallowMount(IssuableLockForm, { store, + provide: { + fullPath: '', + }, propsData: { isEditable: true, ...props, diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb index 4bb09699db4..4b0b44d1325 100644 --- a/spec/helpers/auth_helper_spec.rb +++ b/spec/helpers/auth_helper_spec.rb @@ -500,6 +500,16 @@ RSpec.describe AuthHelper do ) end + context 'when SAML is enabled without specifying a strategy class' do + before do + allow(Gitlab::Auth::OAuth::Provider).to receive(:providers).and_return([:saml]) + end + + it 'returns the saml provider' do + expect(saml_providers).to match_array([:saml]) + end + end + context 'when configuration specifies no provider' do before do allow(Devise).to receive(:omniauth_providers).and_return([]) diff --git a/spec/lib/gitlab/auth/saml/config_spec.rb b/spec/lib/gitlab/auth/saml/config_spec.rb new file mode 100644 index 00000000000..12f5da48873 --- /dev/null +++ b/spec/lib/gitlab/auth/saml/config_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Auth::Saml::Config do + describe '.enabled?' do + subject { described_class.enabled? } + + it { is_expected.to eq(false) } + + context 'when SAML is enabled' do + before do + allow(Gitlab::Auth::OAuth::Provider).to receive(:providers).and_return([:saml]) + end + + it { is_expected.to eq(true) } + end + end +end diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb index 70889369af1..d1a66036149 100644 --- a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb @@ -182,5 +182,26 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d end.to raise_error(RuntimeError, 'Could not find batched background migration') end end + + context 'when uses a CI connection', :reestablished_active_record_base do + before do + skip_if_multiple_databases_not_setup + + ActiveRecord::Base.establish_connection(:ci) # rubocop:disable Database/EstablishConnection + end + + it 'raises an exception' do + ci_migration = create(:batched_background_migration, :active) + + expect do + migration.finalize_batched_background_migration( + job_class_name: ci_migration.job_class_name, + table_name: ci_migration.table_name, + column_name: ci_migration.column_name, + job_arguments: ci_migration.job_arguments + ) + end.to raise_error /is currently not supported when running in decomposed/ + end + end end end diff --git a/spec/lib/gitlab/diff/rendered/notebook/diff_file_spec.rb b/spec/lib/gitlab/diff/rendered/notebook/diff_file_spec.rb index d90c662aec8..1b74e24bf81 100644 --- a/spec/lib/gitlab/diff/rendered/notebook/diff_file_spec.rb +++ b/spec/lib/gitlab/diff/rendered/notebook/diff_file_spec.rb @@ -141,5 +141,9 @@ RSpec.describe Gitlab::Diff::Rendered::Notebook::DiffFile do expect(nb_file.highlighted_diff_lines[12].old_pos).to eq(18) end end + + it 'computes de first line where the remove would appear' do + expect(nb_file.highlighted_diff_lines.map(&:text).join('')).to include('[Hidden Image Output]') + end end end diff --git a/spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb b/spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb index ff8f5797f9d..c15e717b126 100644 --- a/spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb @@ -12,12 +12,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Importers::PrometheusMetrics do subject { described_class.new(dashboard_hash, project: project, dashboard_path: dashboard_path) } - before do - allow_next_instance_of(::Clusters::Applications::ScheduleUpdateService) do |update_service| - allow(update_service).to receive(:execute) - end - end - context 'valid dashboard' do let(:dashboard_hash) { load_sample_dashboard } @@ -45,13 +39,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Importers::PrometheusMetrics do create(:prometheus_metric, existing_metric_attributes) end - let!(:existing_alert) do - alert = create(:prometheus_alert, project: project, prometheus_metric: existing_metric) - existing_metric.prometheus_alerts << alert - - alert - end - it 'updates existing PrometheusMetrics' do subject.execute @@ -68,15 +55,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Importers::PrometheusMetrics do expect { subject.execute }.to change { PrometheusMetric.count }.by(2) end - it 'updates affected environments' do - expect(::Clusters::Applications::ScheduleUpdateService).to receive(:new).with( - existing_alert.environment.cluster_prometheus_adapter, - project - ).and_return(double('ScheduleUpdateService', execute: true)) - - subject.execute - end - context 'with stale metrics' do let!(:stale_metric) do create(:prometheus_metric, @@ -87,13 +65,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Importers::PrometheusMetrics do ) end - let!(:stale_alert) do - alert = create(:prometheus_alert, project: project, prometheus_metric: stale_metric) - stale_metric.prometheus_alerts << alert - - alert - end - it 'updates existing PrometheusMetrics' do subject.execute @@ -111,21 +82,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Importers::PrometheusMetrics do expect { stale_metric.reload }.to raise_error(ActiveRecord::RecordNotFound) end - - it 'deletes stale alert' do - subject.execute - - expect { stale_alert.reload }.to raise_error(ActiveRecord::RecordNotFound) - end - - it 'updates affected environments' do - expect(::Clusters::Applications::ScheduleUpdateService).to receive(:new).with( - existing_alert.environment.cluster_prometheus_adapter, - project - ).and_return(double('ScheduleUpdateService', execute: true)) - - subject.execute - end end end end diff --git a/spec/models/integrations/prometheus_spec.rb b/spec/models/integrations/prometheus_spec.rb index 76e20f20a00..a7495cb9574 100644 --- a/spec/models/integrations/prometheus_spec.rb +++ b/spec/models/integrations/prometheus_spec.rb @@ -122,34 +122,6 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching, end end - describe 'callbacks' do - context 'after_create' do - let(:project) { create(:project) } - let(:integration) { build(:prometheus_integration, project: project) } - - subject(:create_integration) { integration.save! } - - it 'creates default alerts' do - expect(Prometheus::CreateDefaultAlertsWorker) - .to receive(:perform_async) - .with(project.id) - - create_integration - end - - context 'no project exists' do - let(:integration) { build(:prometheus_integration, :instance) } - - it 'does not create default alerts' do - expect(Prometheus::CreateDefaultAlertsWorker) - .not_to receive(:perform_async) - - create_integration - end - end - end - end - describe '#test' do before do integration.manual_configuration = true diff --git a/spec/services/projects/prometheus/metrics/destroy_service_spec.rb b/spec/services/projects/prometheus/metrics/destroy_service_spec.rb index 17cc88b27b6..b4af81f2c87 100644 --- a/spec/services/projects/prometheus/metrics/destroy_service_spec.rb +++ b/spec/services/projects/prometheus/metrics/destroy_service_spec.rb @@ -12,17 +12,4 @@ RSpec.describe Projects::Prometheus::Metrics::DestroyService do expect(PrometheusMetric.find_by(id: metric.id)).to be_nil end - - context 'when metric has a prometheus alert associated' do - it 'schedules a prometheus alert update' do - create(:prometheus_alert, project: metric.project, prometheus_metric: metric) - - schedule_update_service = spy - allow(::Clusters::Applications::ScheduleUpdateService).to receive(:new).and_return(schedule_update_service) - - subject.execute - - expect(schedule_update_service).to have_received(:execute) - end - end end diff --git a/spec/services/projects/prometheus/metrics/update_service_spec.rb b/spec/services/projects/prometheus/metrics/update_service_spec.rb deleted file mode 100644 index bf87093150c..00000000000 --- a/spec/services/projects/prometheus/metrics/update_service_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Projects::Prometheus::Metrics::UpdateService do - let(:metric) { create(:prometheus_metric) } - - it 'updates the prometheus metric' do - expect do - described_class.new(metric, { title: "bar" }).execute - end.to change { metric.reload.title }.to("bar") - end - - context 'when metric has a prometheus alert associated' do - let(:schedule_update_service) { spy } - - before do - create(:prometheus_alert, project: metric.project, prometheus_metric: metric) - allow(::Clusters::Applications::ScheduleUpdateService).to receive(:new).and_return(schedule_update_service) - end - - context 'when updating title' do - it 'schedules a prometheus alert update' do - described_class.new(metric, { title: "bar" }).execute - - expect(schedule_update_service).to have_received(:execute) - end - end - - context 'when updating query' do - it 'schedules a prometheus alert update' do - described_class.new(metric, { query: "sum(bar)" }).execute - - expect(schedule_update_service).to have_received(:execute) - end - end - - it 'does not schedule a prometheus alert update without title nor query being changed' do - described_class.new(metric, { y_label: "bar" }).execute - - expect(schedule_update_service).not_to have_received(:execute) - end - end -end diff --git a/spec/services/prometheus/create_default_alerts_service_spec.rb b/spec/services/prometheus/create_default_alerts_service_spec.rb deleted file mode 100644 index 0880799b589..00000000000 --- a/spec/services/prometheus/create_default_alerts_service_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Prometheus::CreateDefaultAlertsService do - let_it_be(:project) { create(:project, :repository) } - - let(:instance) { described_class.new(project: project) } - let(:expected_alerts) { described_class::DEFAULT_ALERTS } - - describe '#execute' do - subject(:execute) { instance.execute } - - shared_examples 'no alerts created' do - it 'does not create alerts' do - expect { execute }.not_to change { project.reload.prometheus_alerts.count } - end - end - - context 'no environment' do - it_behaves_like 'no alerts created' - end - - context 'environment exists' do - let_it_be(:environment) { create(:environment, project: project) } - - context 'no found metric' do - it_behaves_like 'no alerts created' - end - - context 'metric exists' do - before do - create_expected_metrics! - end - - context 'alert exists already' do - before do - create_pre_existing_alerts!(environment) - end - - it_behaves_like 'no alerts created' - end - - it 'creates alerts' do - expect { execute }.to change { project.reload.prometheus_alerts.count } - .by(expected_alerts.size) - end - - it 'does not schedule an update to prometheus' do - expect(::Clusters::Applications::ScheduleUpdateService).not_to receive(:new) - execute - end - - context 'cluster with prometheus exists' do - let!(:cluster) { create(:cluster, :with_installed_prometheus, :provided_by_user, projects: [project]) } - - it 'schedules an update to prometheus' do - expect_next_instance_of(::Clusters::Applications::ScheduleUpdateService) do |instance| - expect(instance).to receive(:execute) - end - - execute - end - end - - context 'multiple environments' do - let!(:production) { create(:environment, project: project, name: 'production') } - - it 'uses the production environment' do - expect { execute }.to change { production.reload.prometheus_alerts.count } - .by(expected_alerts.size) - end - end - end - end - end - - private - - def create_expected_metrics! - expected_alerts.each do |alert_hash| - create(:prometheus_metric, :common, identifier: alert_hash.fetch(:identifier)) - end - end - - def create_pre_existing_alerts!(environment) - expected_alerts.each do |alert_hash| - metric = PrometheusMetric.for_identifier(alert_hash[:identifier]).first! - create(:prometheus_alert, prometheus_metric: metric, project: project, environment: environment) - end - end -end diff --git a/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb b/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb index d9105981b4b..2741b2a9de7 100644 --- a/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb +++ b/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb @@ -19,7 +19,13 @@ RSpec.shared_examples 'reenqueuer' do describe '#perform' do it 'tries to obtain a lease' do - expect_to_obtain_exclusive_lease(subject.lease_key) + lease_key = if subject.respond_to?(:set_custom_lease_key) + subject.set_custom_lease_key(*job_args) + else + subject.lease_key + end + + expect_to_obtain_exclusive_lease(lease_key) subject_perform end diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb index f7eda9e8558..0c83a692ca8 100644 --- a/spec/workers/every_sidekiq_worker_spec.rb +++ b/spec/workers/every_sidekiq_worker_spec.rb @@ -240,7 +240,6 @@ RSpec.describe 'Every Sidekiq worker' do 'Geo::DesignRepositorySyncWorker' => 1, 'Geo::DestroyWorker' => 3, 'Geo::EventWorker' => 3, - 'Geo::FileDownloadWorker' => 3, 'Geo::FileRegistryRemovalWorker' => 3, 'Geo::FileRemovalWorker' => 3, 'Geo::ProjectSyncWorker' => 1, diff --git a/spec/workers/prometheus/create_default_alerts_worker_spec.rb b/spec/workers/prometheus/create_default_alerts_worker_spec.rb index 887d677c95f..d935bb20a29 100644 --- a/spec/workers/prometheus/create_default_alerts_worker_spec.rb +++ b/spec/workers/prometheus/create_default_alerts_worker_spec.rb @@ -5,63 +5,9 @@ require 'spec_helper' RSpec.describe Prometheus::CreateDefaultAlertsWorker do let_it_be(:project) { create(:project) } - let(:worker) { described_class.new } - let(:logger) { worker.send(:logger) } - let(:service) { instance_double(Prometheus::CreateDefaultAlertsService) } - let(:service_result) { ServiceResponse.success } - subject { described_class.new.perform(project.id) } - before do - allow(Prometheus::CreateDefaultAlertsService) - .to receive(:new).with(project: project) - .and_return(service) - allow(service).to receive(:execute) - .and_return(service_result) - end - - it_behaves_like 'an idempotent worker' do - let(:job_args) { [project.id] } - - it 'calls the service' do - expect(service).to receive(:execute) - - subject - end - - context 'project is nil' do - let(:job_args) { [nil] } - - it 'does not call the service' do - expect(service).not_to receive(:execute) - - subject - end - end - - context 'when service returns an error' do - let(:error_message) { 'some message' } - let(:service_result) { ServiceResponse.error(message: error_message) } - - it 'succeeds and logs the error' do - expect(logger) - .to receive(:info) - .with(a_hash_including('message' => error_message)) - .exactly(worker_exec_times).times - - subject - end - end - end - - context 'when service raises an exception' do - let(:error_message) { 'some exception' } - let(:exception) { StandardError.new(error_message) } - - it 're-raises exception' do - allow(service).to receive(:execute).and_raise(exception) - - expect { subject }.to raise_error(exception) - end + it 'does nothing' do + expect { subject }.not_to change { PrometheusAlert.count } end end |