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/issue_templates/Geo Replicate a new Git repository type.md2
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md2
-rw-r--r--.rubocop.yml1
-rw-r--r--app/assets/javascripts/sidebar/components/labels/labels_select_vue/label_item.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/labels/labels_select_widget/label_item.vue4
-rw-r--r--app/assets/javascripts/super_sidebar/components/context_switcher.vue52
-rw-r--r--app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue6
-rw-r--r--app/assets/javascripts/super_sidebar/components/search_results.vue2
-rw-r--r--app/assets/javascripts/super_sidebar/components/super_sidebar.vue70
-rw-r--r--app/assets/javascripts/super_sidebar/popper_max_size_modifier.js43
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue53
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss10
-rw-r--r--app/assets/stylesheets/framework/super_sidebar.scss8
-rw-r--r--config/initializers/active_record_database_tasks.rb2
-rw-r--r--data/deprecations/15-8-default-private-user-profile.yml9
-rw-r--r--db/docs/schema_migrations.yml5
-rw-r--r--doc/.vale/gitlab/CIConfigFile.yml6
-rw-r--r--doc/administration/audit_events.md64
-rw-r--r--doc/administration/package_information/supported_os.md5
-rw-r--r--doc/api/rest/deprecations.md6
-rw-r--r--doc/development/database/database_dictionary.md15
-rw-r--r--doc/integration/jira/connect-app.md10
-rw-r--r--doc/update/deprecations.md13
-rw-r--r--doc/user/application_security/dast/proxy-based.md2
-rw-r--r--doc/user/application_security/secret_detection/index.md2
-rw-r--r--doc/user/group/saml_sso/img/group_saml_configuration_information.pngbin16489 -> 0 bytes
-rw-r--r--doc/user/group/saml_sso/img/group_saml_settings_v13_12.pngbin66055 -> 0 bytes
-rw-r--r--doc/user/project/ml/experiment_tracking/img/candidate_v15_7.pngbin35164 -> 0 bytes
-rw-r--r--doc/user/project/ml/experiment_tracking/img/candidates_v15_7.pngbin47800 -> 0 bytes
-rw-r--r--doc/user/project/ml/experiment_tracking/img/experiments_v15_7.pngbin23475 -> 0 bytes
-rw-r--r--lib/api/package_files.rb2
-rw-r--r--lib/gitlab/database/gitlab_schema.rb4
-rw-r--r--lib/gitlab/database/tables_locker.rb2
-rw-r--r--lib/gitlab/patch/database_config.rb18
-rw-r--r--lib/tasks/gitlab/db.rake17
-rw-r--r--locale/gitlab.pot64
-rw-r--r--rubocop/migration_helpers.rb4
-rw-r--r--spec/frontend/super_sidebar/components/context_switcher_spec.js64
-rw-r--r--spec/frontend/super_sidebar/components/super_sidebar_spec.js37
-rw-r--r--spec/lib/gitlab/database/gitlab_schema_spec.rb6
-rw-r--r--spec/requests/api/package_files_spec.rb84
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb1
43 files changed, 501 insertions, 197 deletions
diff --git a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
index 60b091b04a2..c528d38ae5d 100644
--- a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
@@ -100,7 +100,7 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
-- [ ] Add the new table to the [database dictionary](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/database/database_dictionary.md) defined in [`ee/db/docs/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/db/docs):
+- [ ] Add the new table to the [database dictionary](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/database/database_dictionary.md) defined in [`ee/db/geo/docs/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/db/geo/docs):
```yaml
table_name: cool_widget_registry
diff --git a/.gitlab/issue_templates/Geo Replicate a new blob type.md b/.gitlab/issue_templates/Geo Replicate a new blob type.md
index df2d1871a85..70d1dfb1105 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -100,7 +100,7 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
- [ ] If deviating from the above example, then be sure to order columns according to [our guidelines](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/ordering_table_columns.md).
-- [ ] Add the new table to the [database dictionary](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/database/database_dictionary.md) defined in [`ee/db/docs/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/db/docs):
+- [ ] Add the new table to the [database dictionary](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/database/database_dictionary.md) defined in [`ee/db/geo/docs/`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/ee/db/geo/docs):
```yaml
table_name: cool_widget_registry
diff --git a/.rubocop.yml b/.rubocop.yml
index dfb2eb84fda..e2d37ff8b88 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -112,6 +112,7 @@ Lint/LastKeywordArgument:
Lint/EmptyFile:
Exclude:
- 'db/seeds.rb'
+ - 'ee/db/embedding/seeds.rb'
- 'ee/db/geo/seeds.rb'
# This cop checks whether some constant value isn't a
diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_vue/label_item.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_vue/label_item.vue
index 2960298dca8..9df03a4d7f8 100644
--- a/app/assets/javascripts/sidebar/components/labels/labels_select_vue/label_item.vue
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_vue/label_item.vue
@@ -31,7 +31,7 @@ export default {
const { label, highlight, isLabelSet, isLabelIndeterminate } = props;
const labelColorBox = h('span', {
- class: 'dropdown-label-box gl-flex-shrink-0 gl-top-0 gl-absolute',
+ class: 'dropdown-label-box gl-mr-2',
style: {
backgroundColor: label.color,
},
diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view.vue
index e664d6b4bd6..dce80af8a5e 100644
--- a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_labels_view.vue
@@ -154,7 +154,6 @@ export default {
v-for="(label, index) in visibleLabels"
:key="label.id"
:is-checked="isLabelSelected(label)"
- is-check-centered
is-check-item
:active="shouldHighlightFirstItem && index === 0"
active-class="is-focused"
diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/label_item.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/label_item.vue
index 19024692bdf..4ce2644262a 100644
--- a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/label_item.vue
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/label_item.vue
@@ -10,9 +10,9 @@ export default {
</script>
<template>
- <div class="gl-display-flex gl-align-items-center gl-word-break-word gl-relative gl-pl-4">
+ <div class="gl-display-flex gl-word-break-word">
<span
- class="dropdown-label-box gl-flex-shrink-0 gl-top-0 gl-absolute"
+ class="dropdown-label-box gl-flex-shrink-0 gl-top-0 gl-mr-3"
:style="{ 'background-color': label.color }"
data-testid="label-color-box"
></span>
diff --git a/app/assets/javascripts/super_sidebar/components/context_switcher.vue b/app/assets/javascripts/super_sidebar/components/context_switcher.vue
index fa9da6cef9d..0fa3c66da51 100644
--- a/app/assets/javascripts/super_sidebar/components/context_switcher.vue
+++ b/app/assets/javascripts/super_sidebar/components/context_switcher.vue
@@ -1,13 +1,15 @@
<script>
import * as Sentry from '@sentry/browser';
-import { GlSearchBoxByType, GlLoadingIcon, GlAlert } from '@gitlab/ui';
+import { GlDisclosureDropdown, GlSearchBoxByType, GlLoadingIcon, GlAlert } from '@gitlab/ui';
import { s__ } from '~/locale';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import searchUserProjectsAndGroups from '../graphql/queries/search_user_groups_and_projects.query.graphql';
import { trackContextAccess, formatContextSwitcherItems } from '../utils';
+import { maxSize, applyMaxSize } from '../popper_max_size_modifier';
import NavItem from './nav_item.vue';
import ProjectsList from './projects_list.vue';
import GroupsList from './groups_list.vue';
+import ContextSwitcherToggle from './context_switcher_toggle.vue';
export default {
i18n: {
@@ -54,6 +56,8 @@ export default {
},
},
components: {
+ GlDisclosureDropdown,
+ ContextSwitcherToggle,
GlSearchBoxByType,
GlLoadingIcon,
GlAlert,
@@ -83,6 +87,10 @@ export default {
required: false,
default: () => ({}),
},
+ contextHeader: {
+ type: Object,
+ required: true,
+ },
},
data() {
return {
@@ -90,6 +98,7 @@ export default {
projects: [],
groups: [],
hasError: false,
+ isOpen: false,
};
},
computed: {
@@ -100,16 +109,24 @@ export default {
return this.$apollo.queries.groupsAndProjects.loading;
},
},
+ watch: {
+ isOpen(isOpen) {
+ this.$emit('toggle', isOpen);
+
+ if (isOpen) {
+ this.focusInput();
+ }
+ },
+ },
created() {
if (this.currentContext.namespace) {
trackContextAccess(this.username, this.currentContext);
}
},
methods: {
- /**
- * This needs to be exposed publicly so that we can auto-focus the search input when the parent
- * GlCollapse is shown.
- */
+ close() {
+ this.$refs['disclosure-dropdown'].close();
+ },
focusInput() {
this.$refs['search-box'].focusInput();
},
@@ -117,13 +134,32 @@ export default {
Sentry.captureException(e);
this.hasError = true;
},
+ onDisclosureDropdownShown() {
+ this.isOpen = true;
+ },
+ onDisclosureDropdownHidden() {
+ this.isOpen = false;
+ },
},
DEFAULT_DEBOUNCE_AND_THROTTLE_MS,
+ popperOptions: {
+ modifiers: [maxSize, applyMaxSize],
+ },
};
</script>
<template>
- <div>
+ <gl-disclosure-dropdown
+ ref="disclosure-dropdown"
+ class="context-switcher gl-w-full"
+ placement="center"
+ :popper-options="$options.popperOptions"
+ @shown="onDisclosureDropdownShown"
+ @hidden="onDisclosureDropdownHidden"
+ >
+ <template #toggle>
+ <context-switcher-toggle :context="contextHeader" :expanded="isOpen" />
+ </template>
<div class="gl-p-1 gl-border-b gl-border-gray-50 gl-bg-white">
<gl-search-box-by-type
ref="search-box"
@@ -144,7 +180,7 @@ export default {
{{ $options.i18n.searchError }}
</gl-alert>
<nav v-else :aria-label="$options.i18n.contextNavigation">
- <ul class="gl-p-0 gl-list-style-none">
+ <ul class="gl-p-0 gl-m-0 gl-list-style-none">
<li v-if="!isSearch">
<div aria-hidden="true" class="gl-font-weight-bold gl-px-3 gl-py-3">
{{ $options.i18n.switchTo }}
@@ -172,5 +208,5 @@ export default {
/>
</ul>
</nav>
- </div>
+ </gl-disclosure-dropdown>
</template>
diff --git a/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue b/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue
index 704b087c534..319ccb1ed63 100644
--- a/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue
+++ b/app/assets/javascripts/super_sidebar/components/context_switcher_toggle.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTruncate, GlAvatar, GlCollapseToggleDirective, GlIcon } from '@gitlab/ui';
+import { GlTruncate, GlAvatar, GlIcon } from '@gitlab/ui';
export default {
components: {
@@ -7,9 +7,6 @@ export default {
GlAvatar,
GlIcon,
},
- directives: {
- CollapseToggle: GlCollapseToggleDirective,
- },
props: {
/*
* Contains metadata about the current view, e.g. `id`, `title` and `avatar`
@@ -36,7 +33,6 @@ export default {
<template>
<button
- v-collapse-toggle.context-switcher
type="button"
class="context-switcher-toggle gl-p-0 gl-bg-transparent gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-border-0 border-top border-bottom gl-border-gray-a-08 gl-box-shadow-none gl-display-flex gl-align-items-center gl-font-weight-bold gl-w-full gl-h-8 gl-flex-shrink-0"
>
diff --git a/app/assets/javascripts/super_sidebar/components/search_results.vue b/app/assets/javascripts/super_sidebar/components/search_results.vue
index cfd6184bc47..b1af3070801 100644
--- a/app/assets/javascripts/super_sidebar/components/search_results.vue
+++ b/app/assets/javascripts/super_sidebar/components/search_results.vue
@@ -82,7 +82,7 @@ export default {
<gl-icon :name="collapseIcon" :size="16" />
</button>
<gl-collapse :id="collapseId" v-model="expanded">
- <div v-if="isEmpty" data-testid="empty-text" class="gl-text-gray-500 gl-font-sm gl-my-3">
+ <div v-if="isEmpty" data-testid="empty-text" class="gl-text-gray-500 gl-font-sm gl-mb-3">
{{ noResultsText }}
</div>
<items-list :aria-label="title" :items="searchResults">
diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
index 94b7c1fb08a..4f312c72de5 100644
--- a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
+++ b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlCollapse } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import Mousetrap from 'mousetrap';
import { keysFor, TOGGLE_SUPER_SIDEBAR } from '~/behaviors/shortcuts/keybindings';
import { __ } from '~/locale';
@@ -12,7 +12,6 @@ import {
import { isCollapsed, toggleSuperSidebarCollapsed } from '../super_sidebar_collapsed_state_manager';
import UserBar from './user_bar.vue';
import SidebarPortalTarget from './sidebar_portal_target.vue';
-import ContextSwitcherToggle from './context_switcher_toggle.vue';
import ContextSwitcher from './context_switcher.vue';
import HelpCenter from './help_center.vue';
import SidebarMenu from './sidebar_menu.vue';
@@ -20,9 +19,7 @@ import SidebarMenu from './sidebar_menu.vue';
export default {
components: {
GlButton,
- GlCollapse,
UserBar,
- ContextSwitcherToggle,
ContextSwitcher,
HelpCenter,
SidebarMenu,
@@ -51,6 +48,13 @@ export default {
return this.sidebarData.current_menu_items || [];
},
},
+ watch: {
+ isCollapsed() {
+ if (this.isCollapsed) {
+ this.$refs['context-switcher'].close();
+ }
+ },
+ },
mounted() {
Mousetrap.bind(keysFor(TOGGLE_SUPER_SIDEBAR), this.toggleSidebar);
},
@@ -64,9 +68,6 @@ export default {
collapseSidebar() {
toggleSuperSidebarCollapsed(true, false);
},
- onContextSwitcherShown() {
- this.$refs['context-switcher'].focusInput();
- },
onHoverAreaMouseEnter() {
this.openPeekTimer = setTimeout(this.openPeek, SUPER_SIDEBAR_PEEK_OPEN_DELAY);
},
@@ -95,6 +96,9 @@ export default {
this.onSidebarMouseEnter();
this.onSidebarMouseLeave();
},
+ onContextSwitcherToggled(open) {
+ this.contextSwitcherOpen = open;
+ },
},
};
</script>
@@ -134,36 +138,28 @@ export default {
<trial-status-popover />
</div>
<div class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-overflow-hidden">
- <context-switcher-toggle
- :context="sidebarData.current_context_header"
- :expanded="contextSwitcherOpen"
- data-qa-selector="context_switcher"
- />
- <div class="gl-flex-grow-1 gl-overflow-auto">
- <gl-collapse
- id="context-switcher"
- v-model="contextSwitcherOpen"
- data-qa-selector="context_section"
- @shown="onContextSwitcherShown"
- >
- <context-switcher
- ref="context-switcher"
- :persistent-links="sidebarData.context_switcher_links"
- :username="sidebarData.username"
- :projects-path="sidebarData.projects_path"
- :groups-path="sidebarData.groups_path"
- :current-context="sidebarData.current_context"
- />
- </gl-collapse>
- <gl-collapse :visible="!contextSwitcherOpen">
- <sidebar-menu
- :items="menuItems"
- :panel-type="sidebarData.panel_type"
- :pinned-item-ids="sidebarData.pinned_items"
- :update-pins-url="sidebarData.update_pins_url"
- />
- <sidebar-portal-target />
- </gl-collapse>
+ <div
+ class="gl-flex-grow-1"
+ :class="{ 'gl-overflow-auto': !contextSwitcherOpen }"
+ data-testid="nav-container"
+ >
+ <context-switcher
+ ref="context-switcher"
+ :persistent-links="sidebarData.context_switcher_links"
+ :username="sidebarData.username"
+ :projects-path="sidebarData.projects_path"
+ :groups-path="sidebarData.groups_path"
+ :current-context="sidebarData.current_context"
+ :context-header="sidebarData.current_context_header"
+ @toggle="onContextSwitcherToggled"
+ />
+ <sidebar-menu
+ :items="menuItems"
+ :panel-type="sidebarData.panel_type"
+ :pinned-item-ids="sidebarData.pinned_items"
+ :update-pins-url="sidebarData.update_pins_url"
+ />
+ <sidebar-portal-target />
</div>
<div class="gl-p-3">
<help-center :sidebar-data="sidebarData" />
diff --git a/app/assets/javascripts/super_sidebar/popper_max_size_modifier.js b/app/assets/javascripts/super_sidebar/popper_max_size_modifier.js
new file mode 100644
index 00000000000..6581d521107
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/popper_max_size_modifier.js
@@ -0,0 +1,43 @@
+import { detectOverflow } from '@popperjs/core';
+
+/**
+ * These modifiers were copied from the community modifier popper-max-size-modifier
+ * https://www.npmjs.com/package/popper-max-size-modifier.
+ * We are considering upgrading Popper.js to Floating UI, at which point the behavior this
+ * introduces will be available out of the box.
+ * https://gitlab.com/gitlab-org/gitlab-ui/-/issues/2213
+ */
+
+export const maxSize = {
+ name: 'maxSize',
+ enabled: true,
+ phase: 'main',
+ requiresIfExists: ['offset', 'preventOverflow', 'flip'],
+ fn({ state, name }) {
+ const overflow = detectOverflow(state);
+ const { x, y } = state.modifiersData.preventOverflow || { x: 0, y: 0 };
+ const { width, height } = state.rects.popper;
+ const [basePlacement] = state.placement.split('-');
+
+ const widthProp = basePlacement === 'left' ? 'left' : 'right';
+ const heightProp = basePlacement === 'top' ? 'top' : 'bottom';
+
+ state.modifiersData[name] = {
+ width: width - overflow[widthProp] - x,
+ height: height - overflow[heightProp] - y,
+ };
+ },
+};
+
+export const applyMaxSize = {
+ name: 'applyMaxSize',
+ enabled: true,
+ phase: 'write',
+ requires: ['maxSize'],
+ fn({ state }) {
+ // The `maxSize` modifier provides this data
+ const { width, height } = state.modifiersData.maxSize;
+ state.elements.popper.style.maxWidth = `${width}px`;
+ state.elements.popper.style.maxHeight = `${height}px`;
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
index c19dfe663f4..25cf5335fb5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
@@ -5,7 +5,7 @@ import { STATUS_MERGED } from '~/issues/constants';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { HTTP_STATUS_UNAUTHORIZED } from '~/lib/utils/http_status';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { s__, __ } from '~/locale';
+import { s__, __, sprintf } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import eventHub from '../../event_hub';
import approvalsMixin from '../../mixins/approvals';
@@ -84,13 +84,22 @@ export default {
return Boolean(this.action);
},
invalidRules() {
- return this.approvals.approvalState?.invalidApproversRules || [];
+ return this.approvals.approvalState?.rules?.filter((rule) => rule.invalid) || [];
+ },
+ invalidApprovedRules() {
+ return this.invalidRules.filter((rule) => rule.allowMergeWhenInvalid);
+ },
+ invalidFailedRules() {
+ return this.invalidRules.filter((rule) => !rule.allowMergeWhenInvalid);
},
hasInvalidRules() {
return this.mr.mergeRequestApproversAvailable && this.invalidRules.length;
},
- invalidRulesText() {
- return this.invalidRules.length;
+ hasInvalidApprovedRules() {
+ return this.mr.mergeRequestApproversAvailable && this.invalidApprovedRules.length;
+ },
+ hasInvalidFailedRules() {
+ return this.mr.mergeRequestApproversAvailable && this.invalidFailedRules.length;
},
approvedBy() {
return this.approvals.approvedBy?.nodes || [];
@@ -133,11 +142,29 @@ export default {
return null;
},
- pluralizedRuleText() {
- return this.invalidRules.length > 1
+ pluralizedApprovedRuleText() {
+ return this.invalidApprovedRules.length > 1
? this.$options.i18n.invalidRulesPlural
: this.$options.i18n.invalidRuleSingular;
},
+ pluralizedFailedRuleText() {
+ return this.invalidFailedRules.length > 1
+ ? this.$options.i18n.invalidFailedRulesPlural
+ : this.$options.i18n.invalidFailedRuleSingular;
+ },
+ pluralizedRuleText() {
+ return [
+ this.hasInvalidFailedRules
+ ? sprintf(this.pluralizedFailedRuleText, { rules: this.invalidFailedRules.length })
+ : null,
+ this.hasInvalidApprovedRules
+ ? sprintf(this.pluralizedApprovedRuleText, { rules: this.invalidApprovedRules.length })
+ : null,
+ ]
+ .filter((text) => Boolean(text))
+ .join(', ')
+ .concat('.');
+ },
},
methods: {
approve() {
@@ -205,11 +232,13 @@ export default {
FETCH_LOADING,
linkToInvalidRules: INVALID_RULES_DOCS_PATH,
i18n: {
- invalidRuleSingular: s__(
- 'mrWidget|%{rules} invalid rule has been approved automatically, as no one can approve it.',
+ invalidRuleSingular: s__('mrWidget|%{rules} invalid rule has been approved automatically'),
+ invalidRulesPlural: s__('mrWidget|%{rules} invalid rules have been approved automatically'),
+ invalidFailedRuleSingular: s__(
+ "mrWidget|%{dangerStart}%{rules} rule can't be approved%{dangerEnd}",
),
- invalidRulesPlural: s__(
- 'mrWidget|%{rules} invalid rules have been approved automatically, as no one can approve them.',
+ invalidFailedRulesPlural: s__(
+ "mrWidget|%{dangerStart}%{rules} rules can't be approved%{dangerEnd}",
),
learnMore: __('Learn more.'),
},
@@ -255,7 +284,9 @@ export default {
</div>
<div v-if="hasInvalidRules" class="gl-text-gray-400 gl-mt-2" data-testid="invalid-rules">
<gl-sprintf :message="pluralizedRuleText">
- <template #rules>{{ invalidRulesText }}</template>
+ <template #danger="{ content }">
+ <span class="gl-font-weight-bold text-danger">{{ content }}</span>
+ </template>
</gl-sprintf>
</div>
</div>
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 7cb1fc293bd..884cb70cb9f 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -718,11 +718,13 @@
}
.dropdown-label-box {
- top: 0;
- left: 0;
- height: 100%;
- width: $gl-spacing-scale-2;
+ margin-right: $gl-spacing-scale-3;
+ margin-top: $gl-spacing-scale-2;
+ display: inline-block;
+ width: $gl-spacing-scale-5;
+ height: $gl-spacing-scale-3;
border-radius: $border-radius-base;
+ border: 1px solid var(--white, $white);
}
.git-revision-dropdown {
diff --git a/app/assets/stylesheets/framework/super_sidebar.scss b/app/assets/stylesheets/framework/super_sidebar.scss
index f3cbdb1e2eb..2653e0acb22 100644
--- a/app/assets/stylesheets/framework/super_sidebar.scss
+++ b/app/assets/stylesheets/framework/super_sidebar.scss
@@ -98,6 +98,14 @@
}
}
+ .context-switcher .gl-new-dropdown-custom-toggle {
+ width: 100%;
+ }
+
+ .context-switcher .gl-new-dropdown-panel {
+ overflow-y: auto;
+ }
+
.context-switcher-search-box input {
@include gl-font-sm;
}
diff --git a/config/initializers/active_record_database_tasks.rb b/config/initializers/active_record_database_tasks.rb
index 8b231f4af14..4c08f0bbe1f 100644
--- a/config/initializers/active_record_database_tasks.rb
+++ b/config/initializers/active_record_database_tasks.rb
@@ -3,5 +3,5 @@
return unless Gitlab.ee?
ActiveSupport.on_load(:active_record) do
- Gitlab::Patch::GeoDatabaseTasks.patch!
+ Gitlab::Patch::AdditionalDatabaseTasks.patch!
end
diff --git a/data/deprecations/15-8-default-private-user-profile.yml b/data/deprecations/15-8-default-private-user-profile.yml
deleted file mode 100644
index d07163e1ca9..00000000000
--- a/data/deprecations/15-8-default-private-user-profile.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-- title: "Null value for `private_profile` attribute in User API is deprecated" # (required) Clearly explain the change, or planned change. For example, "The `confidential` field for a `Note` is deprecated" or "CI/CD job names will be limited to 250 characters."
- announcement_milestone: "15.8" # (required) The milestone when this feature was first announced as deprecated.
- removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
- breaking_change: true # (required) Change to false if this is not a breaking change.
- reporter: lohrc # (required) GitLab username of the person reporting the change
- stage: manage # (required) String value of the stage that the feature was created in. e.g., Growth
- issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/387005 # (required) Link to the deprecation issue in GitLab
- body: | # (required) Do not modify this line, instead modify the lines below.
- When creating and updating users through the API, `null` was a valid value for the `private_profile` attribute, which would internally be converted to the default value. Starting with 16.0, `null` will no longer be a valid value for this parameter, and the response will be a 400 if used. Now the only valid values are `true` and `false`.
diff --git a/db/docs/schema_migrations.yml b/db/docs/schema_migrations.yml
index f5b52bc4db2..3aba0ea1d1b 100644
--- a/db/docs/schema_migrations.yml
+++ b/db/docs/schema_migrations.yml
@@ -2,11 +2,12 @@
table_name: schema_migrations
classes:
- ActiveRecord::SchemaMigration
+- Embedding::SchemaMigration
- Geo::TrackingBase::SchemaMigration
feature_categories:
- database
-description: >-
- An internal table used by ActiveRecord to keep track of which migrations have been applied to the database.
+description: An internal table used by ActiveRecord to keep track of which migrations
+ have been applied to the database.
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/9ba1224867665844b117fa037e1465bb706b3685
milestone: '0.8'
gitlab_schema: gitlab_internal
diff --git a/doc/.vale/gitlab/CIConfigFile.yml b/doc/.vale/gitlab/CIConfigFile.yml
index 4d2ba454410..5cbd02e799b 100644
--- a/doc/.vale/gitlab/CIConfigFile.yml
+++ b/doc/.vale/gitlab/CIConfigFile.yml
@@ -10,8 +10,4 @@ link: https://docs.gitlab.com/ee/development/documentation/versions.html
level: error
scope: raw
raw:
- - '(`gitlab-ci.yml`|'
- - '`gitlabci.yml`|'
- - '`gitlab.ci.yml`|'
- - '`.gitlab.ci-yml`|'
- - '`.gitlab-ci.yaml`)'
+ - '(?!`\.gitlab-ci\.yml`)`.?gitlab.?ci.?ya?ml`'
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index cbff4031550..0f9f7eae1aa 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -159,11 +159,35 @@ You can view different events depending on the version of GitLab you have.
The following actions on groups generate group audit events:
+#### Group management
+
- Group name or path changed.
- Group repository size limit changed.
- Group created or deleted.
- Group changed visibility.
- User was added to group and with which [permissions](../user/permissions.md).
+- Removed user from group.
+- Project repository imported into group.
+- [Project shared with group](../user/project/members/share_project_with_groups.md) and with which
+ [permissions](../user/permissions.md).
+- Removal of a previously shared group with a project.
+- LFS enabled or disabled.
+- Membership lock enabled or disabled.
+- Request access enabled or disabled.
+- Roles allowed to create project changed.
+- Group deploy token was successfully created, revoked, or deleted.
+ [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452) in GitLab 14.9.
+- Failed attempt to create a group deploy token. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452)
+ in GitLab 14.9.
+- [IP restrictions](../user/group/access_and_permissions.md#restrict-group-access-by-ip-address) changed.
+ [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358986) in GitLab 15.0.
+- Group had a security policy project linked, changed, or unlinked.
+ [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/377877) in GitLab 15.6.
+- An environment is protected or unprotected.
+ [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216164) in GitLab 15.8.
+
+#### Authentication and authorization
+
- User sign-in using [Group SAML](../user/group/saml_sso/index.md).
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8071) in GitLab 14.5, changes to the following
[group SAML](../user/group/saml_sso/index.md) configuration:
@@ -177,32 +201,28 @@ The following actions on groups generate group audit events:
- Default membership role.
- SSO-SAML group sync configuration.
- Permissions changes of a user assigned to a group.
-- Removed user from group.
-- Project repository imported into group.
-- [Project shared with group](../user/project/members/share_project_with_groups.md) and with which
- [permissions](../user/permissions.md).
-- Removal of a previously shared group with a project.
-- LFS enabled or disabled.
-- Shared runners minutes limit changed.
-- Membership lock enabled or disabled.
-- Request access enabled or disabled.
- 2FA enforcement or grace period changed.
-- Roles allowed to create project changed.
-- Group CI/CD variable added, removed, or protected status changed.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.3.
+
+#### Compliance and security
+
- Compliance framework created, updated, or deleted.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340649) in GitLab 14.5.
- Event streaming destination created, updated, or deleted.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344664) in GitLab 14.6.
+- Changes to push rules. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227629) in GitLab 15.0.
+- Changes to streaming audit destination custom HTTP headers.
+ [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366350) in GitLab 15.3.
- Instance administrator started or stopped impersonation of a group member.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300961) in GitLab 14.8.
-- Group deploy token was successfully created, revoked, or deleted.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452) in GitLab 14.9.
-- Failed attempt to create a group deploy token. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353452)
- in GitLab 14.9.
-- [IP restrictions](../user/group/access_and_permissions.md#restrict-group-access-by-ip-address) changed.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358986) in GitLab 15.0.
-- Changes to push rules. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227629) in GitLab 15.0.
+
+#### CI/CD
+
+- Shared runners minutes limit changed.
+- Group CI/CD variable added, removed, or protected status changed.
+ [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.3.
+
+#### Code collaboration
+
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/356152) in GitLab 15.1, changes to the following merge
request approvals settings:
- Prevent approval by author.
@@ -210,12 +230,6 @@ The following actions on groups generate group audit events:
- Prevent editing approval rules in projects and merge requests.
- Require user password to approve.
- Remove all approvals when commits are added to the source branch.
-- Changes to streaming audit destination custom HTTP headers.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366350) in GitLab 15.3.
-- Group had a security policy project linked, changed, or unlinked.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/377877) in GitLab 15.6.
-- An environment is protected or unprotected.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216164) in GitLab 15.8.
- Changes to Code Suggestions.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/405295) in GitLab 15.11.
diff --git a/doc/administration/package_information/supported_os.md b/doc/administration/package_information/supported_os.md
index ea87dfb6e28..95630a7973f 100644
--- a/doc/administration/package_information/supported_os.md
+++ b/doc/administration/package_information/supported_os.md
@@ -15,6 +15,11 @@ operating systems supported by GitLab are listed in the
The following lists the currently supported OSs and their possible EOL dates.
+NOTE:
+`amd64` and `x86_64` refer to the same 64-bit architecture.
+The names `arm64` and `aarch64` are also interchangeable and refer to the same
+architecture.
+
| OS Version | First supported GitLab version | Arch | Install Documentation | OS EOL | Details |
| ------------------------------------------------------------ | ------------------------------ | --------------- | :----------------------------------------------------------: | ---------- | ------------------------------------------------------------ |
| AlmaLinux 8 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | [AlmaLinux Install Documentation](https://about.gitlab.com/install/#almalinux-8) | 2029 | <https://almalinux.org/> |
diff --git a/doc/api/rest/deprecations.md b/doc/api/rest/deprecations.md
index 7bfc9e1f59e..0299a2c4a73 100644
--- a/doc/api/rest/deprecations.md
+++ b/doc/api/rest/deprecations.md
@@ -31,6 +31,12 @@ has been deprecated in favor of the `detailed_merge_status` field which more cor
all of the potential statuses that a merge request can be in. API users are encouraged to use the
new `detailed_merge_status` field instead. The `merge_status` field will be removed in v5 of the GitLab REST API.
+### Null value for `private_profile` attribute in User API
+
+Breaking change. [Related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/387005).
+
+When creating and updating users through the API, `null` was a valid value for the `private_profile` attribute, which would internally be converted to the default value. In v5 of the GitLab REST API, `null` will no longer be a valid value for this parameter, and the response will be a 400 if used. After this change, the only valid values will be `true` and `false`.
+
## Single merge request changes API endpoint
Breaking change. [Related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/322117).
diff --git a/doc/development/database/database_dictionary.md b/doc/development/database/database_dictionary.md
index 515bf00c6f0..84b76ddc34c 100644
--- a/doc/development/database/database_dictionary.md
+++ b/doc/development/database/database_dictionary.md
@@ -12,7 +12,8 @@ locate the feature categories responsible for specific database tables.
## Location
Database dictionary metadata files are stored in the `gitlab` project under `db/docs/` for the `main` and `ci` databases.
-For the `geo` database, the dictionary files are stored under `ee/db/docs/`.
+For the `embedding` database, the dictionary files are stored under `ee/db/embedding/docs/`.
+For the `geo` database, the dictionary files are stored under `ee/db/geo/docs/`.
## Example dictionary file
@@ -51,7 +52,8 @@ When adding a table, you should:
- `gitlab_main` table: `db/docs/`
- `gitlab_ci` table: `db/docs/`
- `gitlab_shared` table: `db/docs/`
- - `gitlab_geo` table: `ee/db/docs/`
+ - `gitlab_embedding` table: `ee/db/embedding/docs/`
+ - `gitlab_geo` table: `ee/db/geo/docs/`
1. Name the file `<table_name>.yml`, and include as much information as you know about the table.
1. Include this file in the commit with the migration that creates the table.
@@ -79,7 +81,8 @@ When dropping a table, you should:
- `gitlab_main` table: `db/docs/deleted_tables/`
- `gitlab_ci` table: `db/docs/deleted_tables/`
- `gitlab_shared` table: `db/docs/deleted_tables/`
- - `gitlab_geo` table: `ee/db/docs/deleted_tables/`
+ - `gitlab_embedding` table: `ee/db/embedding/docs/deleted_tables/`
+ - `gitlab_geo` table: `ee/db/geo/docs/deleted_tables/`
1. Add the fields `removed_by_url` and `removed_in_milestone` to the dictionary file.
1. Include this change in the commit with the migration that drops the table.
@@ -105,7 +108,8 @@ When adding a new view, you should:
- `gitlab_main` view: `db/docs/views/`
- `gitlab_ci` view: `db/docs/views/`
- `gitlab_shared` view: `db/docs/views/`
- - `gitlab_geo` view: `ee/db/docs/views/`
+ - `gitlab_embedding` view: `ee/db/embedding/docs/views/`
+ - `gitlab_geo` view: `ee/db/geo/docs/views/`
1. Name the file `<view_name>.yml`, and include as much information as you know about the view.
1. Include this file in the commit with the migration that creates the view.
@@ -133,6 +137,7 @@ When dropping a view, you should:
- `gitlab_main` view: `db/docs/deleted_views/`
- `gitlab_ci` view: `db/docs/deleted_views/`
- `gitlab_shared` view: `db/docs/deleted_views/`
- - `gitlab_geo` view: `ee/db/docs/deleted_views/`
+ - `gitlab_embedding` view: `ee/db/embedding/docs/deleted_views/`
+ - `gitlab_geo` view: `ee/db/geo/docs/deleted_views/`
1. Add the fields `removed_by_url` and `removed_in_milestone` to the dictionary file.
1. Include this change in the commit with the migration that drops the view.
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index c2c49d6afe3..7ef6a542993 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -104,7 +104,7 @@ It's not possible to create branches from Jira for self-managed instances. For m
### Set up your instance
-See [prerequisites](#prerequisites).
+[Prerequisites](#prerequisites)
To set up your self-managed instance for the GitLab for Jira Cloud app in GitLab 15.7 and later:
@@ -116,7 +116,7 @@ To set up your self-managed instance for the GitLab for Jira Cloud app in GitLab
### Link your instance
-See [prerequisites](#prerequisites).
+[Prerequisites](#prerequisites)
To link your self-managed instance to the GitLab for Jira Cloud app:
@@ -145,7 +145,7 @@ self-managed GitLab instances with Jira Cloud, you can do one of the following:
### Install the application in development mode
-See [prerequisites](#prerequisites-1).
+[Prerequisites](#prerequisites-1)
To configure your Atlassian Cloud instance so you can install applications
from outside the Marketplace:
@@ -173,12 +173,12 @@ then reinstall the application.
### Create a Marketplace listing
+[Prerequisites](#prerequisites-1)
+
If you don't want to use development mode on your Jira instance, you can create
your own Marketplace listing. This way, your application
can be installed from the Atlassian Marketplace.
-See [prerequisites](#prerequisites-1).
-
To create a Marketplace listing:
1. Register as a Marketplace vendor.
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 1ebfff9acc5..53d1d356a77 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -1376,19 +1376,6 @@ and `config/redis.shared_state.yml` files.
<div class="deprecation breaking-change" data-milestone="16.0">
-### Null value for `private_profile` attribute in User API is deprecated
-
-<div class="deprecation-notes">
-- Announced in: GitLab <span class="milestone">15.8</span>
-- [Breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/)
-</div>
-
-When creating and updating users through the API, `null` was a valid value for the `private_profile` attribute, which would internally be converted to the default value. Starting with 16.0, `null` will no longer be a valid value for this parameter, and the response will be a 400 if used. Now the only valid values are `true` and `false`.
-
-</div>
-
-<div class="deprecation breaking-change" data-milestone="16.0">
-
### Old versions of JSON web tokens are deprecated
<div class="deprecation-notes">
diff --git a/doc/user/application_security/dast/proxy-based.md b/doc/user/application_security/dast/proxy-based.md
index ae2d04ae4bb..8b71e340a43 100644
--- a/doc/user/application_security/dast/proxy-based.md
+++ b/doc/user/application_security/dast/proxy-based.md
@@ -80,7 +80,7 @@ To enable DAST to run automatically, either:
- Enable [Auto DAST](../../../topics/autodevops/stages.md#auto-dast) (provided
by [Auto DevOps](../../../topics/autodevops/index.md)).
-- [Edit the `.gitlab.ci.yml` file manually](#edit-the-gitlab-ciyml-file-manually).
+- [Edit the `.gitlab-ci.yml` file manually](#edit-the-gitlab-ciyml-file-manually).
- [Configure DAST using the UI](#configure-dast-using-the-ui).
#### Edit the `.gitlab-ci.yml` file manually
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index b95abfdc1fc..b63db28bfc6 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -144,7 +144,7 @@ To enable Secret Detection, either:
- Enable [Auto DevOps](../../../topics/autodevops/index.md), which includes [Auto Secret Detection](../../../topics/autodevops/stages.md#auto-secret-detection).
-- [Edit the `.gitlab.ci.yml` file manually](#edit-the-gitlab-ciyml-file-manually). Use this method
+- [Edit the `.gitlab-ci.yml` file manually](#edit-the-gitlab-ciyml-file-manually). Use this method
if your `.gitlab-ci.yml` file is complex.
- [Use an automatically configured merge request](#use-an-automatically-configured-merge-request).
diff --git a/doc/user/group/saml_sso/img/group_saml_configuration_information.png b/doc/user/group/saml_sso/img/group_saml_configuration_information.png
deleted file mode 100644
index e03c50ceb01..00000000000
--- a/doc/user/group/saml_sso/img/group_saml_configuration_information.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/saml_sso/img/group_saml_settings_v13_12.png b/doc/user/group/saml_sso/img/group_saml_settings_v13_12.png
deleted file mode 100644
index 2271f281655..00000000000
--- a/doc/user/group/saml_sso/img/group_saml_settings_v13_12.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/ml/experiment_tracking/img/candidate_v15_7.png b/doc/user/project/ml/experiment_tracking/img/candidate_v15_7.png
deleted file mode 100644
index fb2e2e706d6..00000000000
--- a/doc/user/project/ml/experiment_tracking/img/candidate_v15_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/ml/experiment_tracking/img/candidates_v15_7.png b/doc/user/project/ml/experiment_tracking/img/candidates_v15_7.png
deleted file mode 100644
index 58dfe94a108..00000000000
--- a/doc/user/project/ml/experiment_tracking/img/candidates_v15_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/ml/experiment_tracking/img/experiments_v15_7.png b/doc/user/project/ml/experiment_tracking/img/experiments_v15_7.png
deleted file mode 100644
index a7d4a3e559f..00000000000
--- a/doc/user/project/ml/experiment_tracking/img/experiments_v15_7.png
+++ /dev/null
Binary files differ
diff --git a/lib/api/package_files.rb b/lib/api/package_files.rb
index bb9f96cdbb1..7ff49f326d9 100644
--- a/lib/api/package_files.rb
+++ b/lib/api/package_files.rb
@@ -29,6 +29,7 @@ module API
params do
use :pagination
end
+ route_setting :authentication, job_token_allowed: true
get ':id/packages/:package_id/package_files' do
package = ::Packages::PackageFinder
.new(user_project, params[:package_id]).execute
@@ -51,6 +52,7 @@ module API
params do
requires :package_file_id, type: Integer, desc: 'ID of a package file'
end
+ route_setting :authentication, job_token_allowed: true
delete ':id/packages/:package_id/package_files/:package_file_id' do
authorize_destroy_package!(user_project)
diff --git a/lib/gitlab/database/gitlab_schema.rb b/lib/gitlab/database/gitlab_schema.rb
index 926a4aeedf1..f11458945f4 100644
--- a/lib/gitlab/database/gitlab_schema.rb
+++ b/lib/gitlab/database/gitlab_schema.rb
@@ -23,6 +23,7 @@ module Gitlab
tables.map { |table| table_schema(table, undefined: undefined) }.to_set
end
+ # rubocop:disable Metrics/CyclomaticComplexity
def self.table_schema(name, undefined: true)
schema_name, table_name = name.split('.', 2) # Strip schema name like: `public.`
@@ -57,6 +58,8 @@ module Gitlab
return :gitlab_ci if table_name.start_with?('_test_gitlab_ci_')
+ return :gitlab_embedding if table_name.start_with?('_test_gitlab_embedding_')
+
return :gitlab_geo if table_name.start_with?('_test_gitlab_geo_')
# All tables that start with `_test_` without a following schema are shared and ignored
@@ -68,6 +71,7 @@ module Gitlab
# When undefined it's best to return a unique name so that we don't incorrectly assume that 2 undefined schemas belong on the same database
undefined ? :"undefined_#{table_name}" : nil
end
+ # rubocop:enable Metrics/CyclomaticComplexity
def self.dictionary_path_globs
[Rails.root.join(DICTIONARY_PATH, '*.yml')]
diff --git a/lib/gitlab/database/tables_locker.rb b/lib/gitlab/database/tables_locker.rb
index 1b6ab3fb24b..0b0d46f4b0e 100644
--- a/lib/gitlab/database/tables_locker.rb
+++ b/lib/gitlab/database/tables_locker.rb
@@ -3,7 +3,7 @@
module Gitlab
module Database
class TablesLocker
- GITLAB_SCHEMAS_TO_IGNORE = %i[gitlab_geo].freeze
+ GITLAB_SCHEMAS_TO_IGNORE = %i[gitlab_embedding gitlab_geo].freeze
def initialize(logger: nil, dry_run: false)
@logger = logger
diff --git a/lib/gitlab/patch/database_config.rb b/lib/gitlab/patch/database_config.rb
index 20d8f7be8fd..8a7566f6e0e 100644
--- a/lib/gitlab/patch/database_config.rb
+++ b/lib/gitlab/patch/database_config.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# The purpose of this code is to set the migrations path
-# for the Geo tracking database.
+# for the Geo tracking database and the embedding database.
module Gitlab
module Patch
module DatabaseConfig
@@ -10,13 +10,17 @@ module Gitlab
def database_configuration
super.to_h do |env, configs|
if Gitlab.ee?
- if configs.key?("geo")
- migrations_paths = Array(configs["geo"]["migrations_paths"])
- migrations_paths << "ee/db/geo/migrate" if migrations_paths.empty?
- migrations_paths << "ee/db/geo/post_migrate" unless ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS']
+ ee_databases = %w[embedding geo]
- configs["geo"]["migrations_paths"] = migrations_paths.uniq
- configs["geo"]["schema_migrations_path"] = "ee/db/geo/schema_migrations" if configs["geo"]["schema_migrations_path"].blank?
+ ee_databases.each do |ee_db_name|
+ next unless configs.key?(ee_db_name)
+
+ migrations_paths = Array(configs[ee_db_name]['migrations_paths'])
+ migrations_paths << File.join('ee', 'db', ee_db_name, 'migrate') if migrations_paths.empty?
+ migrations_paths << File.join('ee', 'db', ee_db_name, 'post_migrate') unless ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS']
+
+ configs[ee_db_name]['migrations_paths'] = migrations_paths.uniq
+ configs[ee_db_name]['schema_migrations_path'] = File.join('ee', 'db', ee_db_name, 'schema_migrations') if configs[ee_db_name]['schema_migrations_path'].blank?
end
end
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 963fe23c682..7d95f744d44 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -4,6 +4,7 @@ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
def each_database(databases, include_geo: false)
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |database|
+ next if database == 'embedding'
next if !include_geo && database == 'geo'
yield database
@@ -472,15 +473,19 @@ namespace :gitlab do
end
namespace :dictionary do
- DB_DOCS_PATH = File.join(Rails.root, 'db', 'docs')
- EE_DICTIONARY_PATH = File.join(Rails.root, 'ee', 'db', 'docs')
+ DB_DOCS_PATH = Rails.root.join('db', 'docs')
desc 'Generate database docs yaml'
task generate: :environment do
next if Gitlab.jh?
FileUtils.mkdir_p(DB_DOCS_PATH)
- FileUtils.mkdir_p(EE_DICTIONARY_PATH) if Gitlab.ee?
+
+ if Gitlab.ee?
+ Gitlab::Database::EE_DATABASES_NAME_TO_DIR.each do |_, ee_db_dir|
+ FileUtils.mkdir_p(Rails.root.join(ee_db_dir, 'docs'))
+ end
+ end
Rails.application.eager_load!
@@ -558,7 +563,11 @@ namespace :gitlab do
def dictionary_file_path(source_name, views, database)
sub_directory = views.include?(source_name) ? 'views' : ''
- path = database == 'geo' ? EE_DICTIONARY_PATH : DB_DOCS_PATH
+ path = if Gitlab.ee? && Gitlab::Database::EE_DATABASES_NAME_TO_DIR.key?(database.to_s)
+ Rails.root.join(Gitlab::Database::EE_DATABASES_NAME_TO_DIR[database.to_s], 'docs')
+ else
+ DB_DOCS_PATH
+ end
File.join(path, sub_directory, "#{source_name}.yml")
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 19425dcee23..187df1ef8da 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -859,9 +859,6 @@ msgstr ""
msgid "%{linkStart} Learn more%{linkEnd}."
msgstr ""
-msgid "%{linkStart}Approval settings%{linkEnd} prevent approvals by its eligible approvers."
-msgstr ""
-
msgid "%{listToShow}, and %{awardsListLength} more"
msgstr ""
@@ -5490,9 +5487,39 @@ msgstr ""
msgid "Approvals required"
msgstr ""
+msgid "Approvals|%{count} of %{total}"
+msgstr ""
+
+msgid "Approvals|Action required"
+msgstr ""
+
+msgid "Approvals|Auto approved"
+msgstr ""
+
+msgid "Approvals|It looks like there was a conflict between the rules for approving this Merge Request and the users who were eligible to approve it. As a result, the system has automatically approved it to keep things moving."
+msgstr ""
+
+msgid "Approvals|Rule automatically approved"
+msgstr ""
+
+msgid "Approvals|Rule cannot be approved"
+msgstr ""
+
msgid "Approvals|Section: %section"
msgstr ""
+msgid "Approvals|The number of people who need to approve this is more than those who are allowed to. Please ask the project owner to update %{securityPolicy}."
+msgstr ""
+
+msgid "Approvals|Verify the number of %{linkStart}eligible security approvers%{linkEnd} matches the required approvers for the security policy."
+msgstr ""
+
+msgid "Approvals|Verify your %{eligibleApproverLinkStart}eligible approvers%{eligibleApproverLinkEnd} and %{approvalSettingsLinkStart}approval settings%{approvalSettingsLinkEnd} agree with each other."
+msgstr ""
+
+msgid "Approvals|Verify your %{linkStart}approval settings%{linkEnd} do not conflict with this rule."
+msgstr ""
+
msgid "Approve"
msgstr ""
@@ -8806,13 +8833,13 @@ msgstr ""
msgid "Checkout"
msgstr ""
-msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
+msgid "Checkout|$%{pricePerUserPerYear} per user per year"
msgstr ""
-msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
+msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
msgstr ""
-msgid "Checkout|$%{selectedPlanPrice} per user per year"
+msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
msgstr ""
msgid "Checkout|%d CI minute pack"
@@ -23713,9 +23740,6 @@ msgstr ""
msgid "Introducing Your DevOps Reports"
msgstr ""
-msgid "Invalid"
-msgstr ""
-
msgid "Invalid Insights config file detected"
msgstr ""
@@ -23776,9 +23800,6 @@ msgstr ""
msgid "Invalid repository path"
msgstr ""
-msgid "Invalid rules are automatically approved to unblock the merge request."
-msgstr ""
-
msgid "Invalid server response"
msgstr ""
@@ -24411,9 +24432,6 @@ msgstr ""
msgid "Issue|Title"
msgstr ""
-msgid "It doesn't have any %{linkStart}eligible approvers%{linkEnd}."
-msgstr ""
-
msgid "It looks like you're attempting to activate your subscription. Use %{a_start}the Subscription page%{a_end} instead."
msgstr ""
@@ -45605,9 +45623,6 @@ msgstr ""
msgid "This repository was last checked %{last_check_timestamp}. The check passed."
msgstr ""
-msgid "This rule is invalid because no one can approve it for one or more of these reasons:"
-msgstr ""
-
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
@@ -49835,9 +49850,6 @@ msgstr ""
msgid "Why can't I approve?"
msgstr ""
-msgid "Why is this rule invalid?"
-msgstr ""
-
msgid "Wiki"
msgstr ""
@@ -52928,6 +52940,12 @@ msgstr ""
msgid "mrWidget|%{boldStart}Ready to be merged automatically.%{boldEnd} Ask someone with write access to this repository to merge this request."
msgstr ""
+msgid "mrWidget|%{dangerStart}%{rules} rule can't be approved%{dangerEnd}"
+msgstr ""
+
+msgid "mrWidget|%{dangerStart}%{rules} rules can't be approved%{dangerEnd}"
+msgstr ""
+
msgid "mrWidget|%{mergeError}."
msgstr ""
@@ -52943,10 +52961,10 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
-msgid "mrWidget|%{rules} invalid rule has been approved automatically, as no one can approve it."
+msgid "mrWidget|%{rules} invalid rule has been approved automatically"
msgstr ""
-msgid "mrWidget|%{rules} invalid rules have been approved automatically, as no one can approve them."
+msgid "mrWidget|%{rules} invalid rules have been approved automatically"
msgstr ""
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb
index db8fc079774..d49280c39e4 100644
--- a/rubocop/migration_helpers.rb
+++ b/rubocop/migration_helpers.rb
@@ -42,11 +42,11 @@ module RuboCop
end
def in_deployment_migration?(node)
- dirname(node).end_with?('db/migrate', 'db/geo/migrate')
+ dirname(node).end_with?('db/migrate', 'db/embedding/migrate', 'db/geo/migrate')
end
def in_post_deployment_migration?(node)
- dirname(node).end_with?('db/post_migrate', 'db/geo/post_migrate')
+ dirname(node).end_with?('db/post_migrate', 'db/embedding/post_migrate', 'db/geo/post_migrate')
end
# Returns true if we've defined an 'EnforcedSince' variable in rubocop.yml and the migration version
diff --git a/spec/frontend/super_sidebar/components/context_switcher_spec.js b/spec/frontend/super_sidebar/components/context_switcher_spec.js
index 11da6ef1243..7928ee6400c 100644
--- a/spec/frontend/super_sidebar/components/context_switcher_spec.js
+++ b/spec/frontend/super_sidebar/components/context_switcher_spec.js
@@ -1,10 +1,11 @@
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { GlSearchBoxByType, GlLoadingIcon, GlAlert } from '@gitlab/ui';
+import { GlDisclosureDropdown, GlSearchBoxByType, GlLoadingIcon, GlAlert } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import { s__ } from '~/locale';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ContextSwitcher from '~/super_sidebar/components/context_switcher.vue';
+import ContextSwitcherToggle from '~/super_sidebar/components/context_switcher_toggle.vue';
import NavItem from '~/super_sidebar/components/nav_item.vue';
import ProjectsList from '~/super_sidebar/components/projects_list.vue';
import GroupsList from '~/super_sidebar/components/groups_list.vue';
@@ -31,6 +32,7 @@ const persistentLinks = [
const username = 'root';
const projectsPath = 'projectsPath';
const groupsPath = 'groupsPath';
+const contextHeader = { avatar_shape: 'circle' };
Vue.use(VueApollo);
@@ -38,6 +40,8 @@ describe('ContextSwitcher component', () => {
let wrapper;
let mockApollo;
+ const findDisclosureDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
+ const findContextSwitcherToggle = () => wrapper.findComponent(ContextSwitcherToggle);
const findNavItems = () => wrapper.findAllComponents(NavItem);
const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
const findProjectsList = () => wrapper.findComponent(ProjectsList);
@@ -72,9 +76,18 @@ describe('ContextSwitcher component', () => {
username,
projectsPath,
groupsPath,
+ contextHeader,
...props,
},
stubs: {
+ GlDisclosureDropdown: stubComponent(GlDisclosureDropdown, {
+ template: `
+ <div>
+ <slot name="toggle" />
+ <slot />
+ </div>
+ `,
+ }),
GlSearchBoxByType: stubComponent(GlSearchBoxByType, {
props: ['placeholder'],
methods: { focusInput: focusInputMock },
@@ -111,7 +124,7 @@ describe('ContextSwitcher component', () => {
);
});
- it('passes the correct props the frequent projects list', () => {
+ it('passes the correct props to the frequent projects list', () => {
expect(findProjectsList().props()).toEqual({
username,
viewAllLink: projectsPath,
@@ -120,7 +133,7 @@ describe('ContextSwitcher component', () => {
});
});
- it('passes the correct props the frequent groups list', () => {
+ it('passes the correct props to the frequent groups list', () => {
expect(findGroupsList().props()).toEqual({
username,
viewAllLink: groupsPath,
@@ -129,12 +142,6 @@ describe('ContextSwitcher component', () => {
});
});
- it('focuses the search input when focusInput is called', () => {
- wrapper.vm.focusInput();
-
- expect(focusInputMock).toHaveBeenCalledTimes(1);
- });
-
it('does not trigger the search query on mount', () => {
expect(searchUserProjectsAndGroupsHandlerSuccess).not.toHaveBeenCalled();
});
@@ -145,6 +152,45 @@ describe('ContextSwitcher component', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
+
+ it('passes the correct props to the toggle', () => {
+ expect(findContextSwitcherToggle().props('context')).toEqual(contextHeader);
+ expect(findContextSwitcherToggle().props('expanded')).toEqual(false);
+ });
+
+ it("passes Popper.js' options to the disclosure dropdown", () => {
+ expect(findDisclosureDropdown().props('popperOptions')).toMatchObject({
+ modifiers: expect.any(Array),
+ });
+ });
+
+ it('does not emit the `toggle` event initially', () => {
+ expect(wrapper.emitted('toggle')).toBe(undefined);
+ });
+ });
+
+ describe('visibility changes', () => {
+ beforeEach(() => {
+ createWrapper();
+ findDisclosureDropdown().vm.$emit('shown');
+ });
+
+ it('emits the `toggle` event, focuses the search input and puts the toggle in the expanded state when opened', () => {
+ expect(wrapper.emitted('toggle')).toHaveLength(1);
+ expect(wrapper.emitted('toggle')[0]).toEqual([true]);
+ expect(focusInputMock).toHaveBeenCalledTimes(1);
+ expect(findContextSwitcherToggle().props('expanded')).toBe(true);
+ });
+
+ it("emits the `toggle` event, does not attempt to focus the input, and resets the toggle's `expanded` props to `false` when closed", async () => {
+ findDisclosureDropdown().vm.$emit('hidden');
+ await nextTick();
+
+ expect(wrapper.emitted('toggle')).toHaveLength(2);
+ expect(wrapper.emitted('toggle')[1]).toEqual([false]);
+ expect(focusInputMock).toHaveBeenCalledTimes(1);
+ expect(findContextSwitcherToggle().props('expanded')).toBe(false);
+ });
});
describe('item access tracking', () => {
diff --git a/spec/frontend/super_sidebar/components/super_sidebar_spec.js b/spec/frontend/super_sidebar/components/super_sidebar_spec.js
index 72ed5dbba15..2d535b0c727 100644
--- a/spec/frontend/super_sidebar/components/super_sidebar_spec.js
+++ b/spec/frontend/super_sidebar/components/super_sidebar_spec.js
@@ -1,5 +1,4 @@
import { nextTick } from 'vue';
-import { GlCollapse } from '@gitlab/ui';
import Mousetrap from 'mousetrap';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SuperSidebar from '~/super_sidebar/components/super_sidebar.vue';
@@ -19,7 +18,7 @@ import { stubComponent } from 'helpers/stub_component';
import { sidebarData } from '../mock_data';
jest.mock('~/super_sidebar/super_sidebar_collapsed_state_manager');
-const focusInputMock = jest.fn();
+const closeContextSwitcherMock = jest.fn();
const trialStatusWidgetStubTestId = 'trial-status-widget';
const TrialStatusWidgetStub = { template: `<div data-testid="${trialStatusWidgetStubTestId}" />` };
@@ -34,6 +33,8 @@ describe('SuperSidebar component', () => {
const findSidebar = () => wrapper.findByTestId('super-sidebar');
const findHoverArea = () => wrapper.findByTestId('super-sidebar-hover-area');
const findUserBar = () => wrapper.findComponent(UserBar);
+ const findContextSwitcher = () => wrapper.findComponent(ContextSwitcher);
+ const findNavContainer = () => wrapper.findByTestId('nav-container');
const findHelpCenter = () => wrapper.findComponent(HelpCenter);
const findSidebarPortalTarget = () => wrapper.findComponent(SidebarPortalTarget);
const findTrialStatusWidget = () => wrapper.findByTestId(trialStatusWidgetStubTestId);
@@ -55,7 +56,7 @@ describe('SuperSidebar component', () => {
},
stubs: {
ContextSwitcher: stubComponent(ContextSwitcher, {
- methods: { focusInput: focusInputMock },
+ methods: { close: closeContextSwitcherMock },
}),
TrialStatusWidget: TrialStatusWidgetStub,
TrialStatusPopover: TrialStatusPopoverStub,
@@ -89,10 +90,10 @@ describe('SuperSidebar component', () => {
expect(findSidebarPortalTarget().exists()).toBe(true);
});
- it("does not call the context switcher's focusInput method initially", () => {
+ it("does not call the context switcher's close method initially", () => {
createWrapper();
- expect(focusInputMock).not.toHaveBeenCalled();
+ expect(closeContextSwitcherMock).not.toHaveBeenCalled();
});
it('renders hidden shortcut links', () => {
@@ -135,6 +136,17 @@ describe('SuperSidebar component', () => {
});
});
+ describe('on collapse', () => {
+ beforeEach(() => {
+ createWrapper();
+ wrapper.vm.isCollapsed = true;
+ });
+
+ it('closes the context switcher', () => {
+ expect(closeContextSwitcherMock).toHaveBeenCalled();
+ });
+ });
+
describe('when peeking on hover', () => {
const peekClass = 'super-sidebar-peek';
@@ -222,15 +234,20 @@ describe('SuperSidebar component', () => {
});
});
- describe('when opening the context switcher', () => {
+ describe('nav container', () => {
beforeEach(() => {
createWrapper();
- wrapper.findComponent(GlCollapse).vm.$emit('input', true);
- wrapper.findComponent(GlCollapse).vm.$emit('shown');
});
- it("calls the context switcher's focusInput method", () => {
- expect(focusInputMock).toHaveBeenCalledTimes(1);
+ it('allows overflow while the context switcher is closed', () => {
+ expect(findNavContainer().classes()).toContain('gl-overflow-auto');
+ });
+
+ it('hides overflow when context switcher is opened', async () => {
+ findContextSwitcher().vm.$emit('toggle', true);
+ await nextTick();
+
+ expect(findNavContainer().classes()).not.toContain('gl-overflow-auto');
});
});
diff --git a/spec/lib/gitlab/database/gitlab_schema_spec.rb b/spec/lib/gitlab/database/gitlab_schema_spec.rb
index b187b29c270..3d1e3a1c1af 100644
--- a/spec/lib/gitlab/database/gitlab_schema_spec.rb
+++ b/spec/lib/gitlab/database/gitlab_schema_spec.rb
@@ -51,8 +51,10 @@ RSpec.describe Gitlab::Database::GitlabSchema, feature_category: :database do
context "for #{db_config_name} using #{db_class}" do
let(:db_data_sources) { db_class.connection.data_sources }
- # The Geo database does not share the same structure as all decomposed databases
- subject { described_class.views_and_tables_to_schema.select { |_, v| v != :gitlab_geo } }
+ # The embedding and Geo databases do not share the same structure as all decomposed databases
+ subject do
+ described_class.views_and_tables_to_schema.reject { |_, v| v == :gitlab_embedding || v == :gitlab_geo }
+ end
it 'new data sources are added' do
missing_data_sources = db_data_sources.to_set - subject.keys
diff --git a/spec/requests/api/package_files_spec.rb b/spec/requests/api/package_files_spec.rb
index f47dca387ef..3b4bd2f3cf4 100644
--- a/spec/requests/api/package_files_spec.rb
+++ b/spec/requests/api/package_files_spec.rb
@@ -10,6 +10,15 @@ RSpec.describe API::PackageFiles, feature_category: :package_registry do
describe 'GET /projects/:id/packages/:package_id/package_files' do
let(:url) { "/projects/#{project.id}/packages/#{package.id}/package_files" }
+ shared_examples 'handling job token and returning' do |status:|
+ it "returns status #{status}" do
+ get api(url, job_token: job.token)
+
+ expect(response).to have_gitlab_http_status(status)
+ expect(response).to match_response_schema('public_api/v4/packages/package_files') if status == :ok
+ end
+ end
+
before do
project.add_developer(user)
end
@@ -27,6 +36,12 @@ RSpec.describe API::PackageFiles, feature_category: :package_registry do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ context 'with JOB-TOKEN auth' do
+ let(:job) { create(:ci_build, :running, user: user, project: project) }
+
+ it_behaves_like 'handling job token and returning', status: :ok
+ end
end
context 'project is private' do
@@ -52,6 +67,28 @@ RSpec.describe API::PackageFiles, feature_category: :package_registry do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/packages/package_files')
end
+
+ context 'with JOB-TOKEN auth' do
+ let(:job) { create(:ci_build, :running, user: user, project: project) }
+
+ context 'a non authenticated user' do
+ let(:user) { nil }
+
+ it_behaves_like 'handling job token and returning', status: :not_found
+ end
+
+ context 'a user without access to the project', :sidekiq_inline do
+ before do
+ project.team.truncate
+ end
+
+ it_behaves_like 'handling job token and returning', status: :not_found
+ end
+
+ context 'a user with access to the project' do
+ it_behaves_like 'handling job token and returning', status: :ok
+ end
+ end
end
context 'with pagination params' do
@@ -97,6 +134,18 @@ RSpec.describe API::PackageFiles, feature_category: :package_registry do
subject(:api_request) { delete api(url, user) }
+ shared_examples 'handling job token and returning' do |status:|
+ it "returns status #{status}", :aggregate_failures do
+ if status == :no_content
+ expect { api_request }.to change { package.package_files.pending_destruction.count }.by(1)
+ else
+ expect { api_request }.not_to change { package.package_files.pending_destruction.count }
+ end
+
+ expect(response).to have_gitlab_http_status(status)
+ end
+ end
+
context 'project is public' do
context 'without user' do
let(:user) { nil }
@@ -108,6 +157,14 @@ RSpec.describe API::PackageFiles, feature_category: :package_registry do
end
end
+ context 'with JOB-TOKEN auth' do
+ subject(:api_request) { delete api(url, job_token: job.token) }
+
+ let(:job) { create(:ci_build, :running, user: user, project: project) }
+
+ it_behaves_like 'handling job token and returning', status: :forbidden
+ end
+
it 'returns 403 for a user without access to the project', :aggregate_failures do
expect { api_request }.not_to change { package.package_files.pending_destruction.count }
@@ -175,6 +232,33 @@ RSpec.describe API::PackageFiles, feature_category: :package_registry do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'with JOB-TOKEN auth' do
+ subject(:api_request) { delete api(url, job_token: job.token) }
+
+ let(:job) { create(:ci_build, :running, user: user, project: project) }
+ let_it_be_with_refind(:project) { create(:project, :private) }
+
+ context 'a user without access to the project' do
+ it_behaves_like 'handling job token and returning', status: :not_found
+ end
+
+ context 'a user without enough permissions' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'handling job token and returning', status: :forbidden
+ end
+
+ context 'a user with the right permissions' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it_behaves_like 'handling job token and returning', status: :no_content
+ end
+ end
end
end
end
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index 45d0c050949..fb45bc0864d 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -566,6 +566,7 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor
end
if Gitlab.ee?
+ allow(File).to receive(:open).with(Rails.root.join(Gitlab::Database::EMBEDDING_DATABASE_DIR, 'structure.sql').to_s, any_args).and_yield(output)
allow(File).to receive(:open).with(Rails.root.join(Gitlab::Database::GEO_DATABASE_DIR, 'structure.sql').to_s, any_args).and_yield(output)
end
end