Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-30 21:09:38 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-30 21:09:38 +0300
commit028bb5dda7abc9ec76f21ae8e691825b4673f733 (patch)
treea41741811452f928c6f650451c69fc18e46b62a4
parent7f305b576b51c3503970ef224cf4b31e247a322d (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--app/assets/javascripts/registry/settings/store/getters.js1
-rw-r--r--app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue116
-rw-r--r--app/assets/javascripts/registry/shared/constants.js32
-rw-r--r--app/assets/javascripts/static_site_editor/components/saved_changes_message.vue7
-rw-r--r--app/assets/javascripts/static_site_editor/components/static_site_editor.vue1
-rw-r--r--app/assets/javascripts/static_site_editor/services/submit_content_changes.js6
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/import/google_code_controller.rb4
-rw-r--r--app/helpers/icons_helper.rb2
-rw-r--r--app/models/blob_viewer/dependency_manager.rb2
-rw-r--r--app/models/clusters/applications/jupyter.rb2
-rw-r--r--app/models/concerns/diff_positionable_note.rb2
-rw-r--r--app/models/concerns/redis_cacheable.rb2
-rw-r--r--app/models/project_services/mock_monitoring_service.rb2
-rw-r--r--app/models/sent_notification.rb2
-rw-r--r--app/services/metrics/dashboard/grafana_metric_embed_service.rb2
-rw-r--r--app/services/metrics/dashboard/transient_embed_service.rb2
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_link_list_service.rb2
-rw-r--r--app/services/projects/lsif_data_service.rb2
-rw-r--r--app/workers/irker_worker.rb2
-rw-r--r--changelogs/unreleased/207267-regex-keep-frontend.yml5
-rw-r--r--changelogs/unreleased/update-jupyter-to-0-9-0.yml5
-rw-r--r--doc/user/packages/container_registry/index.md4
-rw-r--r--doc/user/project/import/bitbucket.md11
-rw-r--r--doc/user/project/import/bitbucket_server.md4
-rw-r--r--doc/user/project/merge_requests/code_quality.md6
-rw-r--r--doc/user/search/index.md5
-rw-r--r--lib/gitlab/database/with_lock_retries.rb14
-rw-r--r--locale/gitlab.pot14
-rw-r--r--spec/controllers/oauth/token_info_controller_spec.rb10
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb2
-rw-r--r--spec/controllers/projects/cycle_analytics/events_controller_spec.rb6
-rw-r--r--spec/controllers/projects/environments/prometheus_api_controller_spec.rb2
-rw-r--r--spec/controllers/projects/logs_controller_spec.rb2
-rw-r--r--spec/features/error_tracking/user_filters_errors_by_status_spec.rb2
-rw-r--r--spec/features/error_tracking/user_sees_error_index_spec.rb2
-rw-r--r--spec/features/projects/import_export/export_file_spec.rb4
-rw-r--r--spec/features/projects/settings/operations_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/registry_settings_spec.rb2
-rw-r--r--spec/frontend/integrations/integration_settings_form_spec.js (renamed from spec/javascripts/integrations/integration_settings_form_spec.js)165
-rw-r--r--spec/frontend/registry/settings/store/getters_spec.js14
-rw-r--r--spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap18
-rw-r--r--spec/frontend/registry/shared/components/expiration_policy_fields_spec.js37
-rw-r--r--spec/frontend/static_site_editor/components/saved_changes_message_spec.js7
-rw-r--r--spec/frontend/static_site_editor/mock_data.js3
-rw-r--r--spec/frontend/static_site_editor/services/submit_content_changes_spec.js3
-rw-r--r--spec/helpers/todos_helper_spec.rb2
-rw-r--r--spec/initializers/lograge_spec.rb2
-rw-r--r--spec/lib/gitlab/database/with_lock_retries_spec.rb21
-rw-r--r--spec/models/ci/pipeline_spec.rb2
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb4
-rw-r--r--spec/models/container_repository_spec.rb2
-rw-r--r--spec/models/project_services/irker_service_spec.rb2
-rw-r--r--spec/models/snippet_spec.rb4
-rw-r--r--spec/requests/api/graphql/boards/board_lists_query_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb10
-rw-r--r--spec/requests/api/projects_spec.rb4
-rw-r--r--spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb2
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb8
-rw-r--r--spec/support/helpers/workhorse_helpers.rb2
-rw-r--r--spec/support/import_export/configuration_helper.rb4
-rw-r--r--spec/support/matchers/disallow_request_matchers.rb2
-rw-r--r--spec/support/shared_contexts/features/error_tracking_shared_context.rb4
-rw-r--r--spec/support/shared_contexts/json_response_shared_context.rb2
-rw-r--r--spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb4
68 files changed, 389 insertions, 242 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3ba8df9b0d2..a5d5b918428 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -30,7 +30,7 @@ workflow:
# merge requests used for this merge a branch release-tools/X into a stable
# branch. For these merge requests we don't want to run any pipelines, as
# they serve no purpose and will run anyway when the changes are merged.
- - if: '$CI_COMMIT_BRANCH =~ /^release-tools\/\d+\.\d+\.\d+-rc\d+$/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/ && $CI_PROJECT_PATH == "gitlab-org/gitlab"'
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^release-tools\/\d+\.\d+\.\d+-rc\d+$/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/ && $CI_PROJECT_PATH == "gitlab-org/gitlab"'
when: never
# For merge requests, create a pipeline.
- if: '$CI_MERGE_REQUEST_IID'
diff --git a/app/assets/javascripts/registry/settings/store/getters.js b/app/assets/javascripts/registry/settings/store/getters.js
index ef4b4f0ba02..ac1a931d8e0 100644
--- a/app/assets/javascripts/registry/settings/store/getters.js
+++ b/app/assets/javascripts/registry/settings/store/getters.js
@@ -16,6 +16,7 @@ export const getSettings = (state, getters) => ({
older_than: getters.getOlderThan,
keep_n: getters.getKeepN,
name_regex: state.settings.name_regex,
+ name_regex_keep: state.settings.name_regex_keep,
});
export const getIsEdited = state => !isEqual(state.original, state.settings);
diff --git a/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue b/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue
index 26dfd11b55c..04a547db07e 100644
--- a/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue
+++ b/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue
@@ -1,8 +1,23 @@
<script>
import { uniqueId } from 'lodash';
import { GlFormGroup, GlToggle, GlFormSelect, GlFormTextarea, GlSprintf } from '@gitlab/ui';
-import { s__, __ } from '~/locale';
-import { NAME_REGEX_LENGTH } from '../constants';
+import {
+ NAME_REGEX_LENGTH,
+ ENABLED_TEXT,
+ DISABLED_TEXT,
+ TEXT_AREA_INVALID_FEEDBACK,
+ EXPIRATION_INTERVAL_LABEL,
+ EXPIRATION_SCHEDULE_LABEL,
+ KEEP_N_LABEL,
+ NAME_REGEX_LABEL,
+ NAME_REGEX_PLACEHOLDER,
+ NAME_REGEX_DESCRIPTION,
+ NAME_REGEX_KEEP_LABEL,
+ NAME_REGEX_KEEP_PLACEHOLDER,
+ NAME_REGEX_KEEP_DESCRIPTION,
+ ENABLE_TOGGLE_LABEL,
+ ENABLE_TOGGLE_DESCRIPTION,
+} from '../constants';
import { mapComputedToEvent } from '../utils';
export default {
@@ -40,42 +55,73 @@ export default {
default: 'right',
},
},
- nameRegexPlaceholder: '.*',
+ i18n: {
+ textAreaInvalidFeedback: TEXT_AREA_INVALID_FEEDBACK,
+ enableToggleLabel: ENABLE_TOGGLE_LABEL,
+ enableToggleDescription: ENABLE_TOGGLE_DESCRIPTION,
+ },
selectList: [
{
name: 'expiration-policy-interval',
- label: s__('ContainerRegistry|Expiration interval:'),
+ label: EXPIRATION_INTERVAL_LABEL,
model: 'older_than',
optionKey: 'olderThan',
},
{
name: 'expiration-policy-schedule',
- label: s__('ContainerRegistry|Expiration schedule:'),
+ label: EXPIRATION_SCHEDULE_LABEL,
model: 'cadence',
optionKey: 'cadence',
},
{
name: 'expiration-policy-latest',
- label: s__('ContainerRegistry|Number of tags to retain:'),
+ label: KEEP_N_LABEL,
model: 'keep_n',
optionKey: 'keepN',
},
],
+ textAreaList: [
+ {
+ name: 'expiration-policy-name-matching',
+ label: NAME_REGEX_LABEL,
+ model: 'name_regex',
+ placeholder: NAME_REGEX_PLACEHOLDER,
+ stateVariable: 'nameRegexState',
+ description: NAME_REGEX_DESCRIPTION,
+ },
+ {
+ name: 'expiration-policy-keep-name',
+ label: NAME_REGEX_KEEP_LABEL,
+ model: 'name_regex_keep',
+ placeholder: NAME_REGEX_KEEP_PLACEHOLDER,
+ stateVariable: 'nameKeepRegexState',
+ description: NAME_REGEX_KEEP_DESCRIPTION,
+ },
+ ],
data() {
return {
uniqueId: uniqueId(),
};
},
computed: {
- ...mapComputedToEvent(['enabled', 'cadence', 'older_than', 'keep_n', 'name_regex'], 'value'),
+ ...mapComputedToEvent(
+ ['enabled', 'cadence', 'older_than', 'keep_n', 'name_regex', 'name_regex_keep'],
+ 'value',
+ ),
policyEnabledText() {
- return this.enabled ? __('enabled') : __('disabled');
+ return this.enabled ? ENABLED_TEXT : DISABLED_TEXT;
},
- nameRegexState() {
- return this.name_regex ? this.name_regex.length <= NAME_REGEX_LENGTH : null;
+ textAreaState() {
+ return {
+ nameRegexState: this.validateNameRegex(this.name_regex),
+ nameKeepRegexState: this.validateNameRegex(this.name_regex_keep),
+ };
},
fieldsValidity() {
- return this.nameRegexState !== false;
+ return (
+ this.textAreaState.nameRegexState !== false &&
+ this.textAreaState.nameKeepRegexState !== false
+ );
},
isFormElementDisabled() {
return !this.enabled || this.isLoading;
@@ -94,6 +140,9 @@ export default {
},
},
methods: {
+ validateNameRegex(value) {
+ return value ? value.length <= NAME_REGEX_LENGTH : null;
+ },
idGenerator(id) {
return `${id}_${this.uniqueId}`;
},
@@ -111,7 +160,7 @@ export default {
:label-cols="labelCols"
:label-align="labelAlign"
:label-for="idGenerator('expiration-policy-toggle')"
- :label="s__('ContainerRegistry|Expiration policy:')"
+ :label="$options.i18n.enableToggleLabel"
>
<div class="d-flex align-items-start">
<gl-toggle
@@ -120,9 +169,7 @@ export default {
:disabled="isLoading"
/>
<span class="mb-2 ml-1 lh-2">
- <gl-sprintf
- :message="s__('ContainerRegistry|Docker tag expiration policy is %{toggleStatus}')"
- >
+ <gl-sprintf :message="$options.i18n.enableToggleDescription">
<template #toggleStatus>
<strong>{{ policyEnabledText }}</strong>
</template>
@@ -157,35 +204,34 @@ export default {
</gl-form-group>
<gl-form-group
- :id="idGenerator('expiration-policy-name-matching-group')"
+ v-for="textarea in $options.textAreaList"
+ :id="idGenerator(`${textarea.name}-group`)"
+ :key="textarea.name"
:label-cols="labelCols"
:label-align="labelAlign"
- :label-for="idGenerator('expiration-policy-name-matching')"
- :label="
- s__('ContainerRegistry|Docker tags with names matching this regex pattern will expire:')
- "
- :state="nameRegexState"
- :invalid-feedback="
- s__('ContainerRegistry|The value of this input should be less than 255 characters')
- "
+ :label-for="idGenerator(textarea.name)"
+ :state="textAreaState[textarea.stateVariable]"
+ :invalid-feedback="$options.i18n.textAreaInvalidFeedback"
>
+ <template #label>
+ <gl-sprintf :message="textarea.label">
+ <template #italic="{content}">
+ <i>{{ content }}</i>
+ </template>
+ </gl-sprintf>
+ </template>
<gl-form-textarea
- :id="idGenerator('expiration-policy-name-matching')"
- v-model="name_regex"
- :placeholder="$options.nameRegexPlaceholder"
- :state="nameRegexState"
+ :id="idGenerator(textarea.name)"
+ :value="value[textarea.model]"
+ :placeholder="textarea.placeholder"
+ :state="textAreaState[textarea.stateVariable]"
:disabled="isFormElementDisabled"
trim
+ @input="updateModel($event, textarea.model)"
/>
<template #description>
<span ref="regex-description">
- <gl-sprintf
- :message="
- s__(
- 'ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}',
- )
- "
- >
+ <gl-sprintf :message="textarea.description">
<template #code="{content}">
<code>{{ content }}</code>
</template>
diff --git a/app/assets/javascripts/registry/shared/constants.js b/app/assets/javascripts/registry/shared/constants.js
index c0dac466b29..7a839e4a3ed 100644
--- a/app/assets/javascripts/registry/shared/constants.js
+++ b/app/assets/javascripts/registry/shared/constants.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
export const FETCH_SETTINGS_ERROR_MESSAGE = s__(
'ContainerRegistry|Something went wrong while fetching the expiration policy.',
@@ -13,3 +13,33 @@ export const UPDATE_SETTINGS_SUCCESS_MESSAGE = s__(
);
export const NAME_REGEX_LENGTH = 255;
+
+export const ENABLED_TEXT = __('enabled');
+export const DISABLED_TEXT = __('disabled');
+
+export const ENABLE_TOGGLE_LABEL = s__('ContainerRegistry|Expiration policy:');
+export const ENABLE_TOGGLE_DESCRIPTION = s__(
+ 'ContainerRegistry|Docker tag expiration policy is %{toggleStatus}',
+);
+
+export const TEXT_AREA_INVALID_FEEDBACK = s__(
+ 'ContainerRegistry|The value of this input should be less than 255 characters',
+);
+
+export const EXPIRATION_INTERVAL_LABEL = s__('ContainerRegistry|Expiration interval:');
+export const EXPIRATION_SCHEDULE_LABEL = s__('ContainerRegistry|Expiration schedule:');
+export const KEEP_N_LABEL = s__('ContainerRegistry|Number of tags to retain:');
+export const NAME_REGEX_LABEL = s__(
+ 'ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}',
+);
+export const NAME_REGEX_PLACEHOLDER = '.*';
+export const NAME_REGEX_DESCRIPTION = s__(
+ 'ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}',
+);
+export const NAME_REGEX_KEEP_LABEL = s__(
+ 'ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}be preserved:%{italicEnd}',
+);
+export const NAME_REGEX_KEEP_PLACEHOLDER = '';
+export const NAME_REGEX_KEEP_DESCRIPTION = s__(
+ 'ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported',
+);
diff --git a/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue b/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue
index 41cb901720c..dd907570114 100644
--- a/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue
+++ b/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue
@@ -28,7 +28,8 @@ export default {
},
returnUrl: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
},
};
@@ -46,7 +47,7 @@ export default {
}}
</p>
<div class="d-flex justify-content-end">
- <gl-button ref="returnToSiteButton" :href="returnUrl">{{
+ <gl-button v-if="returnUrl" ref="returnToSiteButton" :href="returnUrl">{{
s__('StaticSiteEditor|Return to site')
}}</gl-button>
<gl-button ref="mergeRequestButton" class="ml-2" :href="mergeRequest.url" variant="success">
@@ -60,7 +61,7 @@ export default {
<ul>
<li>
{{ s__('StaticSiteEditor|You created a new branch:') }}
- <span ref="branchLink">{{ branch.label }}</span>
+ <gl-link ref="branchLink" :href="branch.url">{{ branch.label }}</gl-link>
</li>
<li>
{{ s__('StaticSiteEditor|You created a merge request:') }}
diff --git a/app/assets/javascripts/static_site_editor/components/static_site_editor.vue b/app/assets/javascripts/static_site_editor/components/static_site_editor.vue
index d45c3d08ef4..79e4b4a4581 100644
--- a/app/assets/javascripts/static_site_editor/components/static_site_editor.vue
+++ b/app/assets/javascripts/static_site_editor/components/static_site_editor.vue
@@ -48,6 +48,7 @@ export default {
<!-- Success view -->
<saved-changes-message
v-if="savedContentMeta"
+ class="w-75"
:branch="savedContentMeta.branch"
:commit="savedContentMeta.commit"
:merge-request="savedContentMeta.mergeRequest"
diff --git a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
index ff591e4b245..b4e4e94d4f2 100644
--- a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
+++ b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js
@@ -56,8 +56,8 @@ const submitContentChanges = ({ username, projectId, sourcePath, content }) => {
const meta = {};
return createBranch(projectId, branch)
- .then(() => {
- Object.assign(meta, { branch: { label: branch } });
+ .then(({ data: { web_url: url } }) => {
+ Object.assign(meta, { branch: { label: branch, url } });
return commitContent(projectId, mergeRequestTitle, branch, sourcePath, content);
})
@@ -67,7 +67,7 @@ const submitContentChanges = ({ username, projectId, sourcePath, content }) => {
return createMergeRequest(projectId, mergeRequestTitle, branch);
})
.then(({ data: { iid: label, web_url: url } }) => {
- Object.assign(meta, { mergeRequest: { label, url } });
+ Object.assign(meta, { mergeRequest: { label: label.toString(), url } });
return meta;
});
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 16254c74ba4..942bb4b6b0e 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -43,7 +43,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def usage_data
respond_to do |format|
format.html do
- usage_data_json = JSON.pretty_generate(Gitlab::UsageData.data)
+ usage_data_json = Gitlab::Json.pretty_generate(Gitlab::UsageData.data)
render html: Gitlab::Highlight.highlight('payload.json', usage_data_json, language: 'json')
end
diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb
index 4dddfbcd20d..03bde0345e3 100644
--- a/app/controllers/import/google_code_controller.rb
+++ b/app/controllers/import/google_code_controller.rb
@@ -15,7 +15,7 @@ class Import::GoogleCodeController < Import::BaseController
end
begin
- dump = JSON.parse(dump_file.read)
+ dump = Gitlab::Json.parse(dump_file.read)
rescue
return redirect_back_or_default(options: { alert: _("The uploaded file is not a valid Google Takeout archive.") })
end
@@ -42,7 +42,7 @@ class Import::GoogleCodeController < Import::BaseController
user_map_json = "{}" if user_map_json.blank?
begin
- user_map = JSON.parse(user_map_json)
+ user_map = Gitlab::Json.parse(user_map_json)
rescue
flash.now[:alert] = _("The entered user map is not a valid JSON user map.")
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 876789e0d4a..8a32d3c8a3f 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -158,6 +158,6 @@ module IconsHelper
def known_sprites
return if Rails.env.production?
- @known_sprites ||= JSON.parse(File.read(Rails.root.join('node_modules/@gitlab/svgs/dist/icons.json')))['icons']
+ @known_sprites ||= Gitlab::Json.parse(File.read(Rails.root.join('node_modules/@gitlab/svgs/dist/icons.json')))['icons']
end
end
diff --git a/app/models/blob_viewer/dependency_manager.rb b/app/models/blob_viewer/dependency_manager.rb
index 711465c7c79..a851f22bfcd 100644
--- a/app/models/blob_viewer/dependency_manager.rb
+++ b/app/models/blob_viewer/dependency_manager.rb
@@ -32,7 +32,7 @@ module BlobViewer
def json_data
@json_data ||= begin
prepare!
- JSON.parse(blob.data)
+ Gitlab::Json.parse(blob.data)
rescue
{}
end
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index 42fa4a6f179..056ea355de6 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -5,7 +5,7 @@ require 'securerandom'
module Clusters
module Applications
class Jupyter < ApplicationRecord
- VERSION = '0.9.0-beta.2'
+ VERSION = '0.9.0'
self.table_name = 'clusters_applications_jupyter'
diff --git a/app/models/concerns/diff_positionable_note.rb b/app/models/concerns/diff_positionable_note.rb
index 6484a3157b1..8590bc7f4eb 100644
--- a/app/models/concerns/diff_positionable_note.rb
+++ b/app/models/concerns/diff_positionable_note.rb
@@ -17,7 +17,7 @@ module DiffPositionableNote
%i(original_position position change_position).each do |meth|
define_method "#{meth}=" do |new_position|
if new_position.is_a?(String)
- new_position = JSON.parse(new_position) rescue nil
+ new_position = Gitlab::Json.parse(new_position) rescue nil
end
if new_position.is_a?(Hash)
diff --git a/app/models/concerns/redis_cacheable.rb b/app/models/concerns/redis_cacheable.rb
index 2f23467dc78..2d4ed51ce3b 100644
--- a/app/models/concerns/redis_cacheable.rb
+++ b/app/models/concerns/redis_cacheable.rb
@@ -43,7 +43,7 @@ module RedisCacheable
strong_memoize(:cached_attributes) do
Gitlab::Redis::Cache.with do |redis|
data = redis.get(cache_attribute_key)
- JSON.parse(data, symbolize_names: true) if data
+ Gitlab::Json.parse(data, symbolize_names: true) if data
end
end
end
diff --git a/app/models/project_services/mock_monitoring_service.rb b/app/models/project_services/mock_monitoring_service.rb
index bcf8f1df5da..25ae0f6b60d 100644
--- a/app/models/project_services/mock_monitoring_service.rb
+++ b/app/models/project_services/mock_monitoring_service.rb
@@ -14,7 +14,7 @@ class MockMonitoringService < MonitoringService
end
def metrics(environment)
- JSON.parse(File.read(Rails.root + 'spec/fixtures/metrics.json'))
+ Gitlab::Json.parse(File.read(Rails.root + 'spec/fixtures/metrics.json'))
end
def can_test?
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index f3a9293376f..1bfcad02f38 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -76,7 +76,7 @@ class SentNotification < ApplicationRecord
def position=(new_position)
if new_position.is_a?(String)
- new_position = JSON.parse(new_position) rescue nil
+ new_position = Gitlab::Json.parse(new_position) rescue nil
end
if new_position.is_a?(Hash)
diff --git a/app/services/metrics/dashboard/grafana_metric_embed_service.rb b/app/services/metrics/dashboard/grafana_metric_embed_service.rb
index 5fd1e0dda89..d9ce2c5e905 100644
--- a/app/services/metrics/dashboard/grafana_metric_embed_service.rb
+++ b/app/services/metrics/dashboard/grafana_metric_embed_service.rb
@@ -113,7 +113,7 @@ module Metrics
end
def parse_json(json)
- JSON.parse(json, symbolize_names: true)
+ Gitlab::Json.parse(json, symbolize_names: true)
rescue JSON::ParserError
raise DashboardProcessingError.new('Grafana response contains invalid json')
end
diff --git a/app/services/metrics/dashboard/transient_embed_service.rb b/app/services/metrics/dashboard/transient_embed_service.rb
index b13fc1e4fa8..cb6ca215447 100644
--- a/app/services/metrics/dashboard/transient_embed_service.rb
+++ b/app/services/metrics/dashboard/transient_embed_service.rb
@@ -23,7 +23,7 @@ module Metrics
override :get_raw_dashboard
def get_raw_dashboard
- JSON.parse(params[:embed_json])
+ Gitlab::Json.parse(params[:embed_json])
rescue JSON::ParserError => e
invalid_embed_json!(e.message)
end
diff --git a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
index 48a21bf94ba..efd410088ab 100644
--- a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
@@ -69,7 +69,7 @@ module Projects
# application/vnd.git-lfs+json
# (https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#requests),
# HTTParty does not know this is actually JSON.
- data = JSON.parse(response.body)
+ data = Gitlab::Json.parse(response.body)
raise DownloadLinksError, "LFS Batch API did return any objects" unless data.is_a?(Hash) && data.key?('objects')
diff --git a/app/services/projects/lsif_data_service.rb b/app/services/projects/lsif_data_service.rb
index 142a5a910d4..5e7055b3309 100644
--- a/app/services/projects/lsif_data_service.rb
+++ b/app/services/projects/lsif_data_service.rb
@@ -42,7 +42,7 @@ module Projects
file.open do |stream|
Zlib::GzipReader.wrap(stream) do |gz_stream|
- data = JSON.parse(gz_stream.read)
+ data = Gitlab::Json.parse(gz_stream.read)
end
end
diff --git a/app/workers/irker_worker.rb b/app/workers/irker_worker.rb
index 73bc050d7be..7622f40a949 100644
--- a/app/workers/irker_worker.rb
+++ b/app/workers/irker_worker.rb
@@ -53,7 +53,7 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker
def sendtoirker(privmsg)
to_send = { to: @channels, privmsg: privmsg }
- @socket.puts JSON.dump(to_send)
+ @socket.puts Gitlab::Json.dump(to_send)
end
def close_connection
diff --git a/changelogs/unreleased/207267-regex-keep-frontend.yml b/changelogs/unreleased/207267-regex-keep-frontend.yml
new file mode 100644
index 00000000000..8ff20c390eb
--- /dev/null
+++ b/changelogs/unreleased/207267-regex-keep-frontend.yml
@@ -0,0 +1,5 @@
+---
+title: Add new keep regex to expiration policy settings ui
+merge_request: 29940
+author:
+type: changed
diff --git a/changelogs/unreleased/update-jupyter-to-0-9-0.yml b/changelogs/unreleased/update-jupyter-to-0-9-0.yml
new file mode 100644
index 00000000000..2e309513b87
--- /dev/null
+++ b/changelogs/unreleased/update-jupyter-to-0-9-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update managed jupyter chart to 0.9.0 (stable)
+merge_request: 30393
+author:
+type: changed
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 9d50c23b780..9f4702a09e5 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -503,7 +503,7 @@ then goes through a process of excluding tags from it until only the ones to be
1. Evaluates the `name_regex`, excluding non-matching names from the list.
1. Excludes any tags that do not have a manifest (not part of the options).
1. Orders the remaining tags by `created_date`.
-1. Excludes from the list the N tags based on the `keep_n` value (Expiration latest).
+1. Excludes from the list the N tags based on the `keep_n` value (Number of tags to retain).
1. Excludes from the list the tags older than the `older_than` value (Expiration interval).
1. Finally, the remaining tags in the list are deleted from the Container Registry.
@@ -518,7 +518,7 @@ The UI allows you to configure the following:
- **Expiration policy:** enable or disable the expiration policy.
- **Expiration interval:** how long tags are exempt from being deleted.
- **Expiration schedule:** how often the cron job checking the tags should run.
-- **Expiration latest:** how many tags to _always_ keep for each image.
+- **Number of tags to retain:** how many tags to _always_ keep for each image.
- **Docker tags with names matching this regex pattern will expire:** the regex used to determine what tags should be expired. To qualify all tags for expiration, use the default value of `.*`.
### Managing project expiration policy through the API
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index e7dd94d2794..56717858b53 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -42,7 +42,7 @@ The importer will create any new namespaces (groups) if they don't exist or in
the case the namespace is taken, the repository will be imported under the user's
namespace that started the import process.
-## Importing your Bitbucket repositories
+## Import your Bitbucket repositories
1. Sign in to GitLab and go to your dashboard.
1. Click on **New project**.
@@ -60,3 +60,12 @@ namespace that started the import process.
each project will be imported.
![Import projects](img/bitbucket_import_select_project_v12_3.png)
+
+## Troubleshooting
+
+If you have more than one Bitbucket account, be sure to sign in to the correct account.
+If you've accidentally started the import process with the wrong account, follow these steps:
+
+1. Revoke GitLab access to your Bitbucket account, essentially reversing the process in the following procedure: [Import your Bitbucket repositories](#import-your-bitbucket-repositories).
+
+1. Sign out of the Bitbucket account. Follow the procedure linked from the previous step.
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index 99179c3190e..55df2d7294d 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -73,3 +73,7 @@ namespace that started the import process.
imported.
![Import projects](img/bitbucket_server_import_select_project_v12_3.png)
+
+## Troubleshooting
+
+See the [troubleshooting](bitbucket.md#troubleshooting) section for [Bitbucket](bitbucket.md).
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 4b3bfac6e76..beb90e30906 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -65,10 +65,10 @@ also requires the GitLab Runner 11.5 or later. For earlier versions, use the
This example shows how to run Code Quality on your code by using GitLab CI/CD and Docker.
-First, you need GitLab Runner with:
+First, you need GitLab Runner configured:
-- The [docker-in-docker executor](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
-- Enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB.
+- For the [docker-in-docker workflow](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
+- With enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB.
Once you set up the Runner, include the CodeQuality template in your CI config:
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index ed2a4b36372..eac3d714831 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -41,7 +41,10 @@ groups:
- [Label](../project/labels.md)
- My-reaction
- Confidential
- - Epic ([Introduced](https://gitlab.com/gitlab-org/gitlab/issues/195704) in GitLab 12.9)
+ - Epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9),
+ including [child epic](../group/epics/index.md#multi-level-child-epics-ultimate)
+ ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in
+ [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0)
- Search for this text
1. Select or type the operator to use for filtering the attribute. The following operators are
available:
diff --git a/lib/gitlab/database/with_lock_retries.rb b/lib/gitlab/database/with_lock_retries.rb
index 2f36bfa1480..bebcba6f42e 100644
--- a/lib/gitlab/database/with_lock_retries.rb
+++ b/lib/gitlab/database/with_lock_retries.rb
@@ -78,12 +78,18 @@ module Gitlab
run_block_with_transaction
rescue ActiveRecord::LockWaitTimeout
if retry_with_lock_timeout?
+ disable_idle_in_transaction_timeout
wait_until_next_retry
+ reset_db_settings
retry
else
+ reset_db_settings
run_block_without_lock_timeout
end
+
+ ensure
+ reset_db_settings
end
end
@@ -153,6 +159,14 @@ module Gitlab
def current_sleep_time_in_seconds
timing_configuration[current_iteration - 1][1].to_f
end
+
+ def disable_idle_in_transaction_timeout
+ execute("SET LOCAL idle_in_transaction_session_timeout TO '0'")
+ end
+
+ def reset_db_settings
+ execute('RESET idle_in_transaction_session_timeout; RESET lock_timeout')
+ end
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index aa22bea0367..bff051d896f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5606,9 +5606,6 @@ msgstr ""
msgid "ContainerRegistry|Docker tag expiration policy is %{toggleStatus}"
msgstr ""
-msgid "ContainerRegistry|Docker tags with names matching this regex pattern will expire:"
-msgstr ""
-
msgid "ContainerRegistry|Edit Settings"
msgstr ""
@@ -5654,7 +5651,10 @@ msgstr ""
msgid "ContainerRegistry|Quick Start"
msgstr ""
-msgid "ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
+msgid "ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported"
+msgstr ""
+
+msgid "ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
msgstr ""
msgid "ContainerRegistry|Remove repository"
@@ -5707,6 +5707,12 @@ msgstr ""
msgid "ContainerRegistry|Tags deleted successfully"
msgstr ""
+msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
+msgstr ""
+
msgid "ContainerRegistry|The Container Registry tag expiration and retention policies for this project have not been enabled."
msgstr ""
diff --git a/spec/controllers/oauth/token_info_controller_spec.rb b/spec/controllers/oauth/token_info_controller_spec.rb
index 4b3539879df..4658c2702ca 100644
--- a/spec/controllers/oauth/token_info_controller_spec.rb
+++ b/spec/controllers/oauth/token_info_controller_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show
expect(response).to have_gitlab_http_status(:unauthorized)
- expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
+ expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@@ -23,7 +23,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: access_token.token }
expect(response).to have_gitlab_http_status(:ok)
- expect(JSON.parse(response.body)).to eq(
+ expect(Gitlab::Json.parse(response.body)).to eq(
'scope' => %w[api],
'scopes' => %w[api],
'created_at' => access_token.created_at.to_i,
@@ -40,7 +40,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: 'unknown_token' }
expect(response).to have_gitlab_http_status(:unauthorized)
- expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
+ expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@@ -53,7 +53,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: access_token.token }
expect(response).to have_gitlab_http_status(:unauthorized)
- expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
+ expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@@ -64,7 +64,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: access_token.token }
expect(response).to have_gitlab_http_status(:unauthorized)
- expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
+ expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
end
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index c59983d5138..aa3371f7ddf 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -334,7 +334,7 @@ describe Projects::ArtifactsController do
def params
@params ||= begin
base64_params = send_data.sub(/\Aartifacts\-entry:/, '')
- JSON.parse(Base64.urlsafe_decode64(base64_params))
+ Gitlab::Json.parse(Base64.urlsafe_decode64(base64_params))
end
end
end
diff --git a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
index b828c678d0c..942e095d669 100644
--- a/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
+++ b/spec/controllers/projects/cycle_analytics/events_controller_spec.rb
@@ -17,7 +17,7 @@ describe Projects::CycleAnalytics::EventsController do
get_issue
expect(response).to be_successful
- expect(JSON.parse(response.body)['events']).to be_empty
+ expect(Gitlab::Json.parse(response.body)['events']).to be_empty
end
end
@@ -38,7 +38,7 @@ describe Projects::CycleAnalytics::EventsController do
it 'contains event detais' do
get_issue
- events = JSON.parse(response.body)['events']
+ events = Gitlab::Json.parse(response.body)['events']
expect(events).not_to be_empty
expect(events.first).to include('title', 'author', 'iid', 'total_time', 'created_at', 'url')
@@ -51,7 +51,7 @@ describe Projects::CycleAnalytics::EventsController do
expect(response).to be_successful
- expect(JSON.parse(response.body)['events']).to be_empty
+ expect(Gitlab::Json.parse(response.body)['events']).to be_empty
end
end
end
diff --git a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
index 793c10f0b21..fcb9293d4a9 100644
--- a/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
+++ b/spec/controllers/projects/environments/prometheus_api_controller_spec.rb
@@ -38,7 +38,7 @@ describe Projects::Environments::PrometheusApiController do
context 'with success result' do
let(:service_result) { { status: :success, body: prometheus_body } }
let(:prometheus_body) { '{"status":"success"}' }
- let(:prometheus_json_body) { JSON.parse(prometheus_body) }
+ let(:prometheus_json_body) { Gitlab::Json.parse(prometheus_body) }
it 'returns prometheus response' do
get :proxy, params: environment_params
diff --git a/spec/controllers/projects/logs_controller_spec.rb b/spec/controllers/projects/logs_controller_spec.rb
index ea71dbe45aa..cc0690788c7 100644
--- a/spec/controllers/projects/logs_controller_spec.rb
+++ b/spec/controllers/projects/logs_controller_spec.rb
@@ -50,7 +50,7 @@ describe Projects::LogsController do
container_name: container
}
end
- let(:service_result_json) { JSON.parse(service_result.to_json) }
+ let(:service_result_json) { Gitlab::Json.parse(service_result.to_json) }
let_it_be(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project]) }
diff --git a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
index 51e29e2a5ec..4b5bc16c4db 100644
--- a/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
+++ b/spec/features/error_tracking/user_filters_errors_by_status_spec.rb
@@ -6,7 +6,7 @@ describe 'When a user filters Sentry errors by status', :js, :use_clean_rails_me
include_context 'sentry error tracking context feature'
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
- let_it_be(:filtered_errors_by_status_response) { JSON.parse(issues_response_body).filter { |error| error['status'] == 'ignored' }.to_json }
+ let_it_be(:filtered_errors_by_status_response) { Gitlab::Json.parse(issues_response_body).filter { |error| error['status'] == 'ignored' }.to_json }
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_filter) { "#{sentry_api_urls.issues_url}?limit=20&query=is:ignored" }
let(:auth_token) {{ 'Authorization' => 'Bearer access_token_123' }}
diff --git a/spec/features/error_tracking/user_sees_error_index_spec.rb b/spec/features/error_tracking/user_sees_error_index_spec.rb
index 842e4a2e8b5..34a3a4b5a49 100644
--- a/spec/features/error_tracking/user_sees_error_index_spec.rb
+++ b/spec/features/error_tracking/user_sees_error_index_spec.rb
@@ -6,7 +6,7 @@ describe 'View error index page', :js, :use_clean_rails_memory_store_caching, :s
include_context 'sentry error tracking context feature'
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
- let_it_be(:issues_response) { JSON.parse(issues_response_body) }
+ let_it_be(:issues_response) { Gitlab::Json.parse(issues_response_body) }
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
before do
diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb
index 7ee8f42e6ef..1d6d5ae1b4d 100644
--- a/spec/features/projects/import_export/export_file_spec.rb
+++ b/spec/features/projects/import_export/export_file_spec.rb
@@ -52,7 +52,7 @@ describe 'Import/Export - project export integration test', :js do
project_json_path = File.join(tmpdir, 'project.json')
expect(File).to exist(project_json_path)
- project_hash = JSON.parse(IO.read(project_json_path))
+ project_hash = Gitlab::Json.parse(IO.read(project_json_path))
sensitive_words.each do |sensitive_word|
found = find_sensitive_attributes(sensitive_word, project_hash)
@@ -78,7 +78,7 @@ describe 'Import/Export - project export integration test', :js do
expect(File).to exist(project_json_path)
relations = []
- relations << JSON.parse(IO.read(project_json_path))
+ relations << Gitlab::Json.parse(IO.read(project_json_path))
Dir.glob(File.join(tmpdir, 'tree/project', '*.ndjson')) do |rb_filename|
File.foreach(rb_filename) do |line|
json = ActiveSupport::JSON.decode(line)
diff --git a/spec/features/projects/settings/operations_settings_spec.rb b/spec/features/projects/settings/operations_settings_spec.rb
index 3c9102431e8..752353cf2f5 100644
--- a/spec/features/projects/settings/operations_settings_spec.rb
+++ b/spec/features/projects/settings/operations_settings_spec.rb
@@ -76,7 +76,7 @@ describe 'Projects > Settings > For a forked project', :js do
context 'success path' do
let(:projects_sample_response) do
Gitlab::Utils.deep_indifferent_access(
- JSON.parse(fixture_file('sentry/list_projects_sample_response.json'))
+ Gitlab::Json.parse(fixture_file('sentry/list_projects_sample_response.json'))
)
end
diff --git a/spec/features/projects/settings/registry_settings_spec.rb b/spec/features/projects/settings/registry_settings_spec.rb
index 74d3544ce92..ba92e8bc516 100644
--- a/spec/features/projects/settings/registry_settings_spec.rb
+++ b/spec/features/projects/settings/registry_settings_spec.rb
@@ -29,7 +29,7 @@ describe 'Project > Settings > CI/CD > Container registry tag expiration policy'
select('7 days until tags are automatically removed', from: 'Expiration interval:')
select('Every day', from: 'Expiration schedule:')
select('50 tags per image name', from: 'Number of tags to retain:')
- fill_in('Docker tags with names matching this regex pattern will expire:', with: '*-production')
+ fill_in('Tags with names matching this regex pattern will expire:', with: '*-production')
end
submit_button = find('.card-footer .btn.btn-success')
expect(submit_button).not_to be_disabled
diff --git a/spec/javascripts/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js
index 72d04be822f..c117a37ff2f 100644
--- a/spec/javascripts/integrations/integration_settings_form_spec.js
+++ b/spec/frontend/integrations/integration_settings_form_spec.js
@@ -16,7 +16,7 @@ describe('IntegrationSettingsForm', () => {
beforeEach(() => {
integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- spyOn(integrationSettingsForm, 'init');
+ jest.spyOn(integrationSettingsForm, 'init').mockImplementation(() => {});
});
it('should initialize form element refs on class object', () => {
@@ -130,7 +130,7 @@ describe('IntegrationSettingsForm', () => {
beforeEach(() => {
mock = new MockAdaptor(axios);
- spyOn(axios, 'put').and.callThrough();
+ jest.spyOn(axios, 'put');
integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
// eslint-disable-next-line no-jquery/no-serialize
@@ -141,18 +141,13 @@ describe('IntegrationSettingsForm', () => {
mock.restore();
});
- it('should make an ajax request with provided `formData`', done => {
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
-
- done();
- })
- .catch(done.fail);
+ it('should make an ajax request with provided `formData`', () => {
+ return integrationSettingsForm.testSettings(formData).then(() => {
+ expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
+ });
});
- it('should show error Flash with `Save anyway` action if ajax request responds with error in test', done => {
+ it('should show error Flash with `Save anyway` action if ajax request responds with error in test', () => {
const errorMessage = 'Test failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: true,
@@ -161,32 +156,27 @@ describe('IntegrationSettingsForm', () => {
test_failed: true,
});
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- const $flashContainer = $('.flash-container');
-
- expect(
- $flashContainer
- .find('.flash-text')
- .text()
- .trim(),
- ).toEqual('Test failed. some error');
-
- expect($flashContainer.find('.flash-action')).toBeDefined();
- expect(
- $flashContainer
- .find('.flash-action')
- .text()
- .trim(),
- ).toEqual('Save anyway');
-
- done();
- })
- .catch(done.fail);
+ return integrationSettingsForm.testSettings(formData).then(() => {
+ const $flashContainer = $('.flash-container');
+
+ expect(
+ $flashContainer
+ .find('.flash-text')
+ .text()
+ .trim(),
+ ).toEqual('Test failed. some error');
+
+ expect($flashContainer.find('.flash-action')).toBeDefined();
+ expect(
+ $flashContainer
+ .find('.flash-action')
+ .text()
+ .trim(),
+ ).toEqual('Save anyway');
+ });
});
- it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', done => {
+ it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', () => {
const errorMessage = 'Validations failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: true,
@@ -195,50 +185,40 @@ describe('IntegrationSettingsForm', () => {
test_failed: false,
});
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- const $flashContainer = $('.flash-container');
-
- expect(
- $flashContainer
- .find('.flash-text')
- .text()
- .trim(),
- ).toEqual('Validations failed. some error');
-
- expect($flashContainer.find('.flash-action')).toBeDefined();
- expect(
- $flashContainer
- .find('.flash-action')
- .text()
- .trim(),
- ).toEqual('');
-
- done();
- })
- .catch(done.fail);
+ return integrationSettingsForm.testSettings(formData).then(() => {
+ const $flashContainer = $('.flash-container');
+
+ expect(
+ $flashContainer
+ .find('.flash-text')
+ .text()
+ .trim(),
+ ).toEqual('Validations failed. some error');
+
+ expect($flashContainer.find('.flash-action')).toBeDefined();
+ expect(
+ $flashContainer
+ .find('.flash-action')
+ .text()
+ .trim(),
+ ).toEqual('');
+ });
});
- it('should submit form if ajax request responds without any error in test', done => {
- spyOn(integrationSettingsForm.$form, 'submit');
+ it('should submit form if ajax request responds without any error in test', () => {
+ jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: false,
});
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
-
- done();
- })
- .catch(done.fail);
+ return integrationSettingsForm.testSettings(formData).then(() => {
+ expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
+ });
});
- it('should submit form when clicked on `Save anyway` action of error Flash', done => {
- spyOn(integrationSettingsForm.$form, 'submit');
+ it('should submit form when clicked on `Save anyway` action of error Flash', () => {
+ jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
const errorMessage = 'Test failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
@@ -247,7 +227,7 @@ describe('IntegrationSettingsForm', () => {
test_failed: true,
});
- integrationSettingsForm
+ return integrationSettingsForm
.testSettings(formData)
.then(() => {
const $flashAction = $('.flash-container .flash-action');
@@ -258,44 +238,31 @@ describe('IntegrationSettingsForm', () => {
})
.then(() => {
expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
-
- done();
- })
- .catch(done.fail);
+ });
});
- it('should show error Flash if ajax request failed', done => {
+ it('should show error Flash if ajax request failed', () => {
const errorMessage = 'Something went wrong on our end.';
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(
- $('.flash-container .flash-text')
- .text()
- .trim(),
- ).toEqual(errorMessage);
-
- done();
- })
- .catch(done.fail);
+ return integrationSettingsForm.testSettings(formData).then(() => {
+ expect(
+ $('.flash-container .flash-text')
+ .text()
+ .trim(),
+ ).toEqual(errorMessage);
+ });
});
- it('should always call `toggleSubmitBtnState` with `false` once request is completed', done => {
+ it('should always call `toggleSubmitBtnState` with `false` once request is completed', () => {
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
- spyOn(integrationSettingsForm, 'toggleSubmitBtnState');
+ jest.spyOn(integrationSettingsForm, 'toggleSubmitBtnState').mockImplementation(() => {});
- integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- expect(integrationSettingsForm.toggleSubmitBtnState).toHaveBeenCalledWith(false);
-
- done();
- })
- .catch(done.fail);
+ return integrationSettingsForm.testSettings(formData).then(() => {
+ expect(integrationSettingsForm.toggleSubmitBtnState).toHaveBeenCalledWith(false);
+ });
});
});
});
diff --git a/spec/frontend/registry/settings/store/getters_spec.js b/spec/frontend/registry/settings/store/getters_spec.js
index 944057ebc9f..b781d09466c 100644
--- a/spec/frontend/registry/settings/store/getters_spec.js
+++ b/spec/frontend/registry/settings/store/getters_spec.js
@@ -4,9 +4,12 @@ import { formOptions } from '../../shared/mock_data';
describe('Getters registry settings store', () => {
const settings = {
+ enabled: true,
cadence: 'foo',
keep_n: 'bar',
older_than: 'baz',
+ name_regex: 'name-foo',
+ name_regex_keep: 'name-keep-bar',
};
describe.each`
@@ -29,6 +32,17 @@ describe('Getters registry settings store', () => {
});
});
+ describe('getSettings', () => {
+ it('returns the content of settings', () => {
+ const computedGetters = {
+ getCadence: settings.cadence,
+ getOlderThan: settings.older_than,
+ getKeepN: settings.keep_n,
+ };
+ expect(getters.getSettings({ settings }, computedGetters)).toEqual(settings);
+ });
+ });
+
describe('getIsEdited', () => {
it('returns false when original is equal to settings', () => {
const same = { foo: 'bar' };
diff --git a/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap b/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap
index 6e7bc0491ce..a9034b81d2f 100644
--- a/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap
+++ b/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap
@@ -117,11 +117,11 @@ exports[`Expiration Policy Form renders 1`] = `
<gl-form-group-stub
id="expiration-policy-name-matching-group"
invalid-feedback="The value of this input should be less than 255 characters"
- label="Docker tags with names matching this regex pattern will expire:"
label-align="right"
label-cols="3"
label-for="expiration-policy-name-matching"
>
+
<gl-form-textarea-stub
disabled="true"
id="expiration-policy-name-matching"
@@ -130,5 +130,21 @@ exports[`Expiration Policy Form renders 1`] = `
value=""
/>
</gl-form-group-stub>
+ <gl-form-group-stub
+ id="expiration-policy-keep-name-group"
+ invalid-feedback="The value of this input should be less than 255 characters"
+ label-align="right"
+ label-cols="3"
+ label-for="expiration-policy-keep-name"
+ >
+
+ <gl-form-textarea-stub
+ disabled="true"
+ id="expiration-policy-keep-name"
+ placeholder=""
+ trim=""
+ value=""
+ />
+ </gl-form-group-stub>
</div>
`;
diff --git a/spec/frontend/registry/shared/components/expiration_policy_fields_spec.js b/spec/frontend/registry/shared/components/expiration_policy_fields_spec.js
index 3782bfeaac4..4825351a6d3 100644
--- a/spec/frontend/registry/shared/components/expiration_policy_fields_spec.js
+++ b/spec/frontend/registry/shared/components/expiration_policy_fields_spec.js
@@ -40,12 +40,13 @@ describe('Expiration Policy Form', () => {
});
describe.each`
- elementName | modelName | value | disabledByToggle
- ${'toggle'} | ${'enabled'} | ${true} | ${'not disabled'}
- ${'interval'} | ${'older_than'} | ${'foo'} | ${'disabled'}
- ${'schedule'} | ${'cadence'} | ${'foo'} | ${'disabled'}
- ${'latest'} | ${'keep_n'} | ${'foo'} | ${'disabled'}
- ${'name-matching'} | ${'name_regex'} | ${'foo'} | ${'disabled'}
+ elementName | modelName | value | disabledByToggle
+ ${'toggle'} | ${'enabled'} | ${true} | ${'not disabled'}
+ ${'interval'} | ${'older_than'} | ${'foo'} | ${'disabled'}
+ ${'schedule'} | ${'cadence'} | ${'foo'} | ${'disabled'}
+ ${'latest'} | ${'keep_n'} | ${'foo'} | ${'disabled'}
+ ${'name-matching'} | ${'name_regex'} | ${'foo'} | ${'disabled'}
+ ${'keep-name'} | ${'name_regex_keep'} | ${'bar'} | ${'disabled'}
`(
`${FORM_ELEMENTS_ID_PREFIX}-$elementName form element`,
({ elementName, modelName, value, disabledByToggle }) => {
@@ -118,21 +119,26 @@ describe('Expiration Policy Form', () => {
${'schedule'}
${'latest'}
${'name-matching'}
+ ${'keep-name'}
`(`${FORM_ELEMENTS_ID_PREFIX}-$elementName is disabled`, ({ elementName }) => {
expect(findFormElements(elementName).attributes('disabled')).toBe('true');
});
});
- describe('form validation', () => {
+ describe.each`
+ modelName | elementName | stateVariable
+ ${'name_regex'} | ${'name-matching'} | ${'nameRegexState'}
+ ${'name_regex_keep'} | ${'keep-name'} | ${'nameKeepRegexState'}
+ `('regex textarea validation', ({ modelName, elementName, stateVariable }) => {
describe(`when name regex is longer than ${NAME_REGEX_LENGTH}`, () => {
const invalidString = new Array(NAME_REGEX_LENGTH + 2).join(',');
beforeEach(() => {
- mountComponent({ value: { name_regex: invalidString } });
+ mountComponent({ value: { [modelName]: invalidString } });
});
- it('nameRegexState is false', () => {
- expect(wrapper.vm.nameRegexState).toBe(false);
+ it(`${stateVariable} is false`, () => {
+ expect(wrapper.vm.textAreaState[stateVariable]).toBe(false);
});
it('emit the @invalidated event', () => {
@@ -141,17 +147,20 @@ describe('Expiration Policy Form', () => {
});
it('if the user did not type validation is null', () => {
- mountComponent({ value: { name_regex: '' } });
+ mountComponent({ value: { [modelName]: '' } });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.nameRegexState).toBe(null);
+ expect(wrapper.vm.textAreaState[stateVariable]).toBe(null);
expect(wrapper.emitted('validated')).toBeTruthy();
});
});
it(`if the user typed and is less than ${NAME_REGEX_LENGTH} state is true`, () => {
- mountComponent({ value: { name_regex: 'foo' } });
+ mountComponent({ value: { [modelName]: 'foo' } });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.nameRegexState).toBe(true);
+ const formGroup = findFormGroup(elementName);
+ const formElement = findFormElements(elementName, formGroup);
+ expect(formGroup.attributes('state')).toBeTruthy();
+ expect(formElement.attributes('state')).toBeTruthy();
});
});
});
diff --git a/spec/frontend/static_site_editor/components/saved_changes_message_spec.js b/spec/frontend/static_site_editor/components/saved_changes_message_spec.js
index 659e9be59d2..a63c3a83395 100644
--- a/spec/frontend/static_site_editor/components/saved_changes_message_spec.js
+++ b/spec/frontend/static_site_editor/components/saved_changes_message_spec.js
@@ -46,14 +46,11 @@ describe('~/static_site_editor/components/saved_changes_message.vue', () => {
${'branch'} | ${findBranchLink} | ${props.branch}
${'commit'} | ${findCommitLink} | ${props.commit}
${'merge request'} | ${findMergeRequestLink} | ${props.mergeRequest}
- `('renders $desc link', ({ desc, findEl, prop }) => {
+ `('renders $desc link', ({ findEl, prop }) => {
const el = findEl();
expect(el.exists()).toBe(true);
expect(el.text()).toBe(prop.label);
-
- if (desc !== 'branch') {
- expect(el.attributes('href')).toBe(prop.url);
- }
+ expect(el.attributes('href')).toBe(prop.url);
});
});
diff --git a/spec/frontend/static_site_editor/mock_data.js b/spec/frontend/static_site_editor/mock_data.js
index 962047e6dd2..c90ecc96521 100644
--- a/spec/frontend/static_site_editor/mock_data.js
+++ b/spec/frontend/static_site_editor/mock_data.js
@@ -34,6 +34,9 @@ export const savedContentMeta = {
};
export const submitChangesError = 'Could not save changes';
+export const commitBranchResponse = {
+ web_url: '/tree/root-master-patch-88195',
+};
export const commitMultipleResponse = {
short_id: 'ed899a2f4b5',
web_url: '/commit/ed899a2f4b5',
diff --git a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
index 9a0bd88b57d..962950ec96c 100644
--- a/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
+++ b/spec/frontend/static_site_editor/services/submit_content_changes_spec.js
@@ -13,6 +13,7 @@ import submitContentChanges from '~/static_site_editor/services/submit_content_c
import {
username,
projectId,
+ commitBranchResponse,
commitMultipleResponse,
createMergeRequestResponse,
sourcePath,
@@ -26,7 +27,7 @@ describe('submitContentChanges', () => {
const branch = 'branch-name';
beforeEach(() => {
- jest.spyOn(Api, 'createBranch').mockResolvedValue();
+ jest.spyOn(Api, 'createBranch').mockResolvedValue({ data: commitBranchResponse });
jest.spyOn(Api, 'commitMultiple').mockResolvedValue({ data: commitMultipleResponse });
jest
.spyOn(Api, 'createProjectMergeRequest')
diff --git a/spec/helpers/todos_helper_spec.rb b/spec/helpers/todos_helper_spec.rb
index 7c73b990338..69da5707b2a 100644
--- a/spec/helpers/todos_helper_spec.rb
+++ b/spec/helpers/todos_helper_spec.rb
@@ -32,7 +32,7 @@ describe TodosHelper do
{ 'id' => projects.first.id, 'text' => projects.first.full_name }
]
- expect(JSON.parse(helper.todo_projects_options)).to match_array(expected_results)
+ expect(Gitlab::Json.parse(helper.todo_projects_options)).to match_array(expected_results)
end
end
end
diff --git a/spec/initializers/lograge_spec.rb b/spec/initializers/lograge_spec.rb
index 48acdac74ac..c243217d2a2 100644
--- a/spec/initializers/lograge_spec.rb
+++ b/spec/initializers/lograge_spec.rb
@@ -123,7 +123,7 @@ describe 'lograge', type: :request do
let(:logger) do
Logger.new(log_output).tap { |logger| logger.formatter = ->(_, _, _, msg) { msg } }
end
- let(:log_data) { JSON.parse(log_output.string) }
+ let(:log_data) { Gitlab::Json.parse(log_output.string) }
before do
Lograge.logger = logger
diff --git a/spec/lib/gitlab/database/with_lock_retries_spec.rb b/spec/lib/gitlab/database/with_lock_retries_spec.rb
index b6321f2eab1..9c8c9749125 100644
--- a/spec/lib/gitlab/database/with_lock_retries_spec.rb
+++ b/spec/lib/gitlab/database/with_lock_retries_spec.rb
@@ -84,7 +84,7 @@ describe Gitlab::Database::WithLockRetries do
subject.run do
lock_attempts += 1
- if lock_attempts == retry_count # we reached the last retry iteration, if we kill the thread, the last try (no lock_timeout) will succeed)
+ if lock_attempts == retry_count # we reached the last retry iteration, if we kill the thread, the last try (no lock_timeout) will succeed
lock_fiber.resume
end
@@ -106,9 +106,13 @@ describe Gitlab::Database::WithLockRetries do
end
context 'after the retries, without setting lock_timeout' do
- let(:retry_count) { timing_configuration.size }
+ let(:retry_count) { timing_configuration.size + 1 }
- it_behaves_like 'retriable exclusive lock on `projects`'
+ it_behaves_like 'retriable exclusive lock on `projects`' do
+ before do
+ expect(subject).to receive(:run_block_without_lock_timeout).and_call_original
+ end
+ end
end
context 'when statement timeout is reached' do
@@ -129,11 +133,22 @@ describe Gitlab::Database::WithLockRetries do
end
end
+ context 'restore local database variables' do
+ it do
+ expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW lock_timeout").to_a }
+ end
+
+ it do
+ expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW idle_in_transaction_session_timeout").to_a }
+ end
+ end
+
context 'casting durations correctly' do
let(:timing_configuration) { [[0.015.seconds, 0.025.seconds], [0.015.seconds, 0.025.seconds]] } # 15ms, 25ms
it 'executes `SET LOCAL lock_timeout` using the configured timeout value in milliseconds' do
expect(ActiveRecord::Base.connection).to receive(:execute).with("SAVEPOINT active_record_1").and_call_original
+ expect(ActiveRecord::Base.connection).to receive(:execute).with('RESET idle_in_transaction_session_timeout; RESET lock_timeout').and_call_original
expect(ActiveRecord::Base.connection).to receive(:execute).with("SET LOCAL lock_timeout TO '15ms'").and_call_original
expect(ActiveRecord::Base.connection).to receive(:execute).with("RELEASE SAVEPOINT active_record_1").and_call_original
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index cae81540cd0..3df87e5d2b4 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -2351,7 +2351,7 @@ describe Ci::Pipeline, :mailer do
def have_requested_pipeline_hook(status)
have_requested(:post, stubbed_hostname(hook.url)).with do |req|
- json_body = JSON.parse(req.body)
+ json_body = Gitlab::Json.parse(req.body)
json_body['object_attributes']['status'] == status &&
json_body['builds'].length == 2
end
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index 3bc5088d1ab..937db9217f3 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -57,7 +57,7 @@ describe Clusters::Applications::Jupyter do
it 'is initialized with 4 arguments' do
expect(subject.name).to eq('jupyter')
expect(subject.chart).to eq('jupyter/jupyterhub')
- expect(subject.version).to eq('0.9.0-beta.2')
+ expect(subject.version).to eq('0.9.0')
expect(subject).to be_rbac
expect(subject.repository).to eq('https://jupyterhub.github.io/helm-chart/')
@@ -76,7 +76,7 @@ describe Clusters::Applications::Jupyter do
let(:jupyter) { create(:clusters_applications_jupyter, :errored, version: '0.0.1') }
it 'is initialized with the locked version' do
- expect(subject.version).to eq('0.9.0-beta.2')
+ expect(subject.version).to eq('0.9.0')
end
end
end
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index 59bade3c841..1eecefe5d4a 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -19,7 +19,7 @@ describe ContainerRepository do
.with(headers: { 'Accept' => ContainerRegistry::Client::ACCEPTED_TYPES.join(', ') })
.to_return(
status: 200,
- body: JSON.dump(tags: ['test_tag']),
+ body: Gitlab::Json.dump(tags: ['test_tag']),
headers: { 'Content-Type' => 'application/json' })
end
diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb
index badc964db16..88a93eef214 100644
--- a/spec/models/project_services/irker_service_spec.rb
+++ b/spec/models/project_services/irker_service_spec.rb
@@ -65,7 +65,7 @@ describe IrkerService do
conn = @irker_server.accept
conn.each_line do |line|
- msg = JSON.parse(line.chomp("\n"))
+ msg = Gitlab::Json.parse(line.chomp("\n"))
expect(msg.keys).to match_array(%w(to privmsg))
expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits",
"irc://test.net/#test"])
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 9b37a2d9ad5..12c06feacf3 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -529,11 +529,11 @@ describe Snippet do
let(:snippet) { build(:snippet) }
it 'excludes secret_token from generated json' do
- expect(JSON.parse(to_json).keys).not_to include("secret_token")
+ expect(Gitlab::Json.parse(to_json).keys).not_to include("secret_token")
end
it 'does not override existing exclude option value' do
- expect(JSON.parse(to_json(except: [:id])).keys).not_to include("secret_token", "id")
+ expect(Gitlab::Json.parse(to_json(except: [:id])).keys).not_to include("secret_token", "id")
end
def to_json(params = {})
diff --git a/spec/requests/api/graphql/boards/board_lists_query_spec.rb b/spec/requests/api/graphql/boards/board_lists_query_spec.rb
index 3d2f6cc9046..f0927487f85 100644
--- a/spec/requests/api/graphql/boards/board_lists_query_spec.rb
+++ b/spec/requests/api/graphql/boards/board_lists_query_spec.rb
@@ -132,6 +132,6 @@ describe 'get board lists' do
end
def grab_list_data(response_body)
- JSON.parse(response_body)['data'][board_parent_type]['boards']['edges'][0]['node']['lists']['edges']
+ Gitlab::Json.parse(response_body)['data'][board_parent_type]['boards']['edges'][0]['node']['lists']['edges']
end
end
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index cb751f786a8..256b45498f6 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -171,7 +171,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: DUE_DATE_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
- response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+ response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([due_issue1.iid, due_issue4.iid, due_issue2.iid])
end
@@ -193,7 +193,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: DUE_DATE_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
- response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+ response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([due_issue3.iid, due_issue4.iid, due_issue2.iid])
end
@@ -239,7 +239,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: RELATIVE_POSITION_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
- response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+ response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([relative_issue1.iid, relative_issue4.iid, relative_issue2.iid])
end
@@ -288,7 +288,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: PRIORITY_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
- response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+ response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end
@@ -310,7 +310,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: PRIORITY_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
- response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
+ response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 853155cea7a..f776faf6458 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -24,7 +24,7 @@ shared_examples 'languages and percentages JSON response' do
get api("/projects/#{project.id}/languages", user)
expect(response).to have_gitlab_http_status(:ok)
- expect(JSON.parse(response.body)).to eq(expected_languages)
+ expect(Gitlab::Json.parse(response.body)).to eq(expected_languages)
end
end
@@ -672,7 +672,7 @@ describe API::Projects do
match[1]
end
- ids += JSON.parse(response.body).map { |p| p['id'] }
+ ids += Gitlab::Json.parse(response.body).map { |p| p['id'] }
end
expect(ids).to contain_exactly(*projects.map(&:id))
diff --git a/spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb b/spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb
index 3eebbe98c9d..3547e1f0f8c 100644
--- a/spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb
+++ b/spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb
@@ -217,7 +217,7 @@ describe Metrics::Dashboard::DatasourceNameParser do
include GrafanaApiHelpers
let(:grafana_url) { valid_grafana_dashboard_link('https://gitlab.grafana.net') }
- let(:grafana_dashboard) { JSON.parse(fixture_file('grafana/dashboard_response.json'), symbolize_names: true) }
+ let(:grafana_dashboard) { Gitlab::Json.parse(fixture_file('grafana/dashboard_response.json'), symbolize_names: true) }
subject { described_class.new(grafana_url, grafana_dashboard).parse }
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index 40f4151c0fb..120d432655b 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -86,7 +86,7 @@ module StubGitlabCalls
def stub_container_registry_tag_manifest_content
fixture_path = 'spec/fixtures/container_registry/tag_manifest.json'
- JSON.parse(File.read(Rails.root + fixture_path))
+ Gitlab::Json.parse(File.read(Rails.root + fixture_path))
end
def stub_container_registry_blob_content
@@ -113,12 +113,12 @@ module StubGitlabCalls
def stub_project_8
data = File.read(Rails.root.join('spec/support/gitlab_stubs/project_8.json'))
- allow_any_instance_of(Network).to receive(:project).and_return(JSON.parse(data))
+ allow_any_instance_of(Network).to receive(:project).and_return(Gitlab::Json.parse(data))
end
def stub_project_8_hooks
data = File.read(Rails.root.join('spec/support/gitlab_stubs/project_8_hooks.json'))
- allow_any_instance_of(Network).to receive(:project_hooks).and_return(JSON.parse(data))
+ allow_any_instance_of(Network).to receive(:project_hooks).and_return(Gitlab::Json.parse(data))
end
def stub_projects
@@ -143,7 +143,7 @@ module StubGitlabCalls
def project_hash_array
f = File.read(Rails.root.join('spec/support/gitlab_stubs/projects.json'))
- JSON.parse f
+ Gitlab::Json.parse(f)
end
end
diff --git a/spec/support/helpers/workhorse_helpers.rb b/spec/support/helpers/workhorse_helpers.rb
index 53b36b3dd45..f16b6c1e910 100644
--- a/spec/support/helpers/workhorse_helpers.rb
+++ b/spec/support/helpers/workhorse_helpers.rb
@@ -11,7 +11,7 @@ module WorkhorseHelpers
header = split_header.join(':')
[
type,
- JSON.parse(Base64.urlsafe_decode64(header))
+ Gitlab::Json.parse(Base64.urlsafe_decode64(header))
]
end
end
diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb
index 4330c4314a8..6f67b0f3dd7 100644
--- a/spec/support/import_export/configuration_helper.rb
+++ b/spec/support/import_export/configuration_helper.rb
@@ -44,8 +44,8 @@ module ConfigurationHelper
import_export_config = config_hash(config)
excluded_attributes = import_export_config[:excluded_attributes][relation_name.to_sym]
included_attributes = import_export_config[:included_attributes][relation_name.to_sym]
- attributes = attributes - JSON.parse(excluded_attributes.to_json) if excluded_attributes
- attributes = attributes & JSON.parse(included_attributes.to_json) if included_attributes
+ attributes = attributes - Gitlab::Json.parse(excluded_attributes.to_json) if excluded_attributes
+ attributes = attributes & Gitlab::Json.parse(included_attributes.to_json) if included_attributes
attributes
end
diff --git a/spec/support/matchers/disallow_request_matchers.rb b/spec/support/matchers/disallow_request_matchers.rb
index a161e3660cd..cb6f4bedbd5 100644
--- a/spec/support/matchers/disallow_request_matchers.rb
+++ b/spec/support/matchers/disallow_request_matchers.rb
@@ -11,7 +11,7 @@ end
RSpec::Matchers.define :disallow_request_in_json do
match do |response|
- json_response = JSON.parse(response.body)
+ json_response = Gitlab::Json.parse(response.body)
response.body.include?('You cannot perform write operations') && json_response.key?('message')
end
end
diff --git a/spec/support/shared_contexts/features/error_tracking_shared_context.rb b/spec/support/shared_contexts/features/error_tracking_shared_context.rb
index cbd33dd109b..102cf7c9b11 100644
--- a/spec/support/shared_contexts/features/error_tracking_shared_context.rb
+++ b/spec/support/shared_contexts/features/error_tracking_shared_context.rb
@@ -6,9 +6,9 @@ shared_context 'sentry error tracking context feature' do
let_it_be(:project) { create(:project) }
let_it_be(:project_error_tracking_settings) { create(:project_error_tracking_setting, project: project) }
let_it_be(:issue_response_body) { fixture_file('sentry/issue_sample_response.json') }
- let_it_be(:issue_response) { JSON.parse(issue_response_body) }
+ let_it_be(:issue_response) { Gitlab::Json.parse(issue_response_body) }
let_it_be(:event_response_body) { fixture_file('sentry/issue_latest_event_sample_response.json') }
- let_it_be(:event_response) { JSON.parse(event_response_body) }
+ let_it_be(:event_response) { Gitlab::Json.parse(event_response_body) }
let(:sentry_api_urls) { Sentry::ApiUrls.new(project_error_tracking_settings.api_url) }
let(:issue_id) { issue_response['id'] }
let(:issue_seen) { 1.year.ago.utc }
diff --git a/spec/support/shared_contexts/json_response_shared_context.rb b/spec/support/shared_contexts/json_response_shared_context.rb
index 6a0734decd5..2f0a564d2bc 100644
--- a/spec/support/shared_contexts/json_response_shared_context.rb
+++ b/spec/support/shared_contexts/json_response_shared_context.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
RSpec.shared_context 'JSON response' do
- let(:json_response) { JSON.parse(response.body) }
+ let(:json_response) { Gitlab::Json.parse(response.body) }
end
diff --git a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
index e530237b4e3..fb7e24eecf2 100644
--- a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
@@ -82,7 +82,7 @@ RSpec.shared_examples 'sorted paginated query' do
cursored_query = pagination_query("sort: #{sort_param}, after: \"#{end_cursor}\"", page_info)
post_graphql(cursored_query, current_user: current_user)
- response_data = graphql_dig_at(JSON.parse(response.body), :data, *data_path, :edges)
+ response_data = graphql_dig_at(Gitlab::Json.parse(response.body), :data, *data_path, :edges)
expect(pagination_results_data(response_data)).to eq expected_results.drop(first_param)
end
diff --git a/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
index 90ac60a6fe7..feb3ba46353 100644
--- a/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
@@ -80,7 +80,7 @@ RSpec.shared_examples 'group and project boards query' do
cursored_query = query("after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
- response_data = JSON.parse(response.body)['data'][board_parent_type]['boards']['edges']
+ response_data = Gitlab::Json.parse(response.body)['data'][board_parent_type]['boards']['edges']
expect(grab_names(response_data)).to eq expected_boards.drop(2).first(2).map(&:name)
end
diff --git a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
index 90fcac0e55c..5dd1badbefc 100644
--- a/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
+++ b/spec/support/shared_examples/services/metrics/dashboard_shared_examples.rb
@@ -23,7 +23,7 @@ RSpec.shared_examples 'valid dashboard service response for schema' do
end
RSpec.shared_examples 'valid dashboard service response' do
- let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) }
+ let(:dashboard_schema) { Gitlab::Json.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) }
it_behaves_like 'valid dashboard service response for schema'
end
@@ -38,7 +38,7 @@ RSpec.shared_examples 'caches the unprocessed dashboard for subsequent calls' do
end
RSpec.shared_examples 'valid embedded dashboard service response' do
- let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) }
+ let(:dashboard_schema) { Gitlab::Json.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) }
it_behaves_like 'valid dashboard service response for schema'
end