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:
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml1
-rw-r--r--app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue2
-rw-r--r--app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue4
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue6
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue4
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue2
-rw-r--r--app/assets/javascripts/clusters_list/constants.js4
-rw-r--r--app/assets/javascripts/deploy_tokens/components/revoke_button.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue4
-rw-r--r--app/assets/javascripts/environments/components/delete_environment_modal.vue4
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js6
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue4
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table.vue2
-rw-r--r--app/assets/javascripts/issuable/components/issuable_by_email.vue2
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue6
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue4
-rw-r--r--app/assets/javascripts/issues_list/service_desk_helper.js6
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/app.vue36
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue50
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/index.js3
-rw-r--r--app/assets/javascripts/lib/utils/datetime/date_format_utility.js48
-rw-r--r--app/assets/javascripts/logs/components/environment_logs.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue4
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue2
-rw-r--r--app/assets/javascripts/pages/groups/new/components/app.vue2
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue4
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue6
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue4
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue4
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue4
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue8
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue4
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue6
-rw-r--r--app/assets/javascripts/projects/new/components/app.vue2
-rw-r--r--app/assets/javascripts/projects/storage_counter/constants.js2
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue2
-rw-r--r--app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue4
-rw-r--r--app/assets/javascripts/related_merge_requests/store/actions.js4
-rw-r--r--app/assets/javascripts/search/sidebar/components/radio_filter.vue4
-rw-r--r--app/assets/javascripts/static_site_editor/pages/success.vue2
-rw-r--r--app/assets/javascripts/user_lists/components/user_lists_table.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue2
-rw-r--r--app/assets/javascripts/vue_shared/directives/validation.js6
-rw-r--r--app/helpers/ci/runners_helper.rb19
-rw-r--r--app/models/ci/runner.rb8
-rw-r--r--config/feature_flags/development/use_model_load_balancing.yml8
-rw-r--r--data/deprecations/14-5-runner-api-status-does-contain-paused.yml16
-rw-r--r--doc/administration/gitaly/praefect.md73
-rw-r--r--doc/development/contributing/merge_request_workflow.md18
-rw-r--r--lib/api/entities/ci/runner.rb4
-rw-r--r--lib/gitlab/database/load_balancing/setup.rb77
-rw-r--r--lib/gitlab/import_export/attributes_permitter.rb2
-rw-r--r--lib/gitlab/import_export/project/import_export.yml238
-rw-r--r--locale/gitlab.pot6
-rw-r--r--package.json2
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb69
-rw-r--r--qa/qa/support/matchers/have_matcher.rb1
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/app_spec.js29
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js50
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js10
-rw-r--r--spec/lib/gitlab/database/load_balancing/setup_spec.rb181
-rw-r--r--spec/lib/gitlab/import_export/attributes_permitter_spec.rb31
-rw-r--r--spec/models/ci/runner_spec.rb41
-rw-r--r--spec/models/clusters/applications/runner_spec.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb4
-rw-r--r--yarn.lock8
68 files changed, 920 insertions, 265 deletions
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 9a13600a86c..478fd01f541 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -22,6 +22,7 @@
variables:
DECOMPOSED_DB: "true"
GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: "main"
+ GITLAB_USE_MODEL_LOAD_BALANCING: "true"
.rspec-base:
extends: .rails-job-base
diff --git a/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue b/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
index ed90343777d..e949498c55b 100644
--- a/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
+++ b/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
@@ -138,7 +138,7 @@ export default {
/>
</form>
<template #modal-footer>
- <gl-button @click="onCancel">{{ s__('Cancel') }}</gl-button>
+ <gl-button @click="onCancel">{{ __('Cancel') }}</gl-button>
<gl-button
:disabled="!canSubmit"
category="secondary"
diff --git a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
index 1eb4832a2a3..63ec40d4ec6 100644
--- a/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
+++ b/app/assets/javascripts/analytics/usage_trends/components/usage_counts.vue
@@ -3,7 +3,7 @@ import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import createFlash from '~/flash';
import { number } from '~/lib/utils/unit_format';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import usageTrendsCountQuery from '../graphql/queries/usage_trends_count.query.graphql';
const defaultPrecision = 0;
@@ -52,7 +52,7 @@ export default {
mergeRequests: s__('UsageTrends|Merge requests'),
pipelines: s__('UsageTrends|Pipelines'),
},
- loadCountsError: s__('Could not load usage counts. Please refresh the page to try again.'),
+ loadCountsError: __('Could not load usage counts. Please refresh the page to try again.'),
},
};
</script>
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index 825807e833e..0303930de5d 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -2,7 +2,7 @@
import { GlSprintf, GlModal } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import createFlash from '~/flash';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import Badge from './badge.vue';
import BadgeForm from './badge_form.vue';
import BadgeList from './badge_list.vue';
@@ -25,13 +25,13 @@ export default {
...mapState(['badgeInModal', 'isEditing']),
primaryProps() {
return {
- text: s__('Delete badge'),
+ text: __('Delete badge'),
attributes: [{ category: 'primary' }, { variant: 'danger' }],
};
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
},
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index a3278f8bde2..e75aa523ed0 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -1,7 +1,7 @@
<script>
import { GlModal, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
import Cookies from 'js-cookie';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin();
@@ -69,7 +69,7 @@ export default {
},
},
i18n: {
- modalTitle: s__("That's it, well done!"),
+ modalTitle: __("That's it, well done!"),
pipelinesButton: s__('MR widget|See your pipeline in action'),
mergeRequestButton: s__('MR widget|Back to the Merge request'),
bodyMessage: s__(
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index b0b787ac3f7..98db620e3ab 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -159,7 +159,7 @@ export default {
)
}}</span>
<template #modal-footer>
- <gl-button variant="secondary" @click="handleCancel">{{ s__('Cancel') }}</gl-button>
+ <gl-button variant="secondary" @click="handleCancel">{{ __('Cancel') }}</gl-button>
<template v-if="confirmCleanup">
<gl-button
:disabled="!canSubmit"
diff --git a/app/assets/javascripts/clusters_list/constants.js b/app/assets/javascripts/clusters_list/constants.js
index 0bade1fc281..ffa28f516e6 100644
--- a/app/assets/javascripts/clusters_list/constants.js
+++ b/app/assets/javascripts/clusters_list/constants.js
@@ -91,7 +91,7 @@ export const I18N_INSTALL_AGENT_MODAL = {
),
basicInstallTitle: s__('ClusterAgents|Recommended installation method'),
- basicInstallBody: s__(
+ basicInstallBody: __(
`Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command.`,
),
@@ -100,7 +100,7 @@ export const I18N_INSTALL_AGENT_MODAL = {
'ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}.',
),
- registrationErrorTitle: s__('Failed to register Agent'),
+ registrationErrorTitle: __('Failed to register Agent'),
unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
};
diff --git a/app/assets/javascripts/deploy_tokens/components/revoke_button.vue b/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
index e026391ae22..fdf8b7796bf 100644
--- a/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
+++ b/app/assets/javascripts/deploy_tokens/components/revoke_button.vue
@@ -62,7 +62,7 @@ export default {
</gl-sprintf>
{{ s__('DeployTokens|This action cannot be undone.') }}
<template #modal-footer>
- <gl-button category="secondary" @click="cancelHandler">{{ s__('Cancel') }}</gl-button>
+ <gl-button category="secondary" @click="cancelHandler">{{ __('Cancel') }}</gl-button>
<gl-button
category="primary"
variant="danger"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 746646948fe..46726a8fa07 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -50,7 +50,7 @@ export default {
mixins: [glFeatureFlagsMixin(), IdState({ idProp: (vm) => vm.diffFile.file_hash })],
i18n: {
...DIFF_FILE_HEADER,
- compareButtonLabel: s__('Compare submodule commit revisions'),
+ compareButtonLabel: __('Compare submodule commit revisions'),
},
props: {
discussionPath: {
@@ -130,7 +130,7 @@ export default {
const truncatedOldSha = escape(truncateSha(this.diffFile.submodule_compare.old_sha));
const truncatedNewSha = escape(truncateSha(this.diffFile.submodule_compare.new_sha));
return sprintf(
- s__('Compare %{oldCommitId}...%{newCommitId}'),
+ __('Compare %{oldCommitId}...%{newCommitId}'),
{
oldCommitId: `<span class="commit-sha">${truncatedOldSha}</span>`,
newCommitId: `<span class="commit-sha">${truncatedNewSha}</span>`,
diff --git a/app/assets/javascripts/environments/components/delete_environment_modal.vue b/app/assets/javascripts/environments/components/delete_environment_modal.vue
index 2eb2be351b3..26ec882472b 100644
--- a/app/assets/javascripts/environments/components/delete_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/delete_environment_modal.vue
@@ -1,6 +1,6 @@
<script>
import { GlTooltipDirective, GlModal } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
export default {
@@ -27,7 +27,7 @@ export default {
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
confirmDeleteMessage() {
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 85cff73cc3e..0f9741784d6 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -6,7 +6,7 @@ import Visibility from 'visibilityjs';
import createFlash from '~/flash';
import Poll from '../../lib/utils/poll';
import { getParameterByName } from '../../lib/utils/url_utility';
-import { s__ } from '../../locale';
+import { s__, __ } from '../../locale';
import tabs from '../../vue_shared/components/navigation_tabs.vue';
import tablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import container from '../components/container.vue';
@@ -207,13 +207,13 @@ export default {
tabs() {
return [
{
- name: s__('Available'),
+ name: __('Available'),
scope: 'available',
count: this.state.availableCounter,
isActive: this.scope === 'available',
},
{
- name: s__('Stopped'),
+ name: __('Stopped'),
scope: 'stopped',
count: this.state.stoppedCounter,
isActive: this.scope === 'stopped',
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index e8541d3a4c3..1c5a00568eb 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -2,7 +2,7 @@
import { GlModal, GlButton } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
import createFlash from '~/flash';
-import { __, sprintf, s__ } from '~/locale';
+import { __, sprintf } from '~/locale';
import { modalTypes } from '../../constants';
import { trimPathComponents, getPathParent } from '../../utils';
@@ -58,7 +58,7 @@ export default {
if (this.modalType === modalTypes.rename) {
if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
createFlash({
- message: sprintf(s__('The name "%{name}" is already taken in this directory.'), {
+ message: sprintf(__('The name "%{name}" is already taken in this directory.'), {
name: this.entryName,
}),
fadeTransition: false,
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
index eaa08cb1529..ec6025c84bb 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
@@ -517,7 +517,7 @@ export default {
<gl-empty-state
v-else-if="!hasGroups"
:title="s__('BulkImport|You have no groups to import')"
- :description="s__('Check your source instance permissions.')"
+ :description="__('Check your source instance permissions.')"
/>
<template v-else>
<div
diff --git a/app/assets/javascripts/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue
index 6e300831e00..799d2bdc9e2 100644
--- a/app/assets/javascripts/issuable/components/issuable_by_email.vue
+++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue
@@ -166,7 +166,7 @@ export default {
</gl-sprintf>
</p>
<template #modal-footer>
- <gl-button category="secondary" @click="cancelHandler">{{ s__('Cancel') }}</gl-button>
+ <gl-button category="secondary" @click="cancelHandler">{{ __('Cancel') }}</gl-button>
</template>
</gl-modal>
</div>
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index e4173995fc6..d3b58ed3012 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -4,7 +4,7 @@ import Visibility from 'visibilityjs';
import createFlash from '~/flash';
import Poll from '~/lib/utils/poll';
import { visitUrl } from '~/lib/utils/url_utility';
-import { __, s__, sprintf } from '~/locale';
+import { __, sprintf } from '~/locale';
import {
IssuableStatus,
IssuableStatusText,
@@ -250,7 +250,7 @@ export default {
return false;
},
defaultErrorMessage() {
- return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType });
+ return sprintf(__('Error updating %{issuableType}'), { issuableType: this.issuableType });
},
isClosed() {
return this.issuableStatus === IssuableStatus.Closed;
@@ -437,7 +437,7 @@ export default {
})
.catch(() => {
createFlash({
- message: sprintf(s__('Error deleting %{issuableType}'), {
+ message: sprintf(__('Error deleting %{issuableType}'), {
issuableType: this.issuableType,
}),
});
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index d8ca28e33b6..9dc122d426c 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -2,7 +2,7 @@
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import $ from 'jquery';
import createFlash from '~/flash';
-import { s__, sprintf } from '~/locale';
+import { __, sprintf } from '~/locale';
import TaskList from '../../task_list';
import animateMixin from '../mixins/animate';
@@ -104,7 +104,7 @@ export default {
taskListUpdateError() {
createFlash({
message: sprintf(
- s__(
+ __(
'Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again.',
),
{
diff --git a/app/assets/javascripts/issues_list/service_desk_helper.js b/app/assets/javascripts/issues_list/service_desk_helper.js
index 5cccf2e6bce..815f338f1a0 100644
--- a/app/assets/javascripts/issues_list/service_desk_helper.js
+++ b/app/assets/javascripts/issues_list/service_desk_helper.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
/**
* Generates empty state messages for Service Desk issues list.
@@ -25,7 +25,7 @@ export function generateMessages(emptyStateMeta) {
const commonDescription = `
<span>${serviceDeskSupportedMessage}</span>
- <a href="${serviceDeskHelpPage}">${s__('Learn more.')}</a>`;
+ <a href="${serviceDeskHelpPage}">${__('Learn more.')}</a>`;
return {
serviceDeskEnabledAndCanEditProjectSettings: {
@@ -60,7 +60,7 @@ export function generateMessages(emptyStateMeta) {
'ServiceDesk|To enable Service Desk on this instance, an instance administrator must first set up incoming email.',
),
primaryLink: incomingEmailHelpPage,
- primaryText: s__('Learn more.'),
+ primaryText: __('Learn more.'),
},
serviceDeskIsNotEnabled: {
title: s__('ServiceDesk|Service Desk is not enabled'),
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
index 825d9625c8d..9b3cd04c4e2 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
@@ -1,55 +1,43 @@
<script>
-import { GlAlert, GlButton, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { mapState, mapMutations } from 'vuex';
-import { retrieveAlert, getLocation } from '~/jira_connect/subscriptions/utils';
+import { retrieveAlert } from '~/jira_connect/subscriptions/utils';
import { SET_ALERT } from '../store/mutation_types';
import SubscriptionsList from './subscriptions_list.vue';
import AddNamespaceButton from './add_namespace_button.vue';
+import SignInButton from './sign_in_button.vue';
export default {
name: 'JiraConnectApp',
components: {
GlAlert,
- GlButton,
GlLink,
GlSprintf,
SubscriptionsList,
AddNamespaceButton,
+ SignInButton,
},
inject: {
usersPath: {
default: '',
},
},
- data() {
- return {
- location: '',
- };
- },
computed: {
...mapState(['alert']),
- usersPathWithReturnTo() {
- if (this.location) {
- return `${this.usersPath}?return_to=${this.location}`;
- }
-
- return this.usersPath;
- },
shouldShowAlert() {
return Boolean(this.alert?.message);
},
+ userSignedIn() {
+ return Boolean(!this.usersPath);
+ },
},
created() {
this.setInitialAlert();
- this.setLocation();
},
methods: {
...mapMutations({
setAlert: SET_ALERT,
}),
- async setLocation() {
- this.location = await getLocation();
- },
setInitialAlert() {
const { linkUrl, title, message, variant } = retrieveAlert() || {};
this.setAlert({ linkUrl, title, message, variant });
@@ -82,15 +70,7 @@ export default {
<div class="jira-connect-app-body gl-my-7 gl-px-5 gl-pb-4">
<div class="gl-display-flex gl-justify-content-end">
- <gl-button
- v-if="usersPath"
- category="primary"
- variant="info"
- class="gl-align-self-center"
- :href="usersPathWithReturnTo"
- target="_blank"
- >{{ s__('Integrations|Sign in to add namespaces') }}</gl-button
- >
+ <sign-in-button v-if="!userSignedIn" :users-path="usersPath" />
<add-namespace-button v-else />
</div>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue
new file mode 100644
index 00000000000..08f15519679
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_button.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { getLocation } from '~/jira_connect/subscriptions/utils';
+import { objectToQuery } from '~/lib/utils/url_utility';
+
+export default {
+ components: {
+ GlButton,
+ },
+ props: {
+ usersPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ location: '',
+ };
+ },
+ computed: {
+ usersPathWithReturnTo() {
+ if (this.location) {
+ const queryParams = {
+ return_to: this.location,
+ };
+
+ return `${this.usersPath}?${objectToQuery(queryParams)}`;
+ }
+
+ return this.usersPath;
+ },
+ },
+ created() {
+ this.setLocation();
+ },
+ methods: {
+ async setLocation() {
+ this.location = await getLocation();
+ },
+ },
+};
+</script>
+<template>
+ <gl-button category="primary" variant="info" :href="usersPathWithReturnTo" target="_blank">
+ <slot>
+ {{ s__('Integrations|Sign in to add namespaces') }}
+ </slot>
+ </gl-button>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/index.js b/app/assets/javascripts/jira_connect/subscriptions/index.js
index f1262be0174..46a736c991e 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/index.js
+++ b/app/assets/javascripts/jira_connect/subscriptions/index.js
@@ -11,6 +11,9 @@ import { getLocation, sizeToParent } from './utils';
const store = createStore();
+/**
+ * Add `return_to` query param to all HAML-defined GitLab sign in links.
+ */
const updateSignInLinks = async () => {
const location = await getLocation();
Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
diff --git a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
index 3c446c21865..7bff2bf3e47 100644
--- a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js
@@ -14,33 +14,33 @@ import { s__, n__, __, sprintf } from '../../../locale';
export const getMonthNames = (abbreviated) => {
if (abbreviated) {
return [
- s__('Jan'),
- s__('Feb'),
- s__('Mar'),
- s__('Apr'),
- s__('May'),
- s__('Jun'),
- s__('Jul'),
- s__('Aug'),
- s__('Sep'),
- s__('Oct'),
- s__('Nov'),
- s__('Dec'),
+ __('Jan'),
+ __('Feb'),
+ __('Mar'),
+ __('Apr'),
+ __('May'),
+ __('Jun'),
+ __('Jul'),
+ __('Aug'),
+ __('Sep'),
+ __('Oct'),
+ __('Nov'),
+ __('Dec'),
];
}
return [
- s__('January'),
- s__('February'),
- s__('March'),
- s__('April'),
- s__('May'),
- s__('June'),
- s__('July'),
- s__('August'),
- s__('September'),
- s__('October'),
- s__('November'),
- s__('December'),
+ __('January'),
+ __('February'),
+ __('March'),
+ __('April'),
+ __('May'),
+ __('June'),
+ __('July'),
+ __('August'),
+ __('September'),
+ __('October'),
+ __('November'),
+ __('December'),
];
};
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue
index 2a60825a427..c9e7b034950 100644
--- a/app/assets/javascripts/logs/components/environment_logs.vue
+++ b/app/assets/javascripts/logs/components/environment_logs.vue
@@ -130,7 +130,7 @@ export default {
}}
<a :href="clusterApplicationsDocumentationPath">
<strong>
- {{ s__('View Documentation') }}
+ {{ __('View Documentation') }}
</strong>
</a>
</gl-alert>
diff --git a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
index 1765a2f3d5d..a63008aa382 100644
--- a/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
+++ b/app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue
@@ -63,7 +63,7 @@ export default {
return !(this.form.fileName && !this.form.fileName.endsWith('.yml'));
},
fileNameFeedback() {
- return !this.fileNameState ? s__('The file name should have a .yml extension') : '';
+ return !this.fileNameState ? __('The file name should have a .yml extension') : '';
},
},
mounted() {
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index 831e6dd8f92..33819c78c0f 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -78,8 +78,8 @@ export default {
v-if="resolveAllDiscussionsIssuePath && !allResolved"
v-gl-tooltip
:href="resolveAllDiscussionsIssuePath"
- :title="s__('Create issue to resolve all threads')"
- :aria-label="s__('Create issue to resolve all threads')"
+ :title="__('Create issue to resolve all threads')"
+ :aria-label="__('Create issue to resolve all threads')"
class="new-issue-for-discussion discussion-create-issue-btn"
icon="issue-new"
/>
diff --git a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
index 055d6f40c14..855e06e82ab 100644
--- a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
+++ b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
@@ -70,7 +70,7 @@ export default {
},
primaryProps() {
return {
- text: s__('Delete project'),
+ text: __('Delete project'),
attributes: [{ variant: 'danger' }, { category: 'primary' }, { disabled: !this.canSubmit }],
};
},
diff --git a/app/assets/javascripts/pages/groups/new/components/app.vue b/app/assets/javascripts/pages/groups/new/components/app.vue
index 9aac364d20e..c3ac074cd7a 100644
--- a/app/assets/javascripts/pages/groups/new/components/app.vue
+++ b/app/assets/javascripts/pages/groups/new/components/app.vue
@@ -47,7 +47,7 @@ export default {
<template>
<new-namespace-page
:jump-to-last-persisted-panel="hasErrors"
- :initial-breadcrumb="s__('New group')"
+ :initial-breadcrumb="__('New group')"
:panels="$options.PANELS"
:title="s__('GroupsNew|Create new group')"
persistence-key="new_group_last_active_tab"
diff --git a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
index e42e89ce021..b41611001ab 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
@@ -3,7 +3,7 @@ import { GlModal } from '@gitlab/ui';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
export default {
components: {
@@ -83,7 +83,7 @@ export default {
attributes: [{ variant: 'warning' }],
},
cancelAction: {
- text: s__('Cancel'),
+ text: __('Cancel'),
attributes: [],
},
};
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index 0e646e8c505..85443843684 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -72,18 +72,18 @@ export default {
return [
{
value: KEY_EVERY_DAY,
- text: sprintf(s__(`Every day (at %{time})`), { time: this.formattedTime }),
+ text: sprintf(__(`Every day (at %{time})`), { time: this.formattedTime }),
},
{
value: KEY_EVERY_WEEK,
- text: sprintf(s__('Every week (%{weekday} at %{time})'), {
+ text: sprintf(__('Every week (%{weekday} at %{time})'), {
weekday: this.weekday,
time: this.formattedTime,
}),
},
{
value: KEY_EVERY_MONTH,
- text: sprintf(s__('Every month (Day %{day} at %{time})'), {
+ text: sprintf(__('Every month (Day %{day} at %{time})'), {
day: this.randomDay,
time: this.formattedTime,
}),
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 8deb955842c..384ee1f5034 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -2,7 +2,7 @@
import { GlIcon, GlSprintf, GlLink, GlFormCheckbox, GlToggle } from '@gitlab/ui';
import settingsMixin from 'ee_else_ce/pages/projects/shared/permissions/mixins/settings_pannel_mixin';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import {
visibilityOptions,
visibilityLevelDescriptions,
@@ -31,7 +31,7 @@ export default {
operationsLabel: s__('ProjectSettings|Operations'),
packagesLabel: s__('ProjectSettings|Packages'),
pagesLabel: s__('ProjectSettings|Pages'),
- ciCdLabel: s__('CI/CD'),
+ ciCdLabel: __('CI/CD'),
repositoryLabel: s__('ProjectSettings|Repository'),
requirementsLabel: s__('ProjectSettings|Requirements'),
securityAndComplianceLabel: s__('ProjectSettings|Security & Compliance'),
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
index a8ec731e105..2ce1f0366c1 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -12,7 +12,7 @@ import {
import axios from '~/lib/utils/axios_utils';
import csrf from '~/lib/utils/csrf';
import { setUrlFragment } from '~/lib/utils/url_utility';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import Tracking from '~/tracking';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import {
@@ -83,7 +83,7 @@ export default {
),
},
},
- feedbackTip: s__(
+ feedbackTip: __(
'Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}.',
),
},
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index f163a7c3a8e..1bb82e1d8e6 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlModal, GlModalDirective, GlSegmentedControl } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import { sortOrders, sortOrderOptions } from '../constants';
import RequestWarning from './request_warning.vue';
@@ -55,7 +55,7 @@ export default {
const summary = {};
if (!this.metricDetails.summaryOptions?.hideTotal) {
- summary[s__('Total')] = this.metricDetails.calls;
+ summary[__('Total')] = this.metricDetails.calls;
}
if (!this.metricDetails.summaryOptions?.hideDuration) {
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
index c1739f51f6b..f27c2cd9dca 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -12,7 +12,7 @@ import { produce } from 'immer';
import { fetchPolicies } from '~/lib/graphql';
import { historyPushState } from '~/lib/utils/common_utils';
import { setUrlParams } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
+import { __ } from '~/locale';
import {
BRANCH_PAGINATION_LIMIT,
BRANCH_SEARCH_DEBOUNCE,
@@ -25,9 +25,9 @@ import getLastCommitBranchQuery from '~/pipeline_editor/graphql/queries/client/l
export default {
i18n: {
- dropdownHeader: s__('Switch branch'),
- title: s__('Branches'),
- fetchError: s__('Unable to fetch branch list for this project.'),
+ dropdownHeader: __('Switch branch'),
+ title: __('Branches'),
+ fetchError: __('Unable to fetch branch list for this project.'),
},
inputDebounce: BRANCH_SEARCH_DEBOUNCE,
components: {
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 17cbcabeedb..3cb2dce87d3 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -37,7 +37,7 @@ export default {
},
primaryProps() {
return {
- text: s__('Delete account'),
+ text: __('Delete account'),
attributes: [
{ variant: 'danger', 'data-qa-selector': 'confirm_delete_account_button' },
{ category: 'primary' },
@@ -47,7 +47,7 @@ export default {
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
canSubmit() {
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index 7917a9a75e0..45a6130826d 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -3,7 +3,7 @@ import { GlSafeHtmlDirective as SafeHtml, GlButton, GlModal, GlModalDirective }
import { escape } from 'lodash';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
export default {
components: {
@@ -58,7 +58,7 @@ Please update your Git repository remotes as soon as possible.`),
},
primaryProps() {
return {
- text: s__('Update username'),
+ text: __('Update username'),
attributes: [
{ variant: 'warning' },
{ category: 'primary' },
@@ -68,7 +68,7 @@ Please update your Git repository remotes as soon as possible.`),
},
cancelProps() {
return {
- text: s__('Cancel'),
+ text: __('Cancel'),
};
},
},
diff --git a/app/assets/javascripts/projects/new/components/app.vue b/app/assets/javascripts/projects/new/components/app.vue
index 6e9efc50be8..476d6466cbb 100644
--- a/app/assets/javascripts/projects/new/components/app.vue
+++ b/app/assets/javascripts/projects/new/components/app.vue
@@ -95,7 +95,7 @@ export default {
<template>
<new-namespace-page
- :initial-breadcrumb="s__('New project')"
+ :initial-breadcrumb="__('New project')"
:panels="availablePanels"
:jump-to-last-persisted-panel="hasErrors"
:title="s__('ProjectsNew|Create new project')"
diff --git a/app/assets/javascripts/projects/storage_counter/constants.js b/app/assets/javascripts/projects/storage_counter/constants.js
index 12d56256b9a..df4b1800dff 100644
--- a/app/assets/javascripts/projects/storage_counter/constants.js
+++ b/app/assets/javascripts/projects/storage_counter/constants.js
@@ -51,7 +51,7 @@ export const ERROR_MESSAGE = s__(
'UsageQuota|Something went wrong while fetching project storage statistics',
);
-export const LEARN_MORE_LABEL = s__('Learn more.');
+export const LEARN_MORE_LABEL = __('Learn more.');
export const USAGE_QUOTAS_LABEL = s__('UsageQuota|Usage Quotas');
export const HELP_LINK_ARIA_LABEL = s__('UsageQuota|%{linkTitle} help link');
export const TOTAL_USAGE_DEFAULT_TEXT = __('N/A');
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index f6f409873c8..a79da00de43 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -58,7 +58,7 @@ export default {
};
this.isLoading = false;
createFlash({
- message: s__('Something went wrong on our end'),
+ message: __('Something went wrong on our end'),
});
},
initPolling() {
diff --git a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
index d6187e1b527..50835142d28 100644
--- a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
+++ b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { sprintf, n__, s__ } from '~/locale';
+import { sprintf, __, n__ } from '~/locale';
import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
import { parseIssuableData } from '../../issue_show/utils/parse_data';
@@ -40,7 +40,7 @@ export default {
this.totalCount,
);
- return sprintf(s__('%{mrText}, this issue will be closed automatically.'), { mrText });
+ return sprintf(__('%{mrText}, this issue will be closed automatically.'), { mrText });
},
},
mounted() {
diff --git a/app/assets/javascripts/related_merge_requests/store/actions.js b/app/assets/javascripts/related_merge_requests/store/actions.js
index 652d03a0fd0..94abb50de89 100644
--- a/app/assets/javascripts/related_merge_requests/store/actions.js
+++ b/app/assets/javascripts/related_merge_requests/store/actions.js
@@ -1,7 +1,7 @@
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { normalizeHeaders } from '~/lib/utils/common_utils';
-import { s__ } from '~/locale';
+import { __ } from '~/locale';
import * as types from './mutation_types';
const REQUEST_PAGE_COUNT = 100;
@@ -30,7 +30,7 @@ export const fetchMergeRequests = ({ state, dispatch }) => {
.catch(() => {
dispatch('receiveDataError');
createFlash({
- message: s__('Something went wrong while fetching related merge requests.'),
+ message: __('Something went wrong while fetching related merge requests.'),
});
});
};
diff --git a/app/assets/javascripts/search/sidebar/components/radio_filter.vue b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
index 73911b9d319..aa7c26b8044 100644
--- a/app/assets/javascripts/search/sidebar/components/radio_filter.vue
+++ b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
@@ -1,7 +1,7 @@
<script>
import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import { sprintf, s__ } from '~/locale';
+import { sprintf, __ } from '~/locale';
export default {
name: 'RadioFilter',
@@ -49,7 +49,7 @@ export default {
...mapActions(['setQuery']),
radioLabel(filter) {
return filter.value === this.ANY.value
- ? sprintf(s__('Any %{header}'), { header: this.filterData.header.toLowerCase() })
+ ? sprintf(__('Any %{header}'), { header: this.filterData.header.toLowerCase() })
: filter.label;
},
},
diff --git a/app/assets/javascripts/static_site_editor/pages/success.vue b/app/assets/javascripts/static_site_editor/pages/success.vue
index 70e692a0c86..eb03aa3cca3 100644
--- a/app/assets/javascripts/static_site_editor/pages/success.vue
+++ b/app/assets/javascripts/static_site_editor/pages/success.vue
@@ -30,7 +30,7 @@ export default {
updatedFileDescription() {
const { sourcePath } = this.appData;
- return sprintf(s__('Update %{sourcePath} file'), { sourcePath });
+ return sprintf(__('Update %{sourcePath} file'), { sourcePath });
},
},
created() {
diff --git a/app/assets/javascripts/user_lists/components/user_lists_table.vue b/app/assets/javascripts/user_lists/components/user_lists_table.vue
index 765f59228a6..ccc2bfabb56 100644
--- a/app/assets/javascripts/user_lists/components/user_lists_table.vue
+++ b/app/assets/javascripts/user_lists/components/user_lists_table.vue
@@ -23,7 +23,7 @@ export default {
translations: {
createdTimeagoLabel: s__('UserList|created %{timeago}'),
deleteListTitle: s__('UserList|Delete %{name}?'),
- deleteListMessage: s__('User list %{name} will be removed. Are you sure?'),
+ deleteListMessage: __('User list %{name} will be removed. Are you sure?'),
editUserListLabel: s__('FeatureFlags|Edit User List'),
},
modal: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
index 533af6a5e51..fc17669a737 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
@@ -67,8 +67,8 @@ export default {
<template #targetBranch>
<span class="label-branch">{{ targetBranchEscaped }}</span>
</template>
- <template v-if="glFeatures.restructuredMrWidget" #squashedCommits>
- <template v-if="isSquashEnabled">
+ <template #squashedCommits>
+ <template v-if="glFeatures.restructuredMrWidget && isSquashEnabled">
{{ __('(commits will be squashed)') }}</template
></template
>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 5c67b9c7ab5..9070cb1fe65 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -151,7 +151,7 @@ export default {
right
data-qa-selector="download_dropdown"
>
- <gl-dropdown-section-header>{{ s__('Download as') }}</gl-dropdown-section-header>
+ <gl-dropdown-section-header>{{ __('Download as') }}</gl-dropdown-section-header>
<gl-dropdown-item
:href="mr.emailPatchesPath"
class="js-download-email-patches"
diff --git a/app/assets/javascripts/vue_shared/directives/validation.js b/app/assets/javascripts/vue_shared/directives/validation.js
index 779b04dc2bd..fc0ff78e7b4 100644
--- a/app/assets/javascripts/vue_shared/directives/validation.js
+++ b/app/assets/javascripts/vue_shared/directives/validation.js
@@ -1,4 +1,4 @@
-import { s__ } from '~/locale';
+import { __ } from '~/locale';
/**
* Validation messages will take priority based on the property order.
@@ -12,11 +12,11 @@ import { s__ } from '~/locale';
const defaultFeedbackMap = {
valueMissing: {
isInvalid: (el) => el.validity?.valueMissing,
- message: s__('Please fill out this field.'),
+ message: __('Please fill out this field.'),
},
urlTypeMismatch: {
isInvalid: (el) => el.type === 'url' && el.validity?.typeMismatch,
- message: s__('Please enter a valid URL format, ex: http://www.example.com/home'),
+ message: __('Please enter a valid URL format, ex: http://www.example.com/home'),
},
};
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index bbeb74faf2b..1cd80174f93 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -6,27 +6,30 @@ module Ci
def runner_status_icon(runner, size: 16, icon_class: '')
status = runner.status
+ active = runner.active
title = ''
icon = 'warning-solid'
span_class = ''
case status
+ when :online
+ if active
+ title = s_("Runners|Runner is online, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-active'
+ span_class = 'gl-text-green-500'
+ else
+ title = s_("Runners|Runner is paused, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
+ icon = 'status-paused'
+ span_class = 'gl-text-gray-600'
+ end
when :not_connected
title = s_("Runners|New runner, has not connected yet")
icon = 'warning-solid'
- when :online
- title = s_("Runners|Runner is online, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
- icon = 'status-active'
- span_class = 'gl-text-green-500'
when :offline
title = s_("Runners|Runner is offline, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
icon = 'status-failed'
span_class = 'gl-text-red-500'
- when :paused
- title = s_("Runners|Runner is paused, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) }
- icon = 'status-paused'
- span_class = 'gl-text-gray-600'
end
content_tag(:span, class: span_class, title: title, data: { toggle: 'tooltip', container: 'body', testid: 'runner_status_icon', qa_selector: "runner_status_#{status}_content" }) do
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 13f1302bdb0..8a3025e5608 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -274,6 +274,14 @@ module Ci
end
def status
+ return :not_connected unless contacted_at
+
+ online? ? :online : :offline
+ end
+
+ # DEPRECATED
+ # TODO Remove in %15.0 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ def deprecated_rest_status
if contacted_at.nil?
:not_connected
elsif active?
diff --git a/config/feature_flags/development/use_model_load_balancing.yml b/config/feature_flags/development/use_model_load_balancing.yml
new file mode 100644
index 00000000000..630e34acff3
--- /dev/null
+++ b/config/feature_flags/development/use_model_load_balancing.yml
@@ -0,0 +1,8 @@
+---
+name: use_model_load_balancing
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73631
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344797
+milestone: '14.5'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/data/deprecations/14-5-runner-api-status-does-contain-paused.yml b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
new file mode 100644
index 00000000000..4ce817313ce
--- /dev/null
+++ b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
@@ -0,0 +1,16 @@
+- name: "REST API Runner will not contain 'paused'"
+ announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ Runner REST API will not return "paused" as a status in GitLab 15.0.
+
+ REST API: Paused runners' status will only relate to runner contact status, such as:
+ "online", "offline", "not_connected". Status "paused" will not appear when the runner is
+ not active.
+
+ When checking if a runner is "paused", API users are advised to check the boolean attribute
+ "active" to be `false` instead.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ documentation_url: https://docs.gitlab.com/ee/api/runners.html
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 6d2f65f6953..da456131a52 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -1585,11 +1585,29 @@ all state associated with a given repository including:
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <virtual-storage> -repository <repository>
```
-- `-virtual-storage` is the virtual storage the repository is located in.
-- `-repository` is the repository's relative path in the storage.
+- `-virtual-storage` is the virtual storage the repository is located in. Virtual storages are configured in `/etc/gitlab/gitlab.rb` under `praefect['virtual_storages]` and looks like the following:
-Sometimes parts of the repository continue to exist after running `remove-repository`. This can be caused
-because of:
+ ```ruby
+ praefect['virtual_storages'] = {
+ 'default' => {
+ ...
+ },
+ 'storage-1' => {
+ ...
+ }
+ }
+ ```
+
+ In this example, the virtual storage to specify is `default` or `storage-1`.
+
+- `-repository` is the repository's relative path in the storage [beginning with `@hashed`](../repository_storage_types.md#hashed-storage).
+ For example:
+
+ ```plaintext
+ @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
+ ```
+
+Parts of the repository can continue to exist after running `remove-repository`. This can be because of:
- A deletion error.
- An in-flight RPC call targeting the repository.
@@ -1613,8 +1631,53 @@ The command outputs:
Each entry is a complete JSON string with a newline at the end (configurable using the
`-delimiter` flag). For example:
-```shell
+```plaintext
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories
{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567890.git"}
{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567891.git"}
```
+
+### Manually track repositories
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5658) in GitLab 14.4.
+
+The `track-repository` Praefect sub-command adds repositories on disk to the Praefect database to be tracked.
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage <virtual-storage> -repository <repository>
+```
+
+- `-virtual-storage` is the virtual storage the repository is located in. Virtual storages are configured in `/etc/gitlab/gitlab.rb` under `praefect['virtual_storages]` and looks like the following:
+
+ ```ruby
+ praefect['virtual_storages'] = {
+ 'default' => {
+ ...
+ },
+ 'storage-1' => {
+ ...
+ }
+ }
+ ```
+
+ In this example, the virtual storage to specify is `default` or `storage-1`.
+
+- `-repository` is the repository's relative path in the storage [beginning with `@hashed`](../repository_storage_types.md#hashed-storage).
+ For example:
+
+ ```plaintext
+ @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
+ ```
+
+- `-authoritative-storage` is the storage we want Praefect to treat as the primary. Required if
+ [per-repository replication](#configure-replication-factor) is set as the replication strategy.
+
+The command outputs:
+
+- Results to `STDOUT` and the command's logs.
+- Errors to `STDERR`.
+
+This command fails if:
+
+- The repository is already being tracked by the Praefect database.
+- The repository does not exist on disk.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 91643cd3ee0..82fd62d8d79 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -83,6 +83,24 @@ request is as follows:
migrations on a fresh database before the MR is reviewed. If the review leads
to large changes in the MR, execute the migrations again once the review is complete.
1. Write tests for more complex migrations.
+1. If your merge request adds new validations to existing models, to make sure the
+ data processing is backwards compatible:
+
+ - Ask in the [`#database`](https://gitlab.slack.com/archives/CNZ8E900G) Slack channel
+ for assistance to execute the database query that checks the existing rows to
+ ensure existing rows aren't impacted by the change.
+ - Add the necessary validation with a feature flag to be gradually rolled out
+ following [the rollout steps](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#rollout).
+
+ If this merge request is urgent, the code owners should make the final call on
+ whether reviewing existing rows should be included as an immediate follow-up task
+ to the merge request.
+
+ NOTE:
+ There isn't a way to know anything about our customers' data on their
+ [self-managed instances](../../subscriptions/self_managed/index.md), so keep
+ that in mind for any data implications with your merge request.
+
1. Merge requests **must** adhere to the [merge request performance guidelines](../merge_request_performance_guidelines.md).
1. For tests that use Capybara, read
[how to write reliable, asynchronous integration tests](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara).
diff --git a/lib/api/entities/ci/runner.rb b/lib/api/entities/ci/runner.rb
index ede698696de..60193fe1df4 100644
--- a/lib/api/entities/ci/runner.rb
+++ b/lib/api/entities/ci/runner.rb
@@ -12,7 +12,9 @@ module API
expose :runner_type
expose :name
expose :online?, as: :online
- expose :status
+ # DEPRECATED
+ # TODO Remove in %15.0 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
+ expose :status, as: :deprecated_rest_status
end
end
end
diff --git a/lib/gitlab/database/load_balancing/setup.rb b/lib/gitlab/database/load_balancing/setup.rb
index a44ace9da26..bcb40e45dac 100644
--- a/lib/gitlab/database/load_balancing/setup.rb
+++ b/lib/gitlab/database/load_balancing/setup.rb
@@ -5,7 +5,7 @@ module Gitlab
module LoadBalancing
# Class for setting up load balancing of a specific model.
class Setup
- attr_reader :configuration
+ attr_reader :model, :configuration
def initialize(model, start_service_discovery: false)
@model = model
@@ -15,8 +15,9 @@ module Gitlab
def setup
configure_connection
- setup_load_balancer
+ setup_connection_proxy
setup_service_discovery
+ setup_feature_flag_to_model_load_balancing
end
def configure_connection
@@ -36,28 +37,82 @@ module Gitlab
@model.establish_connection(hash_config)
end
- def setup_load_balancer
- lb = LoadBalancer.new(configuration)
-
+ def setup_connection_proxy
# We just use a simple `class_attribute` here so we don't need to
# inject any modules and/or expose unnecessary methods.
- @model.class_attribute(:connection)
- @model.class_attribute(:sticking)
+ setup_class_attribute(:connection, ConnectionProxy.new(load_balancer))
+ setup_class_attribute(:sticking, Sticking.new(load_balancer))
+ end
+
+ # TODO: This is temporary code to gradually redirect traffic to use
+ # a dedicated DB replicas, or DB primaries (depending on configuration)
+ # This implements a sticky behavior for the current request if enabled.
+ #
+ # This is needed for Phase 3 and Phase 4 of application rollout
+ # https://gitlab.com/groups/gitlab-org/-/epics/6160#progress
+ #
+ # If `GITLAB_USE_MODEL_LOAD_BALANCING` is set, its value is preferred
+ # Otherwise, a `use_model_load_balancing` FF value is used
+ def setup_feature_flag_to_model_load_balancing
+ return if active_record_base?
- @model.connection = ConnectionProxy.new(lb)
- @model.sticking = Sticking.new(lb)
+ @model.singleton_class.prepend(ModelLoadBalancingFeatureFlagMixin)
end
def setup_service_discovery
return unless configuration.service_discovery_enabled?
- lb = @model.connection.load_balancer
- sv = ServiceDiscovery.new(lb, **configuration.service_discovery)
+ sv = ServiceDiscovery.new(load_balancer, **configuration.service_discovery)
sv.perform_service_discovery
sv.start if @start_service_discovery
end
+
+ def load_balancer
+ @load_balancer ||= LoadBalancer.new(configuration)
+ end
+
+ private
+
+ def setup_class_attribute(attribute, value)
+ @model.class_attribute(attribute)
+ @model.public_send("#{attribute}=", value) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def active_record_base?
+ @model == ActiveRecord::Base
+ end
+
+ module ModelLoadBalancingFeatureFlagMixin
+ extend ActiveSupport::Concern
+
+ def use_model_load_balancing?
+ # Cache environment variable and return env variable first if defined
+ use_model_load_balancing_env = Gitlab::Utils.to_boolean(ENV["GITLAB_USE_MODEL_LOAD_BALANCING"])
+
+ unless use_model_load_balancing_env.nil?
+ return use_model_load_balancing_env
+ end
+
+ # Check a feature flag using RequestStore (if active)
+ return false unless Gitlab::SafeRequestStore.active?
+
+ Gitlab::SafeRequestStore.fetch(:use_model_load_balancing) do
+ Feature.enabled?(:use_model_load_balancing, default_enabled: :yaml)
+ end
+ end
+
+ # rubocop:disable Database/MultipleDatabases
+ def connection
+ use_model_load_balancing? ? super : ActiveRecord::Base.connection
+ end
+
+ def sticking
+ use_model_load_balancing? ? super : ActiveRecord::Base.sticking
+ end
+ # rubocop:enable Database/MultipleDatabases
+ end
end
end
end
diff --git a/lib/gitlab/import_export/attributes_permitter.rb b/lib/gitlab/import_export/attributes_permitter.rb
index 2d8e25a9f70..f6f65f85599 100644
--- a/lib/gitlab/import_export/attributes_permitter.rb
+++ b/lib/gitlab/import_export/attributes_permitter.rb
@@ -44,7 +44,7 @@ module Gitlab
# We want to use AttributesCleaner for these relations instead, in the future this should be removed to make sure
# we are using AttributesPermitter for every imported relation.
- DISABLED_RELATION_NAMES = %i[user author issuable_sla].freeze
+ DISABLED_RELATION_NAMES = %i[author issuable_sla].freeze
def initialize(config: ImportExport::Config.new.to_h)
@config = config
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index bbcf802daf6..52cbf6ce750 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -178,17 +178,7 @@ included_attributes:
- :project_id
- :key
- :value
- label:
- - :title
- - :color
- - :project_id
- - :group_id
- - :created_at
- - :updated_at
- - :template
- - :description
- - :priority
- labels:
+ label: &label_definition
- :title
- :color
- :project_id
@@ -198,23 +188,13 @@ included_attributes:
- :template
- :description
- :priority
+ labels: *label_definition
priorities:
- :project_id
- :priority
- :created_at
- :updated_at
- milestone:
- - :iid
- - :title
- - :project_id
- - :group_id
- - :description
- - :due_date
- - :created_at
- - :updated_at
- - :start_date
- - :state
- milestones:
+ milestone: &milestone_definition
- :iid
- :title
- :project_id
@@ -225,6 +205,7 @@ included_attributes:
- :updated_at
- :start_date
- :state
+ milestones: *milestone_definition
protected_branches:
- :project_id
- :name
@@ -315,6 +296,200 @@ included_attributes:
- :project_id
- :issue_template_key
- :project_key
+ snippets:
+ - :title
+ - :content
+ - :author_id
+ - :project_id
+ - :created_at
+ - :updated_at
+ - :file_name
+ - :visibility_level
+ - :description
+ project_members:
+ - :access_level
+ - :source_type
+ - :user_id
+ - :notification_level
+ - :created_at
+ - :updated_at
+ - :created_by_id
+ - :invite_email
+ - :invite_accepted_at
+ - :requested_at
+ - :expires_at
+ - :ldap
+ - :override
+ merge_request: &merge_request_definition
+ - :target_branch
+ - :source_branch
+ - :source_project_id
+ - :author_id
+ - :assignee_id
+ - :title
+ - :created_at
+ - :updated_at
+ - :state
+ - :merge_status
+ - :target_project_id
+ - :iid
+ - :description
+ - :updated_by_id
+ - :merge_error
+ - :merge_params
+ - :merge_when_pipeline_succeeds
+ - :merge_user_id
+ - :merge_commit_sha
+ - :squash_commit_sha
+ - :in_progress_merge_commit_sha
+ - :lock_version
+ - :approvals_before_merge
+ - :rebase_commit_sha
+ - :time_estimate
+ - :squash
+ - :last_edited_at
+ - :last_edited_by_id
+ - :discussion_locked
+ - :allow_maintainer_to_push
+ - :merge_ref_sha
+ - :draft
+ - :diff_head_sha
+ - :source_branch_sha
+ - :target_branch_sha
+ merge_requests: *merge_request_definition
+ award_emoji:
+ - :user_id
+ - :name
+ - :awardable_type
+ - :created_at
+ - :updated_at
+ commit_author:
+ - :name
+ - :email
+ committer:
+ - :name
+ - :email
+ events:
+ - :target_type
+ - :action
+ - :author_id
+ - :fingerprint
+ - :created_at
+ - :updated_at
+ label_links:
+ - :target_type
+ - :created_at
+ - :updated_at
+ merge_request_diff:
+ - :state
+ - :created_at
+ - :updated_at
+ - :base_commit_sha
+ - :real_size
+ - :head_commit_sha
+ - :start_commit_sha
+ - :commits_count
+ - :files_count
+ - :sorted
+ - :diff_type
+ merge_request_diff_commits:
+ - :relative_order
+ - :sha
+ - :authored_date
+ - :committed_date
+ - :message
+ - :trailers
+ merge_request_diff_files:
+ - :relative_order
+ - :new_file
+ - :renamed_file
+ - :deleted_file
+ - :new_path
+ - :old_path
+ - :a_mode
+ - :b_mode
+ - :too_large
+ - :binary
+ - :diff
+ metrics:
+ - :created_at
+ - :updated_at
+ - :latest_closed_by_id
+ - :latest_closed_at
+ - :merged_by_id
+ - :merged_at
+ - :latest_build_started_at
+ - :latest_build_finished_at
+ - :first_deployed_to_production_at
+ - :first_comment_at
+ - :first_commit_at
+ - :last_commit_at
+ - :diff_size
+ - :modified_paths_size
+ - :commits_count
+ - :first_approved_at
+ - :first_reassigned_at
+ - :added_lines
+ - :target_project_id
+ - :removed_lines
+ notes:
+ - :note
+ - :noteable_type
+ - :author_id
+ - :created_at
+ - :updated_at
+ - :project_id
+ - :attachment
+ - :line_code
+ - :commit_id
+ - :system
+ - :st_diff
+ - :updated_by_id
+ - :type
+ - :position
+ - :original_position
+ - :change_position
+ - :resolved_at
+ - :resolved_by_id
+ - :resolved_by_push
+ - :discussion_id
+ - :confidential
+ - :last_edited_at
+ push_event_payload:
+ - :commit_count
+ - :action
+ - :ref_type
+ - :commit_from
+ - :commit_to
+ - :ref
+ - :commit_title
+ - :ref_count
+ resource_label_events:
+ - :action
+ - :user_id
+ - :created_at
+ suggestions:
+ - :relative_order
+ - :applied
+ - :commit_id
+ - :from_content
+ - :to_content
+ - :outdated
+ - :lines_above
+ - :lines_below
+ system_note_metadata:
+ - :commit_count
+ - :action
+ - :created_at
+ - :updated_at
+ timelogs:
+ - :time_spent
+ - :user_id
+ - :project_id
+ - :spent_at
+ - :created_at
+ - :updated_at
+ - :summary
# Do not include the following attributes for the models specified.
excluded_attributes:
@@ -430,16 +605,7 @@ excluded_attributes:
- :service_desk_reply_to
- :upvotes_count
- :work_item_type_id
- merge_request:
- - :milestone_id
- - :sprint_id
- - :ref_fetched
- - :merge_jid
- - :rebase_jid
- - :latest_merge_request_diff_id
- - :head_pipeline_id
- - :state_id
- merge_requests:
+ merge_request: &merge_request_excluded_definition
- :milestone_id
- :sprint_id
- :ref_fetched
@@ -448,6 +614,7 @@ excluded_attributes:
- :latest_merge_request_diff_id
- :head_pipeline_id
- :state_id
+ merge_requests: *merge_request_excluded_definition
award_emoji:
- :awardable_id
statuses:
@@ -516,10 +683,9 @@ excluded_attributes:
- :issue_id
zoom_meetings:
- :issue_id
- design:
- - :issue_id
- designs:
+ design: &design_excluded_definition
- :issue_id
+ designs: *design_excluded_definition
design_versions:
- :issue_id
actions:
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index b450013e3bc..f16a436ecf6 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -38128,9 +38128,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38158,6 +38155,9 @@ msgstr ""
msgid "VulnerabilityManagement|Detected"
msgstr ""
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
diff --git a/package.json b/package.json
index 791e475341b..9bf46e477c2 100644
--- a/package.json
+++ b/package.json
@@ -203,7 +203,7 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "9.4.0",
+ "@gitlab/eslint-plugin": "10.0.0",
"@gitlab/stylelint-config": "2.6.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.2.0",
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 971e7634f6d..cdfd7fbdad9 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -22,20 +22,16 @@ module QA
element :labels_block
end
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue' do
- element :selected_label_content
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue' do
+ element :dropdown_input_field
end
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents.vue' do
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue' do
element :labels_dropdown_content
end
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue' do
- element :labels_edit_button
- end
-
- base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue' do
- element :dropdown_input_field
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue' do
+ element :selected_label_content
end
base.view 'app/views/shared/issuable/_sidebar.html.haml' do
@@ -53,7 +49,7 @@ module QA
end
def assign_milestone(milestone)
- within_element(:milestone_block) do
+ wait_milestone_block_finish_loading do
click_element(:edit_link)
click_on(milestone.title)
end
@@ -70,14 +66,14 @@ module QA
end
def has_assignee?(username)
- within_element(:assignee_block) do
- has_text?(username, wait: 1)
+ wait_assignees_block_finish_loading do
+ has_text?(username)
end
end
def has_no_assignee?(username)
- within_element(:assignee_block) do
- has_no_text?(username, wait: 1)
+ wait_assignees_block_finish_loading do
+ has_no_text?(username)
end
end
@@ -88,8 +84,14 @@ module QA
end
def has_label?(label)
- within_element(:labels_block) do
- !!has_element?(:selected_label_content, label_name: label)
+ wait_labels_block_finish_loading do
+ has_element?(:selected_label_content, label_name: label)
+ end
+ end
+
+ def has_no_label?(label)
+ wait_labels_block_finish_loading do
+ has_no_element?(:selected_label_content, label_name: label)
end
end
@@ -103,27 +105,19 @@ module QA
find_element(:more_assignees_link)
end
- def select_labels_and_refresh(labels)
- Support::Retrier.retry_until do
- click_element(:labels_edit_button)
- has_element?(:labels_dropdown_content, text: labels.first)
- end
+ def select_labels(labels)
+ within_element(:labels_block) do
+ click_element(:edit_link)
- labels.each do |label|
- within_element(:labels_dropdown_content) do
- send_keys_to_element(:dropdown_input_field, [label, :enter])
+ labels.each do |label|
+ within_element(:labels_dropdown_content) do
+ fill_element(:dropdown_input_field, label)
+ click_button(text: label)
+ end
end
end
- click_element(:labels_edit_button)
-
- labels.each do |label|
- has_element?(:labels_block, text: label, wait: 0)
- end
-
- refresh
-
- wait_for_requests
+ click_element(:title) # to blur dropdown
end
def toggle_more_assignees_link
@@ -141,6 +135,15 @@ module QA
end
end
+ def wait_labels_block_finish_loading
+ within_element(:labels_block) do
+ wait_until(reload: false, max_duration: 10, sleep_interval: 1) do
+ finished_loading_block?
+ yield
+ end
+ end
+ end
+
def wait_milestone_block_finish_loading
within_element(:milestone_block) do
wait_until(reload: false, max_duration: 10, sleep_interval: 1) do
diff --git a/qa/qa/support/matchers/have_matcher.rb b/qa/qa/support/matchers/have_matcher.rb
index 7001f53a7b7..47d2d246460 100644
--- a/qa/qa/support/matchers/have_matcher.rb
+++ b/qa/qa/support/matchers/have_matcher.rb
@@ -19,6 +19,7 @@ module QA
related_issue_item
snippet_description
tag
+ label
].each do |predicate|
RSpec::Matchers.define "have_#{predicate}" do |*args, **kwargs|
match do |page_object|
diff --git a/spec/frontend/jira_connect/subscriptions/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
index 691cdb0f676..b63236dec82 100644
--- a/spec/frontend/jira_connect/subscriptions/components/app_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
@@ -1,15 +1,15 @@
-import { GlAlert, GlButton, GlLink } from '@gitlab/ui';
+import { GlAlert, GlLink } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
+import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
import { __ } from '~/locale';
jest.mock('~/jira_connect/subscriptions/utils', () => ({
retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }),
- getLocation: jest.fn(),
}));
describe('JiraConnectApp', () => {
@@ -18,7 +18,7 @@ describe('JiraConnectApp', () => {
const findAlert = () => wrapper.findComponent(GlAlert);
const findAlertLink = () => findAlert().findComponent(GlLink);
- const findGlButton = () => wrapper.findComponent(GlButton);
+ const findSignInButton = () => wrapper.findComponent(SignInButton);
const findAddNamespaceButton = () => wrapper.findComponent(AddNamespaceButton);
const createComponent = ({ provide, mountFn = shallowMount } = {}) => {
@@ -35,28 +35,25 @@ describe('JiraConnectApp', () => {
});
describe('template', () => {
- describe('when user is not logged in', () => {
+ describe.each`
+ scenario | usersPath | expectSignInButton | expectNamespaceButton
+ ${'user is not signed in'} | ${'/users'} | ${true} | ${false}
+ ${'user is signed in'} | ${undefined} | ${false} | ${true}
+ `('when $scenario', ({ usersPath, expectSignInButton, expectNamespaceButton }) => {
beforeEach(() => {
createComponent({
provide: {
- usersPath: '/users',
+ usersPath,
},
});
});
- it('renders "Sign in" button', () => {
- expect(findGlButton().text()).toBe('Sign in to add namespaces');
- expect(findAddNamespaceButton().exists()).toBe(false);
- });
- });
-
- describe('when user is logged in', () => {
- beforeEach(() => {
- createComponent();
+ it('renders sign in button as expected', () => {
+ expect(findSignInButton().exists()).toBe(expectSignInButton);
});
- it('renders "Add namespace" button ', () => {
- expect(findAddNamespaceButton().exists()).toBe(true);
+ it('renders "Add Namespace" button as expected', () => {
+ expect(findAddNamespaceButton().exists()).toBe(expectNamespaceButton);
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js
new file mode 100644
index 00000000000..8ad5206ce0f
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js
@@ -0,0 +1,50 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { getLocation } from '~/jira_connect/subscriptions/utils';
+import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
+import waitForPromises from 'helpers/wait_for_promises';
+
+const MOCK_USERS_PATH = '/user';
+
+jest.mock('~/jira_connect/subscriptions/utils');
+
+describe('SignInButton', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(SignInButton, {
+ propsData: {
+ usersPath: MOCK_USERS_PATH,
+ },
+ });
+ };
+
+ const findButton = () => wrapper.findComponent(GlButton);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays a button', () => {
+ createComponent();
+
+ expect(findButton().exists()).toBe(true);
+ });
+
+ describe.each`
+ getLocationValue | expectedHref
+ ${''} | ${MOCK_USERS_PATH}
+ ${undefined} | ${MOCK_USERS_PATH}
+ ${'https://test.jira.com'} | ${`${MOCK_USERS_PATH}?return_to=${encodeURIComponent('https://test.jira.com')}`}
+ `('when getLocation resolves with `$getLocationValue`', ({ getLocationValue, expectedHref }) => {
+ it(`sets button href to ${expectedHref}`, async () => {
+ getLocation.mockResolvedValue(getLocationValue);
+ createComponent();
+
+ expect(getLocation).toHaveBeenCalled();
+ await waitForPromises();
+
+ expect(findButton().attributes('href')).toBe(expectedHref);
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index f6ad41d5478..7a64b654baa 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -185,15 +185,15 @@ describe('dateInWords', () => {
const date = new Date('07/01/2016');
it('should return date in words', () => {
- expect(datetimeUtility.dateInWords(date)).toEqual(s__('July 1, 2016'));
+ expect(datetimeUtility.dateInWords(date)).toEqual(__('July 1, 2016'));
});
it('should return abbreviated month name', () => {
- expect(datetimeUtility.dateInWords(date, true)).toEqual(s__('Jul 1, 2016'));
+ expect(datetimeUtility.dateInWords(date, true)).toEqual(__('Jul 1, 2016'));
});
it('should return date in words without year', () => {
- expect(datetimeUtility.dateInWords(date, true, true)).toEqual(s__('Jul 1'));
+ expect(datetimeUtility.dateInWords(date, true, true)).toEqual(__('Jul 1'));
});
});
@@ -201,11 +201,11 @@ describe('monthInWords', () => {
const date = new Date('2017-01-20');
it('returns month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date)).toBe(s__('January'));
+ expect(datetimeUtility.monthInWords(date)).toBe(__('January'));
});
it('returns abbreviated month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date, true)).toBe(s__('Jan'));
+ expect(datetimeUtility.monthInWords(date, true)).toBe(__('Jan'));
});
});
diff --git a/spec/lib/gitlab/database/load_balancing/setup_spec.rb b/spec/lib/gitlab/database/load_balancing/setup_spec.rb
index 656c861c72d..dfdf7d19e72 100644
--- a/spec/lib/gitlab/database/load_balancing/setup_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/setup_spec.rb
@@ -8,8 +8,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
setup = described_class.new(ActiveRecord::Base)
expect(setup).to receive(:configure_connection)
- expect(setup).to receive(:setup_load_balancer)
+ expect(setup).to receive(:setup_connection_proxy)
expect(setup).to receive(:setup_service_discovery)
+ expect(setup).to receive(:setup_feature_flag_to_model_load_balancing)
setup.setup
end
@@ -44,7 +45,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
end
end
- describe '#setup_load_balancer' do
+ describe '#setup_connection_proxy' do
it 'sets up the load balancer' do
model = Class.new(ActiveRecord::Base)
setup = described_class.new(model)
@@ -58,7 +59,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
.with(setup.configuration)
.and_return(lb)
- setup.setup_load_balancer
+ setup.setup_connection_proxy
expect(model.connection.load_balancer).to eq(lb)
expect(model.sticking)
@@ -81,7 +82,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
model = ActiveRecord::Base
setup = described_class.new(model)
sv = instance_spy(Gitlab::Database::LoadBalancing::ServiceDiscovery)
- lb = model.connection.load_balancer
allow(setup.configuration)
.to receive(:service_discovery_enabled?)
@@ -89,7 +89,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
allow(Gitlab::Database::LoadBalancing::ServiceDiscovery)
.to receive(:new)
- .with(lb, setup.configuration.service_discovery)
+ .with(setup.load_balancer, setup.configuration.service_discovery)
.and_return(sv)
expect(sv).to receive(:perform_service_discovery)
@@ -102,7 +102,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
model = ActiveRecord::Base
setup = described_class.new(model, start_service_discovery: true)
sv = instance_spy(Gitlab::Database::LoadBalancing::ServiceDiscovery)
- lb = model.connection.load_balancer
allow(setup.configuration)
.to receive(:service_discovery_enabled?)
@@ -110,7 +109,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
allow(Gitlab::Database::LoadBalancing::ServiceDiscovery)
.to receive(:new)
- .with(lb, setup.configuration.service_discovery)
+ .with(setup.load_balancer, setup.configuration.service_discovery)
.and_return(sv)
expect(sv).to receive(:perform_service_discovery)
@@ -120,4 +119,172 @@ RSpec.describe Gitlab::Database::LoadBalancing::Setup do
end
end
end
+
+ describe '#setup_feature_flag_to_model_load_balancing', :reestablished_active_record_base do
+ using RSpec::Parameterized::TableSyntax
+
+ where do
+ {
+ "with model LB enabled it picks a dedicated CI connection" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'true',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'ci' }
+ }
+ },
+ "with model LB enabled and re-use of primary connection it uses CI connection for reads" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'true',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'main' }
+ }
+ },
+ "with model LB disabled it fallbacks to use main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'false',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with model LB disabled, but re-use configured it fallbacks to use main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: 'false',
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
+ request_store_active: false,
+ ff_use_model_load_balancing: nil,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF disabled without RequestStore it uses main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: false,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF enabled without RequestStore sticking of FF does not work, so it fallbacks to use main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: false,
+ ff_use_model_load_balancing: true,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF disabled with RequestStore it uses main" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: true,
+ ff_use_model_load_balancing: false,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'main_replica', write: 'main' }
+ }
+ },
+ "with FF enabled with RequestStore it sticks FF and uses CI connection" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: nil,
+ request_store_active: true,
+ ff_use_model_load_balancing: true,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'ci' }
+ }
+ },
+ "with re-use and FF enabled with RequestStore it sticks FF and uses CI connection for reads" => {
+ env_GITLAB_USE_MODEL_LOAD_BALANCING: nil,
+ env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: 'main',
+ request_store_active: true,
+ ff_use_model_load_balancing: true,
+ expectations: {
+ main: { read: 'main_replica', write: 'main' },
+ ci: { read: 'ci_replica', write: 'main' }
+ }
+ }
+ }
+ end
+
+ with_them do
+ let(:ci_class) do
+ Class.new(ActiveRecord::Base) do
+ def self.name
+ 'Ci::ApplicationRecordTemporary'
+ end
+
+ establish_connection ActiveRecord::DatabaseConfigurations::HashConfig.new(
+ Rails.env,
+ 'ci',
+ ActiveRecord::Base.connection_db_config.configuration_hash
+ )
+ end
+ end
+
+ let(:models) do
+ {
+ main: ActiveRecord::Base,
+ ci: ci_class
+ }
+ end
+
+ around do |example|
+ if request_store_active
+ Gitlab::WithRequestStore.with_request_store do
+ RequestStore.clear!
+
+ example.run
+ end
+ else
+ example.run
+ end
+ end
+
+ before do
+ # Rewrite `class_attribute` to use rspec mocking and prevent modifying the objects
+ allow_next_instance_of(described_class) do |setup|
+ allow(setup).to receive(:configure_connection)
+
+ allow(setup).to receive(:setup_class_attribute) do |attribute, value|
+ allow(setup.model).to receive(attribute) { value }
+ end
+ end
+
+ stub_env('GITLAB_USE_MODEL_LOAD_BALANCING', env_GITLAB_USE_MODEL_LOAD_BALANCING)
+ stub_env('GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci', env_GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci)
+ stub_feature_flags(use_model_load_balancing: ff_use_model_load_balancing)
+ end
+
+ it 'results match expectations' do
+ result = models.transform_values do |model|
+ # Make load balancer to force init with a dedicated replicas connections
+ described_class.new(model).tap do |subject|
+ subject.configuration.hosts = [subject.configuration.replica_db_config.host]
+ subject.setup
+ end
+
+ load_balancer = model.connection.load_balancer
+
+ {
+ read: load_balancer.read { |connection| connection.pool.db_config.name },
+ write: load_balancer.read_write { |connection| connection.pool.db_config.name }
+ }
+ end
+
+ expect(result).to eq(expectations)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
index 55422ec3ef2..4fea61ec3a8 100644
--- a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
+++ b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
@@ -80,8 +80,8 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
let(:attributes_permitter) { described_class.new }
- where(:relation_name, :permitted_attributes_defined) do
- :user | false
+ where(:relation_name, :permitted_attributes_defined ) do
+ :user | true
:author | false
:ci_cd_settings | true
:metrics_setting | true
@@ -91,6 +91,7 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
:auto_devops | true
:boards | true
:custom_attributes | true
+ :label | true
:labels | true
:protected_branches | true
:protected_tags | true
@@ -99,6 +100,28 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
:push_access_levels | true
:releases | true
:links | true
+ :priorities | true
+ :milestone | true
+ :milestones | true
+ :snippets | true
+ :project_members | true
+ :merge_request | true
+ :merge_requests | true
+ :award_emoji | true
+ :commit_author | true
+ :committer | true
+ :events | true
+ :label_links | true
+ :merge_request_diff | true
+ :merge_request_diff_commits | true
+ :merge_request_diff_files | true
+ :metrics | true
+ :notes | true
+ :push_event_payload | true
+ :resource_label_events | true
+ :suggestions | true
+ :system_note_metadata | true
+ :timelogs | true
:container_expiration_policy | true
:project_feature | true
:prometheus_metrics | true
@@ -113,9 +136,11 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
describe 'included_attributes for Project' do
subject { described_class.new }
+ additional_attributes = { user: %w[id] }
+
Gitlab::ImportExport::Config.new.to_h[:included_attributes].each do |relation_sym, permitted_attributes|
context "for #{relation_sym}" do
- it_behaves_like 'a permitted attribute', relation_sym, permitted_attributes
+ it_behaves_like 'a permitted attribute', relation_sym, permitted_attributes, additional_attributes[relation_sym]
end
end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 08c471c6bfb..2e79159cc60 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -626,7 +626,7 @@ RSpec.describe Ci::Runner do
end
describe '#status' do
- let(:runner) { create(:ci_runner, :instance, contacted_at: 1.second.ago) }
+ let(:runner) { build(:ci_runner, :instance) }
subject { runner.status }
@@ -638,6 +638,45 @@ RSpec.describe Ci::Runner do
it { is_expected.to eq(:not_connected) }
end
+ context 'inactive but online' do
+ before do
+ runner.contacted_at = 1.second.ago
+ runner.active = false
+ end
+
+ it { is_expected.to eq(:online) }
+ end
+
+ context 'contacted 1s ago' do
+ before do
+ runner.contacted_at = 1.second.ago
+ end
+
+ it { is_expected.to eq(:online) }
+ end
+
+ context 'contacted long time ago' do
+ before do
+ runner.contacted_at = 1.year.ago
+ end
+
+ it { is_expected.to eq(:offline) }
+ end
+ end
+
+ describe '#deprecated_rest_status' do
+ let(:runner) { build(:ci_runner, :instance, contacted_at: 1.second.ago) }
+
+ subject { runner.deprecated_rest_status }
+
+ context 'never connected' do
+ before do
+ runner.contacted_at = nil
+ end
+
+ it { is_expected.to eq(:not_connected) }
+ end
+
context 'contacted 1s ago' do
before do
runner.contacted_at = 1.second.ago
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index d0257f6c2b6..806c60d5aff 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -162,12 +162,12 @@ RSpec.describe Clusters::Applications::Runner do
it 'pauses associated runner' do
active_runner = create(:ci_runner, contacted_at: 1.second.ago)
- expect(active_runner.status).to eq(:online)
+ expect(active_runner.active).to be_truthy
application_runner = create(:clusters_applications_runner, :scheduled, runner: active_runner)
application_runner.prepare_uninstall
- expect(active_runner.status).to eq(:paused)
+ expect(active_runner.active).to be_falsey
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
index 5ce698c4701..41d3d76b66b 100644
--- a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attributes|
+RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attributes, additional_attributes = []|
let(:prohibited_attributes) { %i[remote_url my_attributes my_ids token my_id test] }
let(:import_export_config) { Gitlab::ImportExport::Config.new.to_h }
@@ -26,7 +26,7 @@ RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attrib
end
it 'does not contain attributes that would be cleaned with AttributeCleaner' do
- expect(cleaned_hash.keys).to include(*permitted_hash.keys)
+ expect(cleaned_hash.keys + additional_attributes.to_a).to include(*permitted_hash.keys)
end
it 'does not contain prohibited attributes that are not related to given relation' do
diff --git a/yarn.lock b/yarn.lock
index 2377c548458..54b1473a65b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -873,10 +873,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/at.js/-/at.js-1.5.7.tgz#1ee6f838cc4410a1d797770934df91d90df8179e"
integrity sha512-c6ySRK/Ma7lxwpIVbSAF3P+xiTLrNTGTLRx4/pHK111AdFxwgUwrYF6aVZFXvmG65jHOJHoa0eQQ21RW6rm0Rg==
-"@gitlab/eslint-plugin@9.4.0":
- version "9.4.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-9.4.0.tgz#cad8f63b7985c22865859cc7d2688eb446ad0bbb"
- integrity sha512-llPypEQrm9/6Xas5GCoSPAK7W/DgO7CKhzDvAk/Ea9BP0rI2+t8Wg4PFhE1XDctYnnUIS/GrdqVKQkpODk24hQ==
+"@gitlab/eslint-plugin@10.0.0":
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-10.0.0.tgz#83430fb4d0a2467bb54975d0b5b9dc8016005722"
+ integrity sha512-frCYzjQQaZ5kW1on3XwuVGhvYa6XjD6Q1POTbxDpzl6tNxSeTwOJohC6Joyw76e0Kw4fPQd/fHAfKQAB0AVQ7A==
dependencies:
babel-eslint "^10.0.3"
eslint-config-airbnb-base "^14.2.1"