Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-04-14 03:08:57 +00:00
parent acd68d938c
commit 7046de6ada
27 changed files with 134 additions and 170 deletions

View File

@ -120,7 +120,7 @@ export default {
:selected-project="selectedProject"
@click="selectProject"
/>
<p class="text-muted mt-1 mb-0">
<p class="gl-text-gray-600 gl-mt-1 gl-mb-0">
<template v-if="projects.length">
{{ $options.i18n.privateForkSelected }}
</template>
@ -134,7 +134,7 @@ export default {
</template>
<gl-link
:href="helpPagePath"
class="w-auto p-0 d-inline-block text-primary bg-transparent"
class="gl-w-auto gl-p-0 gl-display-inline-block gl-bg-transparent"
target="_blank"
>
<span class="sr-only">{{ $options.i18n.readMore }}</span>

View File

@ -163,7 +163,7 @@ export default {
<gl-sprintf
:message="
s__(
'Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0.',
'Deprecations|The logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0.',
)
"
>

View File

@ -409,17 +409,13 @@ export default {
<div>
<gl-alert
v-if="!isDeprecationNoticeDismissed"
:title="__('Feature deprecation and removal')"
:title="__('Feature deprecation')"
class="mb-3"
variant="danger"
variant="warning"
@dismiss="isDeprecationNoticeDismissed = true"
>
<gl-sprintf
:message="
s__(
'Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0.',
)
"
:message="s__('Deprecations|The metrics feature was deprecated in GitLab 14.7.')"
>
<template #epic="{ content }">
<gl-link href="https://gitlab.com/groups/gitlab-org/-/epics/7188" target="_blank">{{

View File

@ -1,16 +1,10 @@
<script>
import { GlButtonGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { s__, __ } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import { s__ } from '~/locale';
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
export default {
components: {
GlButtonGroup,
GlButton,
ModalCopyButton,
},
directives: {
GlTooltip: GlTooltipDirective,
InputCopyToggleVisibility,
},
props: {
value: {
@ -19,65 +13,21 @@ export default {
default: '',
},
},
data() {
return {
isMasked: true,
};
},
computed: {
maskLabel() {
if (this.isMasked) {
return __('Click to reveal');
}
return __('Click to hide');
},
maskIcon() {
if (this.isMasked) {
return 'eye';
}
return 'eye-slash';
},
displayedValue() {
if (this.isMasked && this.value?.length) {
return '*'.repeat(this.value.length);
}
return this.value;
},
},
methods: {
onToggleMasked() {
this.isMasked = !this.isMasked;
},
onCopied() {
onCopy() {
// value already in the clipboard, simply notify the user
this.$toast?.show(s__('Runners|Registration token copied!'));
},
},
i18n: {
copyLabel: s__('Runners|Copy registration token'),
},
I18N_COPY_BUTTON_TITLE: s__('Runners|Copy registration token'),
};
</script>
<template>
<gl-button-group>
<gl-button class="gl-font-monospace" data-testid="token-value" label>
{{ displayedValue }}
</gl-button>
<gl-button
v-gl-tooltip
:aria-label="maskLabel"
:title="maskLabel"
:icon="maskIcon"
class="gl-w-auto! gl-flex-shrink-0!"
data-testid="toggle-masked"
@click.stop="onToggleMasked"
/>
<modal-copy-button
class="gl-w-auto! gl-flex-shrink-0!"
:aria-label="$options.i18n.copyLabel"
:title="$options.i18n.copyLabel"
:text="value"
@success="onCopied"
/>
</gl-button-group>
<input-copy-toggle-visibility
class="gl-m-0"
:value="value"
data-testid="token-value"
:copy-button-title="$options.I18N_COPY_BUTTON_TITLE"
@copy="onCopy"
/>
</template>

View File

@ -110,7 +110,7 @@ export default {
v-gl-tooltip.hover="toggleVisibilityLabel"
:aria-label="toggleVisibilityLabel"
:icon="toggleVisibilityIcon"
@click="handleToggleVisibilityButtonClick"
@click.stop="handleToggleVisibilityButtonClick"
/>
<clipboard-button
v-if="showCopyButton"

View File

@ -15,7 +15,7 @@
= s_('Deprecations|Feature deprecation and removal')
.gl-alert-body
%p
= html_escape(s_('Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
= html_escape(s_('Deprecations|The metrics feature was deprecated in GitLab 14.7. The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
= render 'projects/settings/operations/metrics_dashboard'
= render 'projects/settings/operations/tracing'

View File

@ -14,7 +14,7 @@
= s_('Deprecations|Feature deprecation and removal')
.gl-alert-body
%p
= html_escape(s_('Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
= html_escape(s_('Deprecations|The logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
- if @project.tracing_external_url.present?
%h3.page-title= _('Tracing')

View File

@ -55,9 +55,9 @@ Example:
There are two ways to configure the approval requirements:
- [Unified approval setting](#unified-approval-setting) ... You can define who can execute **and** approve deployments.
This is useful when there is no separation of duties between executors and approvers in your oraganization.
This is useful when there is no separation of duties between executors and approvers in your organization.
- [Multiple approval rules](#multiple-approval-rules) ... You can define who can execute **or** approve deployments.
This is useful when there is a separation of duties between executors and approvers in your oraganization.
This is useful when there is a separation of duties between executors and approvers in your organization.
NOTE:
Multiple approval rules is a more flexible option than the unified approval setting, thus both configurations shouldn't

View File

@ -40,16 +40,20 @@ module Gitlab
# 1. The minimum value for the partitioning column in the table
# 2. If no data is present yet, the current month
def partition_table_by_date(table_name, column_name, min_date: nil, max_date: nil)
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_ddl_mode!
assert_table_is_allowed(table_name)
assert_not_in_transaction_block(scope: ERROR_SCOPE)
max_date ||= Date.today + 1.month
min_date ||= connection.select_one(<<~SQL)['minimum'] || max_date - 1.month
SELECT date_trunc('MONTH', MIN(#{column_name})) AS minimum
FROM #{table_name}
SQL
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do
min_date ||= connection.select_one(<<~SQL)['minimum'] || max_date - 1.month
SELECT date_trunc('MONTH', MIN(#{column_name})) AS minimum
FROM #{table_name}
SQL
end
raise "max_date #{max_date} must be greater than min_date #{min_date}" if min_date >= max_date
@ -154,6 +158,8 @@ module Gitlab
# finalize_backfilling_partitioned_table :audit_events
#
def finalize_backfilling_partitioned_table(table_name)
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.require_dml_mode!
assert_table_is_allowed(table_name)
assert_not_in_transaction_block(scope: ERROR_SCOPE)
@ -170,8 +176,10 @@ module Gitlab
primary_key = connection.primary_key(table_name)
copy_missed_records(table_name, partitioned_table_name, primary_key)
disable_statement_timeout do
execute("VACUUM FREEZE ANALYZE #{partitioned_table_name}")
Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do
disable_statement_timeout do
execute("VACUUM FREEZE ANALYZE #{partitioned_table_name}")
end
end
end

View File

@ -12654,10 +12654,16 @@ msgstr ""
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
msgstr ""
msgid "Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0."
msgid "Deprecations|The logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0."
msgstr ""
msgid "Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
msgid "Deprecations|The logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
msgstr ""
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
msgstr ""
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7. The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
msgstr ""
msgid "Deprioritize label"
@ -15646,7 +15652,7 @@ msgstr ""
msgid "Feature Flags"
msgstr ""
msgid "Feature deprecation and removal"
msgid "Feature deprecation"
msgstr ""
msgid "Feature flag status"

View File

@ -12,7 +12,7 @@ exports[`Confidential merge request project form group component renders empty s
<!---->
<p
class="text-muted mt-1 mb-0"
class="gl-text-gray-600 gl-mt-1 gl-mb-0"
>
No forks are available to you.
@ -27,7 +27,7 @@ exports[`Confidential merge request project form group component renders empty s
</a>
and set the fork's visibility to private.
<gl-link-stub
class="w-auto p-0 d-inline-block text-primary bg-transparent"
class="gl-w-auto gl-p-0 gl-display-inline-block gl-bg-transparent"
href="/help"
target="_blank"
>
@ -62,13 +62,13 @@ exports[`Confidential merge request project form group component renders fork dr
/>
<p
class="text-muted mt-1 mb-0"
class="gl-text-gray-600 gl-mt-1 gl-mb-0"
>
To protect this issue's confidentiality, a private fork of this project was selected.
<gl-link-stub
class="w-auto p-0 d-inline-block text-primary bg-transparent"
class="gl-w-auto gl-p-0 gl-display-inline-block gl-bg-transparent"
href="/help"
target="_blank"
>

View File

@ -4,7 +4,7 @@ import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue';
import { createStore } from '~/mr_notes/stores';
import NoteForm from '~/notes/components/note_form.vue';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { noteableDataMock } from '../../notes/mock_data';
import { noteableDataMock } from 'jest/notes/mock_data';
import diffFileMockData from '../mock_data/diff_file';
jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal', () => {

View File

@ -13,7 +13,7 @@ import {
} from '~/diffs/constants';
import * as utils from '~/diffs/store/utils';
import { MERGE_REQUEST_NOTEABLE_TYPE } from '~/notes/constants';
import { noteableDataMock } from '../../notes/mock_data';
import { noteableDataMock } from 'jest/notes/mock_data';
import diffFileMockData from '../mock_data/diff_file';
import { diffMetadata } from '../mock_data/diff_metadata';

View File

@ -17,11 +17,11 @@ exports[`Dashboard template matches the default snapshot 1`] = `
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
title="Feature deprecation and removal"
variant="danger"
title="Feature deprecation"
variant="warning"
>
<gl-sprintf-stub
message="The metrics, logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0."
message="The metrics feature was deprecated in GitLab 14.7."
/>
<gl-sprintf-stub

View File

@ -4,7 +4,7 @@ import { nextTick } from 'vue';
import diffDiscussionHeader from '~/notes/components/diff_discussion_header.vue';
import createStore from '~/notes/stores';
import mockDiffFile from '../../diffs/mock_data/diff_discussions';
import mockDiffFile from 'jest/diffs/mock_data/diff_discussions';
import { discussionMock } from '../mock_data';
describe('diff_discussion_header component', () => {

View File

@ -8,6 +8,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import RegistrationDropdown from '~/runner/components/registration/registration_dropdown.vue';
import RegistrationToken from '~/runner/components/registration/registration_token.vue';
import RegistrationTokenResetDropdownItem from '~/runner/components/registration/registration_token_reset_dropdown_item.vue';
import { INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE } from '~/runner/constants';
@ -30,11 +31,11 @@ describe('RegistrationDropdown', () => {
const findRegistrationInstructionsDropdownItem = () => wrapper.findComponent(GlDropdownItem);
const findTokenDropdownItem = () => wrapper.findComponent(GlDropdownForm);
const findRegistrationToken = () => wrapper.findComponent(RegistrationToken);
const findRegistrationTokenInput = () => wrapper.findByTestId('token-value').find('input');
const findTokenResetDropdownItem = () =>
wrapper.findComponent(RegistrationTokenResetDropdownItem);
const findToggleMaskButton = () => wrapper.findByTestId('toggle-masked');
const createComponent = ({ props = {}, ...options } = {}, mountFn = shallowMount) => {
wrapper = extendedWrapper(
mountFn(RegistrationDropdown, {
@ -134,9 +135,7 @@ describe('RegistrationDropdown', () => {
it('Displays masked value by default', () => {
createComponent({}, mount);
expect(findTokenDropdownItem().text()).toMatchInterpolatedText(
`Registration token ${maskToken}`,
);
expect(findRegistrationTokenInput().element.value).toBe(maskToken);
});
});
@ -155,16 +154,14 @@ describe('RegistrationDropdown', () => {
});
it('Updates the token when it gets reset', async () => {
const newToken = 'mock1';
createComponent({}, mount);
const newToken = 'mock1';
expect(findRegistrationTokenInput().props('value')).not.toBe(newToken);
findTokenResetDropdownItem().vm.$emit('tokenReset', newToken);
findToggleMaskButton().vm.$emit('click', { stopPropagation: jest.fn() });
await nextTick();
expect(findTokenDropdownItem().text()).toMatchInterpolatedText(
`Registration token ${newToken}`,
);
expect(findRegistrationToken().props('value')).toBe(newToken);
});
});

View File

@ -1,20 +1,17 @@
import { nextTick } from 'vue';
import { GlToast } from '@gitlab/ui';
import { createLocalVue } from '@vue/test-utils';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RegistrationToken from '~/runner/components/registration/registration_token.vue';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
const mockToken = '01234567890';
const mockMasked = '***********';
describe('RegistrationToken', () => {
let wrapper;
let stopPropagation;
let showToast;
const findToggleMaskButton = () => wrapper.findByTestId('toggle-masked');
const findCopyButton = () => wrapper.findComponent(ModalCopyButton);
const findInputCopyToggleVisibility = () => wrapper.findComponent(InputCopyToggleVisibility);
const vueWithGlToast = () => {
const localVue = createLocalVue();
@ -22,10 +19,14 @@ describe('RegistrationToken', () => {
return localVue;
};
const createComponent = ({ props = {}, withGlToast = true } = {}) => {
const createComponent = ({
props = {},
withGlToast = true,
mountFn = shallowMountExtended,
} = {}) => {
const localVue = withGlToast ? vueWithGlToast() : undefined;
wrapper = shallowMountExtended(RegistrationToken, {
wrapper = mountFn(RegistrationToken, {
propsData: {
value: mockToken,
...props,
@ -36,61 +37,33 @@ describe('RegistrationToken', () => {
showToast = wrapper.vm.$toast ? jest.spyOn(wrapper.vm.$toast, 'show') : null;
};
beforeEach(() => {
stopPropagation = jest.fn();
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('Displays value and copy button', () => {
createComponent();
expect(findInputCopyToggleVisibility().props('value')).toBe(mockToken);
expect(findInputCopyToggleVisibility().props('copyButtonTitle')).toBe(
'Copy registration token',
);
});
// Component integration test to ensure secure masking
it('Displays masked value by default', () => {
expect(wrapper.text()).toBe(mockMasked);
});
createComponent({ mountFn: mountExtended });
it('Displays button to reveal token', () => {
expect(findToggleMaskButton().attributes('aria-label')).toBe('Click to reveal');
});
it('Can copy the original token value', () => {
expect(findCopyButton().props('text')).toBe(mockToken);
});
describe('When the reveal icon is clicked', () => {
beforeEach(() => {
findToggleMaskButton().vm.$emit('click', { stopPropagation });
});
it('Click event is not propagated', async () => {
expect(stopPropagation).toHaveBeenCalledTimes(1);
});
it('Displays the actual value', () => {
expect(wrapper.text()).toBe(mockToken);
});
it('Can copy the original token value', () => {
expect(findCopyButton().props('text')).toBe(mockToken);
});
it('Displays button to mask token', () => {
expect(findToggleMaskButton().attributes('aria-label')).toBe('Click to hide');
});
it('When user clicks again, displays masked value', async () => {
findToggleMaskButton().vm.$emit('click', { stopPropagation });
await nextTick();
expect(wrapper.text()).toBe(mockMasked);
expect(findToggleMaskButton().attributes('aria-label')).toBe('Click to reveal');
});
expect(wrapper.find('input').element.value).toBe(mockMasked);
});
describe('When the copy to clipboard button is clicked', () => {
beforeEach(() => {
createComponent();
});
it('shows a copied message', () => {
findCopyButton().vm.$emit('success');
findInputCopyToggleVisibility().vm.$emit('copy');
expect(showToast).toHaveBeenCalledTimes(1);
expect(showToast).toHaveBeenCalledWith('Registration token copied!');
@ -98,7 +71,7 @@ describe('RegistrationToken', () => {
it('does not fail when toast is not defined', () => {
createComponent({ withGlToast: false });
findCopyButton().vm.$emit('success');
findInputCopyToggleVisibility().vm.$emit('copy');
// This block also tests for unhandled errors
expect(showToast).toBeNull();

View File

@ -8,7 +8,7 @@ import { redirectTo } from '~/lib/utils/url_utility';
import EditUserList from '~/user_lists/components/edit_user_list.vue';
import UserListForm from '~/user_lists/components/user_list_form.vue';
import createStore from '~/user_lists/store/edit';
import { userList } from '../../feature_flags/mock_data';
import { userList } from 'jest/feature_flags/mock_data';
jest.mock('~/api');
jest.mock('~/lib/utils/url_utility');

View File

@ -7,7 +7,7 @@ import Api from '~/api';
import { redirectTo } from '~/lib/utils/url_utility';
import NewUserList from '~/user_lists/components/new_user_list.vue';
import createStore from '~/user_lists/store/new';
import { userList } from '../../feature_flags/mock_data';
import { userList } from 'jest/feature_flags/mock_data';
jest.mock('~/api');
jest.mock('~/lib/utils/url_utility');

View File

@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils';
import Form from '~/user_lists/components/user_list_form.vue';
import { userList } from '../../feature_flags/mock_data';
import { userList } from 'jest/feature_flags/mock_data';
describe('user_lists/components/user_list_form', () => {
let wrapper;

View File

@ -7,7 +7,7 @@ import Api from '~/api';
import UserList from '~/user_lists/components/user_list.vue';
import createStore from '~/user_lists/store/show';
import { parseUserIds, stringifyUserIds } from '~/user_lists/store/utils';
import { userList } from '../../feature_flags/mock_data';
import { userList } from 'jest/feature_flags/mock_data';
jest.mock('~/api');

View File

@ -9,7 +9,7 @@ import UserListsComponent from '~/user_lists/components/user_lists.vue';
import UserListsTable from '~/user_lists/components/user_lists_table.vue';
import createStore from '~/user_lists/store/index';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import { userList } from '../../feature_flags/mock_data';
import { userList } from 'jest/feature_flags/mock_data';
jest.mock('~/api');

View File

@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils';
import * as timeago from 'timeago.js';
import { nextTick } from 'vue';
import UserListsTable from '~/user_lists/components/user_lists_table.vue';
import { userList } from '../../feature_flags/mock_data';
import { userList } from 'jest/feature_flags/mock_data';
jest.mock('timeago.js', () => ({
format: jest.fn().mockReturnValue('2 weeks ago'),

View File

@ -89,8 +89,11 @@ describe('InputCopyToggleVisibility', () => {
});
describe('when clicked', () => {
let event;
beforeEach(async () => {
await findRevealButton().trigger('click');
event = { stopPropagation: jest.fn() };
await findRevealButton().trigger('click', event);
});
it('displays value', () => {
@ -110,6 +113,11 @@ describe('InputCopyToggleVisibility', () => {
it('emits `visibility-change` event', () => {
expect(wrapper.emitted('visibility-change')[0]).toEqual([true]);
});
it('stops propagation on click event', () => {
// in case the input is located in a dropdown or modal
expect(event.stopPropagation).toHaveBeenCalledTimes(1);
});
});
});

View File

@ -16,7 +16,7 @@ import {
searchResponseOnMR,
projectMembersResponse,
participantsQueryResponse,
} from '../../sidebar/mock_data';
} from 'jest/sidebar/mock_data';
const assignee = {
id: 'gid://gitlab/User/4',

View File

@ -125,6 +125,17 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
expect_table_partitioned_by(partitioned_table, [partition_column])
end
it 'requires the migration helper to be run in DDL mode' do
expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_ddl_mode!)
migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
expect(connection.table_exists?(partitioned_table)).to be(true)
expect(connection.primary_key(partitioned_table)).to eq(new_primary_key)
expect_table_partitioned_by(partitioned_table, [partition_column])
end
it 'changes the primary key datatype to bigint' do
migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
@ -191,6 +202,8 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
it 'creates a partition spanning over each month from the first record' do
expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:with_suppressed).and_yield
migration.partition_table_by_date source_table, partition_column, max_date: max_date
expect_range_partitions_for(partitioned_table, {
@ -206,6 +219,8 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
context 'without data' do
it 'creates the catchall partition plus two actual partition' do
expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:with_suppressed).and_yield
migration.partition_table_by_date source_table, partition_column, max_date: max_date
expect_range_partitions_for(partitioned_table, {
@ -536,6 +551,16 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
migration.finalize_backfilling_partitioned_table source_table
end
it 'requires the migration helper to execute in DML mode' do
expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_dml_mode!)
expect(Gitlab::BackgroundMigration).to receive(:steal)
.with(described_class::MIGRATION_CLASS_NAME)
.and_yield(background_job)
migration.finalize_backfilling_partitioned_table source_table
end
end
context 'when there is missed data' do
@ -627,6 +652,7 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
allow(backfill).to receive(:perform).and_return(1)
end
expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:with_suppressed).and_yield
expect(migration).to receive(:disable_statement_timeout).and_call_original
expect(migration).to receive(:execute).with("VACUUM FREEZE ANALYZE #{partitioned_table}")

View File

@ -35,11 +35,11 @@ RSpec.shared_examples 'shows and resets runner registration token' do
it 'has a registration token' do
click_on 'Click to reveal'
expect(page.find('[data-testid="token-value"]')).to have_content(registration_token)
expect(page.find('[data-testid="token-value"] input').value).to have_content(registration_token)
end
describe 'reset registration token' do
let!(:old_registration_token) { find('[data-testid="token-value"]').text }
let!(:old_registration_token) { find('[data-testid="token-value"] input').value }
before do
click_on 'Reset registration token'