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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-31 21:10:31 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-31 21:10:31 +0300
commite9885f7a36065b9b45a35feb6c427c7742a906a4 (patch)
treebffa88df5eadcdf282eb0904a925b7c3cec13027
parentfab00cd7efb84b369dfb45cabb797f7feace4b66 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/CODEOWNERS6
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.checksum4
-rw-r--r--Gemfile.lock8
-rw-r--r--app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_trigger.vue2
-rw-r--r--app/assets/javascripts/authentication/password/components/password_input.vue10
-rw-r--r--app/assets/javascripts/projects/settings/components/access_dropdown.vue31
-rw-r--r--app/assets/javascripts/search/index.js2
-rw-r--r--app/assets/javascripts/search/sidebar/components/app.vue23
-rw-r--r--app/assets/javascripts/search/sidebar/components/scope_legacy_navigation.vue (renamed from app/assets/javascripts/search/sidebar/components/scope_navigation.vue)2
-rw-r--r--app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue (renamed from app/assets/javascripts/search/sidebar/components/scope_new_navigation.vue)2
-rw-r--r--app/assets/javascripts/search/store/index.js4
-rw-r--r--app/assets/javascripts/search/store/state.js4
-rw-r--r--app/graphql/types/ci/catalog/resource_type.rb27
-rw-r--r--app/services/packages/ml_model/create_package_file_service.rb46
-rw-r--r--app/services/packages/ml_model/find_or_create_package_service.rb11
-rw-r--r--app/views/projects/commits/_commits.html.haml8
-rw-r--r--doc/api/graphql/reference/index.md1
-rw-r--r--doc/development/pipelines/index.md2
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md20
-rw-r--r--glfm_specification/output_example_snapshots/html.yml28
-rw-r--r--lib/banzai/filter/sanitization_filter.rb2
-rw-r--r--lib/gitlab/usage_data.rb10
-rw-r--r--locale/gitlab.pot9
-rw-r--r--qa/qa/page/search/results.rb2
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb2
-rw-r--r--spec/controllers/admin/instance_review_controller_spec.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb2
-rw-r--r--spec/finders/projects_finder_spec.rb4
-rw-r--r--spec/frontend/projects/settings/components/new_access_dropdown_spec.js34
-rw-r--r--spec/frontend/search/sidebar/components/app_spec.js36
-rw-r--r--spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js (renamed from spec/frontend/search/sidebar/components/scope_navigation_spec.js)6
-rw-r--r--spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js (renamed from spec/frontend/search/sidebar/components/scope_new_navigation_spec.js)6
-rw-r--r--spec/graphql/types/ci/catalog/resource_type_spec.rb1
-rw-r--r--spec/lib/banzai/filter/footnote_filter_spec.rb12
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb12
-rw-r--r--spec/lib/banzai/pipeline/full_pipeline_spec.rb6
-rw-r--r--spec/lib/gitlab/checks/force_push_spec.rb30
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb8
-rw-r--r--spec/requests/api/usage_data_non_sql_metrics_spec.rb2
-rw-r--r--spec/requests/api/usage_data_queries_spec.rb2
-rw-r--r--spec/services/packages/ml_model/create_package_file_service_spec.rb94
-rw-r--r--spec/services/packages/ml_model/find_or_create_package_service_spec.rb67
-rw-r--r--spec/support/helpers/search_helpers.rb2
-rw-r--r--spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb3
-rw-r--r--spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb2
-rw-r--r--spec/tasks/gitlab/usage_data_rake_spec.rb2
47 files changed, 494 insertions, 109 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 7a45d32b666..85f601f19c7 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -30,6 +30,8 @@ GITALY_SERVER_VERSION @project_278964_bot6 @gitlab-org/maintainers/rails-backend
/doc/.markdownlint/ @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
/doc/.vale/ @marcel.amirault @eread @aqualls @gitlab-org/tw-leadership
/lib/tasks/gitlab/tw/codeowners.rake @aqualls @gitlab-org/tw-leadership
+/scripts/lint-doc.sh @marcel.amirault @eread @axil @sarahgerman @gitlab-org/tw-leadership
+/scripts/lint-docs-metadata.sh @marcel.amirault @eread @axil @sarahgerman @gitlab-org/tw-leadership
^[Source code editing]
.solargraph.yml.example @igor.drozdov
@@ -1434,8 +1436,8 @@ ee/lib/ee/api/entities/project.rb
/ee/lib/sidebars/
[Global Search] @gitlab-org/search-team/migration-maintainers
-/ee/elastic/migrate
-/ee/spec/elastic/migrate
+/ee/elastic/migrate/
+/ee/spec/elastic/migrate/
/ee/spec/support/elastic.rb
# JiHu GitLab rules. See https://gitlab.com/gitlab-jh/gitlab-jh-enablement/-/issues/213#note_1024367528
diff --git a/Gemfile b/Gemfile
index ff3f645ecc4..5c621c4545e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -182,7 +182,7 @@ gem 'typhoeus', '~> 1.4.0' # Used with Elasticsearch to support http keep-alive
gem 'html-pipeline', '~> 2.14.3'
gem 'deckar01-task_list', '2.3.2'
gem 'gitlab-markup', '~> 1.9.0', require: 'github/markup'
-gem 'commonmarker', '~> 0.23.6'
+gem 'commonmarker', '~> 0.23.9'
gem 'kramdown', '~> 2.3.1'
gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 6.3.2'
@@ -367,7 +367,7 @@ gem 'prometheus-client-mmap', '~> 0.24', require: 'prometheus/client'
gem 'warning', '~> 1.3.0'
group :development do
- gem 'lefthook', '~> 1.4.0', require: false
+ gem 'lefthook', '~> 1.4.1', require: false
gem 'rubocop'
gem 'solargraph', '~> 0.47.2', require: false
diff --git a/Gemfile.checksum b/Gemfile.checksum
index a7492e77dc2..b23ee78f108 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -84,7 +84,7 @@
{"name":"coderay","version":"1.1.3","platform":"ruby","checksum":"dc530018a4684512f8f38143cd2a096c9f02a1fc2459edcfe534787a7fc77d4b"},
{"name":"coercible","version":"1.0.0","platform":"ruby","checksum":"5081ad24352cc8435ce5472bc2faa30260c7ea7f2102cc6a9f167c4d9bffaadc"},
{"name":"colored2","version":"3.1.2","platform":"ruby","checksum":"b13c2bd7eeae2cf7356a62501d398e72fde78780bd26aec6a979578293c28b4a"},
-{"name":"commonmarker","version":"0.23.6","platform":"ruby","checksum":"c8aeaaaff4ba497bf180f762db63a0069794fafb6eff221224c9c8199d337b38"},
+{"name":"commonmarker","version":"0.23.9","platform":"ruby","checksum":"2e739c85a6961531cb6f5ba5169f2c7f64471b7e700c64b048ec22a5b230811c"},
{"name":"concurrent-ruby","version":"1.2.2","platform":"ruby","checksum":"3879119b8b75e3b62616acc256c64a134d0b0a7a9a3fcba5a233025bcde22c4f"},
{"name":"connection_pool","version":"2.3.0","platform":"ruby","checksum":"677985be912f33c90f98f229aaa0c0ddb2ef8776f21929a36eeeb25251c944da"},
{"name":"cork","version":"0.3.0","platform":"ruby","checksum":"a0a0ac50e262f8514d1abe0a14e95e71c98b24e3378690e5d044daf0013ad4bc"},
@@ -331,7 +331,7 @@
{"name":"kramdown-parser-gfm","version":"1.1.0","platform":"ruby","checksum":"fb39745516427d2988543bf01fc4cf0ab1149476382393e0e9c48592f6581729"},
{"name":"kubeclient","version":"4.11.0","platform":"ruby","checksum":"4985fcd749fb8c364a668a8350a49821647f03aa52d9ee6cbc582beb8e883fcc"},
{"name":"launchy","version":"2.5.0","platform":"ruby","checksum":"954243c4255920982ce682f89a42e76372dba94770bf09c23a523e204bdebef5"},
-{"name":"lefthook","version":"1.4.0","platform":"ruby","checksum":"363e055d4bf985a5409c548f7b0d584ab87902221f6c5b3a5cc3fcfc84a2f356"},
+{"name":"lefthook","version":"1.4.1","platform":"ruby","checksum":"b0cd741c3557ec3223d466cabd80a45e852bc9933645cd0b12b80f82acb18181"},
{"name":"letter_opener","version":"1.7.0","platform":"ruby","checksum":"095bc0d58e006e5b43ea7d219e64ecf2de8d1f7d9dafc432040a845cf59b4725"},
{"name":"letter_opener_web","version":"2.0.0","platform":"ruby","checksum":"33860ad41e1785d75456500e8ca8bba8ed71ee6eaf08a98d06bbab67c5577b6f"},
{"name":"libyajl2","version":"1.2.0","platform":"ruby","checksum":"1117cd1e48db013b626e36269bbf1cef210538ca6d2e62d3fa3db9ded005b258"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 0d6f2d36e9a..655953117e8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -307,7 +307,7 @@ GEM
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
colored2 (3.1.2)
- commonmarker (0.23.6)
+ commonmarker (0.23.9)
concurrent-ruby (1.2.2)
connection_pool (2.3.0)
cork (0.3.0)
@@ -878,7 +878,7 @@ GEM
rest-client (~> 2.0)
launchy (2.5.0)
addressable (~> 2.7)
- lefthook (1.4.0)
+ lefthook (1.4.1)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (2.0.0)
@@ -1690,7 +1690,7 @@ DEPENDENCIES
charlock_holmes (~> 0.7.7)
circuitbox (= 2.0.0)
cloud_profiler_agent (~> 0.0.0)!
- commonmarker (~> 0.23.6)
+ commonmarker (~> 0.23.9)
concurrent-ruby (~> 1.1)
connection_pool (~> 2.0)
countries (~> 4.0.0)
@@ -1803,7 +1803,7 @@ DEPENDENCIES
knapsack (~> 1.21.1)
kramdown (~> 2.3.1)
kubeclient (~> 4.11.0)
- lefthook (~> 1.4.0)
+ lefthook (~> 1.4.1)
letter_opener_web (~> 2.0.0)
license_finder (~> 7.0)
licensee (~> 9.15)
diff --git a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_trigger.vue b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_trigger.vue
index a58b6e62254..eb5d1d39142 100644
--- a/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_trigger.vue
+++ b/app/assets/javascripts/add_context_commits_modal/components/add_context_commits_modal_trigger.vue
@@ -38,7 +38,7 @@ export default {
:class="[
{
'gl-ml-5': !contextCommitsEmpty,
- 'gl-mt-5': !commitsEmpty && contextCommitsEmpty,
+ 'gl-mt-1': !commitsEmpty && contextCommitsEmpty,
},
]"
:variant="commitsEmpty ? 'confirm' : 'default'"
diff --git a/app/assets/javascripts/authentication/password/components/password_input.vue b/app/assets/javascripts/authentication/password/components/password_input.vue
index fa9a7782b74..6e3af96cf33 100644
--- a/app/assets/javascripts/authentication/password/components/password_input.vue
+++ b/app/assets/javascripts/authentication/password/components/password_input.vue
@@ -15,27 +15,27 @@ export default {
title: {
type: String,
required: false,
- default: '',
+ default: null,
},
id: {
type: String,
required: false,
- default: '',
+ default: null,
},
minimumPasswordLength: {
type: String,
required: false,
- default: '',
+ default: null,
},
qaSelector: {
type: String,
required: false,
- default: '',
+ default: null,
},
testid: {
type: String,
required: false,
- default: '',
+ default: null,
},
autocomplete: {
type: String,
diff --git a/app/assets/javascripts/projects/settings/components/access_dropdown.vue b/app/assets/javascripts/projects/settings/components/access_dropdown.vue
index 08a1c586f69..a2e4827cbfa 100644
--- a/app/assets/javascripts/projects/settings/components/access_dropdown.vue
+++ b/app/assets/javascripts/projects/settings/components/access_dropdown.vue
@@ -63,6 +63,11 @@ export default {
required: false,
default: () => [],
},
+ items: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
data() {
return {
@@ -143,11 +148,37 @@ export default {
query: debounce(function debouncedSearch() {
return this.getData();
}, 500),
+ items(items) {
+ this.setDataForSave(items);
+ },
},
created() {
this.getData({ initial: true });
},
methods: {
+ setDataForSave(items) {
+ this.selected = items.reduce(
+ (selected, item) => {
+ if (item.group_id) {
+ selected[LEVEL_TYPES.GROUP].push({ id: item.group_id, ...item });
+ } else if (item.user_id) {
+ selected[LEVEL_TYPES.USER].push({ id: item.user_id, ...item });
+ } else if (item.access_level) {
+ const level = this.accessLevelsData.find(({ id }) => item.access_level === id);
+ selected[LEVEL_TYPES.ROLE].push(level);
+ } else if (item.deploy_key_id) {
+ selected[LEVEL_TYPES.DEPLOY_KEY].push({ id: item.deploy_key_id, ...item });
+ }
+ return selected;
+ },
+ {
+ [LEVEL_TYPES.GROUP]: [],
+ [LEVEL_TYPES.USER]: [],
+ [LEVEL_TYPES.ROLE]: [],
+ [LEVEL_TYPES.DEPLOY_KEY]: [],
+ },
+ );
+ },
focusInput() {
this.$refs.search.focusInput();
},
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index 1e4b1e36514..f5684cebbf9 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -15,7 +15,7 @@ export const initSearchApp = () => {
const store = createStore({
query,
navigation,
- useNewNavigation: gon.use_new_navigation,
+ useSidebarNavigation: gon.use_new_navigation,
});
initTopbar(store);
diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue
index 317145d4cd1..7046a57058d 100644
--- a/app/assets/javascripts/search/sidebar/components/app.vue
+++ b/app/assets/javascripts/search/sidebar/components/app.vue
@@ -1,7 +1,7 @@
<script>
import { mapState, mapGetters } from 'vuex';
-import ScopeNavigation from '~/search/sidebar/components/scope_navigation.vue';
-import ScopeNewNavigation from '~/search/sidebar/components/scope_new_navigation.vue';
+import ScopeLegacyNavigation from '~/search/sidebar/components/scope_legacy_navigation.vue';
+import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue';
import SidebarPortal from '~/super_sidebar/components/sidebar_portal.vue';
import { SCOPE_ISSUES, SCOPE_MERGE_REQUESTS, SCOPE_BLOB } from '../constants';
import ResultsFilters from './results_filters.vue';
@@ -11,13 +11,14 @@ export default {
name: 'GlobalSearchSidebar',
components: {
ResultsFilters,
- ScopeNavigation,
- ScopeNewNavigation,
+ ScopeLegacyNavigation,
+ ScopeSidebarNavigation,
LanguageFilter,
SidebarPortal,
},
computed: {
- ...mapState(['urlQuery', 'useNewNavigation']),
+ // useSidebarNavigation refers to whether the new left sidebar navigation is enabled
+ ...mapState(['useSidebarNavigation']),
...mapGetters(['currentScope']),
showIssueAndMergeFilters() {
return this.currentScope === SCOPE_ISSUES || this.currentScope === SCOPE_MERGE_REQUESTS;
@@ -25,7 +26,9 @@ export default {
showBlobFilter() {
return this.currentScope === SCOPE_BLOB;
},
- showOldNavigation() {
+ showScopeNavigation() {
+ // showLegacyNavigation refers to whether the scope navigation should be shown
+ // while the legacy navigation is being used and there are no search results the scope navigation has to be hidden
return Boolean(this.currentScope);
},
},
@@ -33,18 +36,18 @@ export default {
</script>
<template>
- <section v-if="useNewNavigation">
+ <section v-if="useSidebarNavigation">
<sidebar-portal>
- <scope-new-navigation />
+ <scope-sidebar-navigation />
<results-filters v-if="showIssueAndMergeFilters" />
<language-filter v-if="showBlobFilter" />
</sidebar-portal>
</section>
<section
- v-else
+ v-else-if="showScopeNavigation"
class="search-sidebar gl-display-flex gl-flex-direction-column gl-md-mr-5 gl-mb-6 gl-mt-5"
>
- <scope-navigation />
+ <scope-legacy-navigation />
<results-filters v-if="showIssueAndMergeFilters" />
<language-filter v-if="showBlobFilter" />
</section>
diff --git a/app/assets/javascripts/search/sidebar/components/scope_navigation.vue b/app/assets/javascripts/search/sidebar/components/scope_legacy_navigation.vue
index fc41baee831..e682369d60b 100644
--- a/app/assets/javascripts/search/sidebar/components/scope_navigation.vue
+++ b/app/assets/javascripts/search/sidebar/components/scope_legacy_navigation.vue
@@ -8,7 +8,7 @@ import { NAV_LINK_DEFAULT_CLASSES, NAV_LINK_COUNT_DEFAULT_CLASSES } from '../con
import { slugifyWithUnderscore } from '../../../lib/utils/text_utility';
export default {
- name: 'ScopeNavigation',
+ name: 'ScopeLegacyNavigation',
i18n: {
countOverLimitLabel: s__('GlobalSearch|Result count is over limit.'),
},
diff --git a/app/assets/javascripts/search/sidebar/components/scope_new_navigation.vue b/app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue
index 86b7cc577a6..3707e152e47 100644
--- a/app/assets/javascripts/search/sidebar/components/scope_new_navigation.vue
+++ b/app/assets/javascripts/search/sidebar/components/scope_sidebar_navigation.vue
@@ -6,7 +6,7 @@ import NavItem from '~/super_sidebar/components/nav_item.vue';
import { NAV_LINK_DEFAULT_CLASSES, NAV_LINK_COUNT_DEFAULT_CLASSES } from '../constants';
export default {
- name: 'ScopeNewNavigation',
+ name: 'ScopeSidebarNavigation',
i18n: {
countOverLimitLabel: s__('GlobalSearch|Result count is over limit.'),
},
diff --git a/app/assets/javascripts/search/store/index.js b/app/assets/javascripts/search/store/index.js
index 634f8f7a7fa..2478518c157 100644
--- a/app/assets/javascripts/search/store/index.js
+++ b/app/assets/javascripts/search/store/index.js
@@ -7,11 +7,11 @@ import createState from './state';
Vue.use(Vuex);
-export const getStoreConfig = ({ query, navigation, useNewNavigation }) => ({
+export const getStoreConfig = (storeInitValues) => ({
actions,
getters,
mutations,
- state: createState({ query, navigation, useNewNavigation }),
+ state: createState(storeInitValues),
});
const createStore = (config) => new Vuex.Store(getStoreConfig(config));
diff --git a/app/assets/javascripts/search/store/state.js b/app/assets/javascripts/search/store/state.js
index a62b6728819..c897d4108a8 100644
--- a/app/assets/javascripts/search/store/state.js
+++ b/app/assets/javascripts/search/store/state.js
@@ -1,7 +1,7 @@
import { cloneDeep } from 'lodash';
import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from './constants';
-const createState = ({ query, navigation, useNewNavigation }) => ({
+const createState = ({ query, navigation, useSidebarNavigation }) => ({
urlQuery: cloneDeep(query),
query,
groups: [],
@@ -14,7 +14,7 @@ const createState = ({ query, navigation, useNewNavigation }) => ({
},
sidebarDirty: false,
navigation,
- useNewNavigation,
+ useSidebarNavigation,
aggregations: {
error: false,
fetching: false,
diff --git a/app/graphql/types/ci/catalog/resource_type.rb b/app/graphql/types/ci/catalog/resource_type.rb
index 7958a0ba558..b90ae111a3d 100644
--- a/app/graphql/types/ci/catalog/resource_type.rb
+++ b/app/graphql/types/ci/catalog/resource_type.rb
@@ -37,6 +37,10 @@ module Types
description: 'Number of times the catalog resource has been forked.',
alpha: { milestone: '16.1' }
+ field :root_namespace, Types::NamespaceType, null: true,
+ description: 'Root namespace of the catalog resource.',
+ alpha: { milestone: '16.1' }
+
def web_path
::Gitlab::Routing.url_helpers.project_path(object.project)
end
@@ -44,6 +48,29 @@ module Types
def forks_count
BatchLoader::GraphQL.wrap(object.forks_count)
end
+
+ def root_namespace
+ BatchLoader::GraphQL.for(object.project_id).batch do |project_ids, loader|
+ projects = Project.id_in(project_ids)
+
+ # This preloader uses traversal_ids to obtain Group-type root namespaces.
+ # It also preloads each project's immediate parent namespace, which effectively
+ # preloads the User-type root namespaces since they cannot be nested (parent == root).
+ Preloaders::ProjectRootAncestorPreloader.new(projects, :group).execute
+ root_namespaces = projects.map(&:root_ancestor)
+
+ # NamespaceType requires the `:read_namespace` ability. We must preload the policy for
+ # Group-type namespaces to avoid N+1 queries caused by the authorization requests.
+ group_root_namespaces = root_namespaces.select { |n| n.type == ::Group.sti_name }
+ Preloaders::GroupPolicyPreloader.new(group_root_namespaces, current_user).execute
+
+ # For User-type namespaces, the authorization request requires preloading the owner objects.
+ user_root_namespaces = root_namespaces.select { |n| n.type == ::Namespaces::UserNamespace.sti_name }
+ ActiveRecord::Associations::Preloader.new(records: user_root_namespaces, associations: :owner).call
+
+ projects.each { |project| loader.call(project.id, project.root_ancestor) }
+ end
+ end
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/services/packages/ml_model/create_package_file_service.rb b/app/services/packages/ml_model/create_package_file_service.rb
new file mode 100644
index 00000000000..574f70940fc
--- /dev/null
+++ b/app/services/packages/ml_model/create_package_file_service.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Packages
+ module MlModel
+ class CreatePackageFileService < BaseService
+ def execute
+ ::Packages::Package.transaction do
+ create_package_file(find_or_create_package)
+ end
+ end
+
+ private
+
+ def find_or_create_package
+ package_params = {
+ name: params[:package_name],
+ version: params[:package_version],
+ build: params[:build],
+ status: params[:status]
+ }
+
+ package = ::Packages::MlModel::FindOrCreatePackageService
+ .new(project, current_user, package_params)
+ .execute
+
+ package.update_column(:status, params[:status]) if params[:status] && params[:status] != package.status
+
+ package.create_build_infos!(params[:build])
+
+ package
+ end
+
+ def create_package_file(package)
+ file_params = {
+ file: params[:file],
+ size: params[:file].size,
+ file_sha256: params[:file].sha256,
+ file_name: params[:file_name],
+ build: params[:build]
+ }
+
+ ::Packages::CreatePackageFileService.new(package, file_params).execute
+ end
+ end
+ end
+end
diff --git a/app/services/packages/ml_model/find_or_create_package_service.rb b/app/services/packages/ml_model/find_or_create_package_service.rb
new file mode 100644
index 00000000000..cab99e1b008
--- /dev/null
+++ b/app/services/packages/ml_model/find_or_create_package_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Packages
+ module MlModel
+ class FindOrCreatePackageService < ::Packages::CreatePackageService
+ def execute
+ find_or_create_package!(::Packages::Package.package_types['ml_model'])
+ end
+ end
+ end
+end
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index 5d693ac603d..a0f47f375f7 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -8,10 +8,10 @@
- hidden = @hidden_commit_count
- commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, daily_commits|
- %li.js-commit-header.gl-mt-7.gl-pb-2.gl-border-b{ data: { day: day } }
+ %li.js-commit-header.gl-py-2.gl-border-b{ data: { day: day } }
%span.day.font-weight-bold= l(day, format: '%b %d, %Y')
- %li.commits-row{ data: { day: day } }
+ %li.commits-row.gl-mb-6{ data: { day: day } }
%ul.content-list.commit-list.flex-list
- if Feature.enabled?(:cached_commits, project)
= render partial: 'projects/commits/commit', collection: daily_commits, locals: { project: project, ref: ref, merge_request: merge_request }, cached: ->(commit) { commit_partial_cache_key(commit, ref: ref, merge_request: merge_request, request: request) }
@@ -19,13 +19,13 @@
= render partial: 'projects/commits/commit', collection: daily_commits, locals: { project: project, ref: ref, merge_request: merge_request }
- if context_commits.present?
- %li.js-commit-header.gl-mt-7.gl-pb-2.gl-border-b
+ %li.js-commit-header.gl-py-2.gl-border-b
%span.font-weight-bold= n_("%d previously merged commit", "%d previously merged commits", context_commits.count) % context_commits.count
- if can_update_merge_request
= render Pajamas::ButtonComponent.new(button_options: { class: 'gl-ml-3 add-review-item-modal-trigger', data: { context_commits_empty: 'false' } }) do
= _('Add/remove')
- %li.commits-row
+ %li.commits-row.gl-mb-6
%ul.content-list.commit-list.flex-list
- if Feature.enabled?(:cached_commits, project)
= render partial: 'projects/commits/commit', collection: context_commits, locals: { project: project, ref: ref, merge_request: merge_request }, cached: ->(commit) { commit_partial_cache_key(commit, ref: ref, merge_request: merge_request, request: request) }
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index f3785078393..093d8aa624d 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -12455,6 +12455,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cicatalogresourceicon"></a>`icon` **{warning-solid}** | [`String`](#string) | **Introduced** in 15.11. This feature is an Experiment. It can be changed or removed at any time. Icon for the catalog resource. |
| <a id="cicatalogresourceid"></a>`id` **{warning-solid}** | [`ID!`](#id) | **Introduced** in 15.11. This feature is an Experiment. It can be changed or removed at any time. ID of the catalog resource. |
| <a id="cicatalogresourcename"></a>`name` **{warning-solid}** | [`String`](#string) | **Introduced** in 15.11. This feature is an Experiment. It can be changed or removed at any time. Name of the catalog resource. |
+| <a id="cicatalogresourcerootnamespace"></a>`rootNamespace` **{warning-solid}** | [`Namespace`](#namespace) | **Introduced** in 16.1. This feature is an Experiment. It can be changed or removed at any time. Root namespace of the catalog resource. |
| <a id="cicatalogresourcestarcount"></a>`starCount` **{warning-solid}** | [`Int!`](#int) | **Introduced** in 16.1. This feature is an Experiment. It can be changed or removed at any time. Number of times the catalog resource has been starred. |
| <a id="cicatalogresourcewebpath"></a>`webPath` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.1. This feature is an Experiment. It can be changed or removed at any time. Web path of the catalog resource. |
diff --git a/doc/development/pipelines/index.md b/doc/development/pipelines/index.md
index 651fa2d2ce9..610e68dd2fb 100644
--- a/doc/development/pipelines/index.md
+++ b/doc/development/pipelines/index.md
@@ -442,7 +442,7 @@ This [GitLab JH validation](https://gitlab.com/gitlab-org-sandbox/gitlab-jh-vali
project variables set.
It's a pull mirror pulling from [GitLab JH mirror](https://gitlab.com/gitlab-org/gitlab-jh-mirrors/gitlab),
-mirroring only protected branches, `master` and `main-jh`, overriding
+mirroring specific branches: `(master|main-jh)`, overriding
divergent refs, triggering no pipelines when mirror is updated.
The pulling user is [`@gitlab-jh-validation-bot`](https://gitlab.com/gitlab-jh-validation-bot), who is a maintainer in the project, and also a
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index 4bebe4c1a97..97c56b9158d 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -160,8 +160,10 @@ To purge files from a GitLab repository:
Refer to the Git [`replace`](https://git-scm.com/book/en/v2/Git-Tools-Replace) documentation for information on how this works.
-1. Wait at least 30 minutes, because the repository cleanup process only processes object older than 30 minutes.
-1. Run [repository cleanup](#repository-cleanup).
+1. Wait at least 30 minutes before attempting the next step.
+1. Run [repository cleanup](#repository-cleanup). This process only cleans up objects
+ that are more than 30 minutes old. See [Space not being freed](#space-not-being-freed)
+ for more information.
## Repository cleanup
@@ -300,3 +302,17 @@ end
puts "#{artifact_storage} bytes"
```
+
+### Space not being freed
+
+The process defined on this page can decrease the size of repository exports
+decreasing, but the usage in the file system appearing unchanged in both the Web UI and terminal.
+
+The process leaves many unreachable objects remaining in the repository.
+Because they are unreachable, they are not included in the export, but they are
+still stored in the file system. These files are pruned after a grace period of
+two weeks. Pruning deletes these files and ensures your storage usage statistics
+are accurate.
+
+To expedite this process, see the
+['Prune Unreachable Objects' housekeeping task](../../../administration/housekeeping.md).
diff --git a/glfm_specification/output_example_snapshots/html.yml b/glfm_specification/output_example_snapshots/html.yml
index c34ba47a004..d47d1d71b27 100644
--- a/glfm_specification/output_example_snapshots/html.yml
+++ b/glfm_specification/output_example_snapshots/html.yml
@@ -5494,7 +5494,7 @@
canonical: |
<p><strong>foo, <strong>bar</strong>, baz</strong></p>
static: |-
- <p data-sourcepos="1:1-1:21" dir="auto"><strong>foo, <strong>bar</strong>, baz</strong></p>
+ <p data-sourcepos="1:1-1:21" dir="auto"><strong>foo, bar, baz</strong></p>
wysiwyg: |-
<p><strong>foo, bar</strong>, baz</p>
06_05_00__inlines__emphasis_and_strong_emphasis__040:
@@ -5696,7 +5696,7 @@
canonical: |
<p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
static: |-
- <p data-sourcepos="1:1-1:24" dir="auto">foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
+ <p data-sourcepos="1:1-1:24" dir="auto">foo<strong>bar</strong>***baz</p>
wysiwyg: |-
<p>foo<strong>bar</strong>***baz</p>
06_05_00__inlines__emphasis_and_strong_emphasis__068:
@@ -5755,21 +5755,21 @@
canonical: |
<p><strong>foo <strong>bar</strong> baz</strong></p>
static: |-
- <p data-sourcepos="1:1-1:19" dir="auto"><strong>foo <strong>bar</strong> baz</strong></p>
+ <p data-sourcepos="1:1-1:19" dir="auto"><strong>foo bar baz</strong></p>
wysiwyg: |-
<p><strong>foo bar</strong> baz</p>
06_05_00__inlines__emphasis_and_strong_emphasis__076:
canonical: |
<p><strong><strong>foo</strong> bar</strong></p>
static: |-
- <p data-sourcepos="1:1-1:15" dir="auto"><strong><strong>foo</strong> bar</strong></p>
+ <p data-sourcepos="1:1-1:15" dir="auto"><strong>foo bar</strong></p>
wysiwyg: |-
<p><strong>foo</strong> bar</p>
06_05_00__inlines__emphasis_and_strong_emphasis__077:
canonical: |
<p><strong>foo <strong>bar</strong></strong></p>
static: |-
- <p data-sourcepos="1:1-1:15" dir="auto"><strong>foo <strong>bar</strong></strong></p>
+ <p data-sourcepos="1:1-1:15" dir="auto"><strong>foo bar</strong></p>
wysiwyg: |-
<p><strong>foo bar</strong></p>
06_05_00__inlines__emphasis_and_strong_emphasis__078:
@@ -6031,21 +6031,21 @@
canonical: |
<p><strong><strong>foo</strong></strong></p>
static: |-
- <p data-sourcepos="1:1-1:11" dir="auto"><strong><strong>foo</strong></strong></p>
+ <p data-sourcepos="1:1-1:11" dir="auto"><strong>foo</strong></p>
wysiwyg: |-
<p><strong>foo</strong></p>
06_05_00__inlines__emphasis_and_strong_emphasis__115:
canonical: |
<p><strong><strong>foo</strong></strong></p>
static: |-
- <p data-sourcepos="1:1-1:11" dir="auto"><strong><strong>foo</strong></strong></p>
+ <p data-sourcepos="1:1-1:11" dir="auto"><strong>foo</strong></p>
wysiwyg: |-
<p><strong>foo</strong></p>
06_05_00__inlines__emphasis_and_strong_emphasis__116:
canonical: |
<p><strong><strong><strong>foo</strong></strong></strong></p>
static: |-
- <p data-sourcepos="1:1-1:15" dir="auto"><strong><strong><strong>foo</strong></strong></strong></p>
+ <p data-sourcepos="1:1-1:15" dir="auto"><strong>foo</strong></p>
wysiwyg: |-
<p><strong>foo</strong></p>
06_05_00__inlines__emphasis_and_strong_emphasis__117:
@@ -6059,7 +6059,7 @@
canonical: |
<p><em><strong><strong>foo</strong></strong></em></p>
static: |-
- <p data-sourcepos="1:1-1:13" dir="auto"><em><strong><strong>foo</strong></strong></em></p>
+ <p data-sourcepos="1:1-1:13" dir="auto"><em><strong>foo</strong></em></p>
wysiwyg: |-
<p><strong><em>foo</em></strong></p>
06_05_00__inlines__emphasis_and_strong_emphasis__119:
@@ -7392,7 +7392,7 @@
canonical: |
<p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>
static: |-
- <p data-sourcepos="1:1-1:41" dir="auto">foo &lt;!-- not a comment -- two hyphens --&gt;</p>
+ <p data-sourcepos="1:1-1:41" dir="auto">foo <!-- not a comment -- two hyphens --></p>
wysiwyg: |-
<p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>
06_11_00__inlines__raw_html__015:
@@ -7400,7 +7400,7 @@
<p>foo &lt;!--&gt; foo --&gt;</p>
<p>foo &lt;!-- foo---&gt;</p>
static: |-
- <p data-sourcepos="1:1-1:17" dir="auto">foo &lt;!--&gt; foo --&gt;</p>
+ <p data-sourcepos="1:1-1:17" dir="auto">foo <!----> foo --&gt;</p>
<p data-sourcepos="3:1-3:16" dir="auto">foo &lt;!-- foo---&gt;</p>
wysiwyg: |-
<p>foo &lt;!--&gt; foo --&gt;</p>
@@ -8238,10 +8238,10 @@
<section data-footnotes class="footnotes">
<ol>
<li id="fn-1-42">
- <p data-sourcepos="5:7-5:41">This is the text inside a footnote. <a href="#fnref-1-42" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p data-sourcepos="5:7-5:41">This is the text inside a footnote. <a href="#fnref-1-42" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
<li id="fn-footnote-42">
- <p data-sourcepos="7:14-7:38">This is another footnote. <a href="#fnref-footnote-42" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p data-sourcepos="7:14-7:38">This is another footnote. <a href="#fnref-footnote-42" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
</ol>
</section>
@@ -8643,7 +8643,7 @@
<section data-footnotes class="footnotes">
<ol>
<li id="fn-fortytwo-42">
- <p data-sourcepos="3:14-3:26">footnote text <a href="#fnref-fortytwo-42" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p data-sourcepos="3:14-3:26">footnote text <a href="#fnref-fortytwo-42" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
</ol>
</section>
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index b119c2ffccf..c2cad237d6f 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -34,7 +34,7 @@ module Banzai
# Allow section elements with data-footnotes attribute
allowlist[:elements].push('section')
allowlist[:attributes]['section'] = %w(data-footnotes)
- allowlist[:attributes]['a'].push('data-footnote-ref', 'data-footnote-backref')
+ allowlist[:attributes]['a'].push('data-footnote-ref', 'data-footnote-backref', 'data-footnote-backref-idx')
allowlist
end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 83dc8c5dcf8..846bb934a3d 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -42,11 +42,14 @@ module Gitlab
clear_memoized
with_finished_at(:recording_ce_finished_at) do
- { recorded_at: recorded_at }
- .merge(usage_data_metrics)
+ usage_data_metrics
end
end
+ def license_usage_data
+ { recorded_at: recorded_at }
+ end
+
def recorded_at
@recorded_at ||= Time.current
end
@@ -549,7 +552,8 @@ module Gitlab
end
def usage_data_metrics
- system_usage_data_license
+ license_usage_data
+ .merge(system_usage_data_license)
.merge(system_usage_data_settings)
.merge(system_usage_data)
.merge(system_usage_data_monthly)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 40516f87ad7..8ec3ee9bfe7 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5196,6 +5196,9 @@ msgstr ""
msgid "Analytics|Browser Family"
msgstr ""
+msgid "Analytics|By GitLab"
+msgstr ""
+
msgid "Analytics|Cancel"
msgstr ""
@@ -16443,9 +16446,6 @@ msgstr ""
msgid "Edit Release"
msgstr ""
-msgid "Edit Requirement"
-msgstr ""
-
msgid "Edit Slack integration"
msgstr ""
@@ -36887,6 +36887,9 @@ msgstr ""
msgid "ProtectedEnvironments|Number of approvals must be between 1 and 5"
msgstr ""
+msgid "ProtectedEnvironments|Remove approval rule"
+msgstr ""
+
msgid "ProtectedEnvironments|Required approval count"
msgstr ""
diff --git a/qa/qa/page/search/results.rb b/qa/qa/page/search/results.rb
index 769f8accfca..a04fd9092d1 100644
--- a/qa/qa/page/search/results.rb
+++ b/qa/qa/page/search/results.rb
@@ -4,7 +4,7 @@ module QA
module Page
module Search
class Results < QA::Page::Base
- view 'app/assets/javascripts/search/sidebar/components/scope_navigation.vue' do
+ view 'app/assets/javascripts/search/sidebar/components/scope_legacy_navigation.vue' do
element :code_tab, ':data-qa-selector="qaSelectorValue(item)"' # rubocop:disable QA/ElementWithPattern
element :projects_tab, ':data-qa-selector="qaSelectorValue(item)"' # rubocop:disable QA/ElementWithPattern
end
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index 537424093fb..a721722a5c3 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set
end
end
- describe 'GET #usage_data', :with_license, feature_category: :service_ping do
+ describe 'GET #usage_data', feature_category: :service_ping do
before do
stub_usage_data_connections
stub_database_flavor_check
diff --git a/spec/controllers/admin/instance_review_controller_spec.rb b/spec/controllers/admin/instance_review_controller_spec.rb
index b69d22ba1e3..f0225a71e00 100644
--- a/spec/controllers/admin/instance_review_controller_spec.rb
+++ b/spec/controllers/admin/instance_review_controller_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Admin::InstanceReviewController, feature_category: :service_ping
subject { post :index }
- context 'with usage ping enabled', :with_license do
+ context 'with usage ping enabled' do
before do
stub_application_setting(usage_ping_enabled: true)
stub_usage_data_connections
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index d3b43029f2a..1f43caf37e7 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -977,7 +977,7 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do
end
end
- context 'Service usage data page', :with_license do
+ context 'Service usage data page' do
before do
stub_usage_data_connections
stub_database_flavor_check
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index c68ae443231..3d108951c64 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -502,13 +502,13 @@ RSpec.describe ProjectsFinder do
end
end
- describe 'without CTE flag enabled' do
+ describe 'without CTE flag enabled', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/408387' do
let(:use_cte) { false }
it_behaves_like 'ProjectFinder#execute examples'
end
- describe 'with CTE flag enabled' do
+ describe 'with CTE flag enabled', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/408387' do
let(:use_cte) { true }
it_behaves_like 'ProjectFinder#execute examples'
diff --git a/spec/frontend/projects/settings/components/new_access_dropdown_spec.js b/spec/frontend/projects/settings/components/new_access_dropdown_spec.js
index f3e536de703..ce696ee321b 100644
--- a/spec/frontend/projects/settings/components/new_access_dropdown_spec.js
+++ b/spec/frontend/projects/settings/components/new_access_dropdown_spec.js
@@ -99,6 +99,9 @@ describe('Access Level Dropdown', () => {
const findDropdownItemWithText = (items, text) =>
items.filter((item) => item.text().includes(text)).at(0);
+ const findSelected = (type) =>
+ wrapper.findAllByTestId(`${type}-dropdown-item`).filter((w) => w.props('isChecked'));
+
describe('data request', () => {
it('should make an api call for users, groups && deployKeys when user has a license', () => {
createComponent();
@@ -305,9 +308,6 @@ describe('Access Level Dropdown', () => {
{ id: 122, type: 'deploy_key', deploy_key_id: 12 },
];
- const findSelected = (type) =>
- wrapper.findAllByTestId(`${type}-dropdown-item`).filter((w) => w.props('isChecked'));
-
beforeEach(async () => {
createComponent({ preselectedItems });
await waitForPromises();
@@ -339,6 +339,34 @@ describe('Access Level Dropdown', () => {
});
});
+ describe('handling two-way data binding', () => {
+ it('emits a formatted update on selection', async () => {
+ createComponent();
+ await waitForPromises();
+ const dropdownItems = findAllDropdownItems();
+ // select new item from each group
+ findDropdownItemWithText(dropdownItems, 'role1').trigger('click');
+ findDropdownItemWithText(dropdownItems, 'group4').trigger('click');
+ findDropdownItemWithText(dropdownItems, 'user7').trigger('click');
+ findDropdownItemWithText(dropdownItems, 'key10').trigger('click');
+
+ await wrapper.setProps({ items: [{ user_id: 7 }] });
+
+ const selectedUsers = findSelected(LEVEL_TYPES.USER);
+ expect(selectedUsers).toHaveLength(1);
+ expect(selectedUsers.at(0).text()).toBe('user7');
+
+ const selectedRoles = findSelected(LEVEL_TYPES.ROLE);
+ expect(selectedRoles).toHaveLength(0);
+
+ const selectedGroups = findSelected(LEVEL_TYPES.GROUP);
+ expect(selectedGroups).toHaveLength(0);
+
+ const selectedDeployKeys = findSelected(LEVEL_TYPES.DEPLOY_KEY);
+ expect(selectedDeployKeys).toHaveLength(0);
+ });
+ });
+
describe('on dropdown open', () => {
beforeEach(() => {
createComponent();
diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js
index 963b73aeae5..4bdb034d4bb 100644
--- a/spec/frontend/search/sidebar/components/app_spec.js
+++ b/spec/frontend/search/sidebar/components/app_spec.js
@@ -4,7 +4,8 @@ import Vuex from 'vuex';
import { MOCK_QUERY } from 'jest/search/mock_data';
import GlobalSearchSidebar from '~/search/sidebar/components/app.vue';
import ResultsFilters from '~/search/sidebar/components/results_filters.vue';
-import ScopeNavigation from '~/search/sidebar/components/scope_navigation.vue';
+import ScopeLegacyNavigation from '~/search/sidebar/components/scope_legacy_navigation.vue';
+import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue';
import LanguageFilter from '~/search/sidebar/components/language_filter/index.vue';
Vue.use(Vuex);
@@ -12,22 +13,16 @@ Vue.use(Vuex);
describe('GlobalSearchSidebar', () => {
let wrapper;
- const actionSpies = {
- applyQuery: jest.fn(),
- resetQuery: jest.fn(),
- };
-
const getterSpies = {
currentScope: jest.fn(() => 'issues'),
};
- const createComponent = (initialState, featureFlags) => {
+ const createComponent = (initialState = {}, featureFlags = {}) => {
const store = new Vuex.Store({
state: {
urlQuery: MOCK_QUERY,
...initialState,
},
- actions: actionSpies,
getters: getterSpies,
});
@@ -43,13 +38,14 @@ describe('GlobalSearchSidebar', () => {
const findSidebarSection = () => wrapper.find('section');
const findFilters = () => wrapper.findComponent(ResultsFilters);
- const findSidebarNavigation = () => wrapper.findComponent(ScopeNavigation);
+ const findScopeLegacyNavigation = () => wrapper.findComponent(ScopeLegacyNavigation);
+ const findScopeSidebarNavigation = () => wrapper.findComponent(ScopeSidebarNavigation);
const findLanguageAggregation = () => wrapper.findComponent(LanguageFilter);
describe('renders properly', () => {
describe('always', () => {
beforeEach(() => {
- createComponent({});
+ createComponent();
});
it(`shows section`, () => {
expect(findSidebarSection().exists()).toBe(true);
@@ -77,12 +73,24 @@ describe('GlobalSearchSidebar', () => {
});
});
- describe('renders navigation', () => {
+ describe.each`
+ currentScope | sidebarNavShown | legacyNavShown
+ ${'issues'} | ${false} | ${true}
+ ${''} | ${false} | ${false}
+ ${'issues'} | ${true} | ${false}
+ ${''} | ${true} | ${false}
+ `('renders navigation', ({ currentScope, sidebarNavShown, legacyNavShown }) => {
beforeEach(() => {
- createComponent({});
+ getterSpies.currentScope = jest.fn(() => currentScope);
+ createComponent({ useSidebarNavigation: sidebarNavShown });
});
- it('shows the vertical navigation', () => {
- expect(findSidebarNavigation().exists()).toBe(true);
+
+ it(`${!legacyNavShown ? 'hides' : 'shows'} the legacy navigation`, () => {
+ expect(findScopeLegacyNavigation().exists()).toBe(legacyNavShown);
+ });
+
+ it(`${!sidebarNavShown ? 'hides' : 'shows'} the sidebar navigation`, () => {
+ expect(findScopeSidebarNavigation().exists()).toBe(sidebarNavShown);
});
});
});
diff --git a/spec/frontend/search/sidebar/components/scope_navigation_spec.js b/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js
index e8737384f27..6a94da31a1b 100644
--- a/spec/frontend/search/sidebar/components/scope_navigation_spec.js
+++ b/spec/frontend/search/sidebar/components/scope_legacy_navigation_spec.js
@@ -3,11 +3,11 @@ import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { MOCK_QUERY, MOCK_NAVIGATION } from 'jest/search/mock_data';
-import ScopeNavigation from '~/search/sidebar/components/scope_navigation.vue';
+import ScopeLegacyNavigation from '~/search/sidebar/components/scope_legacy_navigation.vue';
Vue.use(Vuex);
-describe('ScopeNavigation', () => {
+describe('ScopeLegacyNavigation', () => {
let wrapper;
const actionSpies = {
@@ -29,7 +29,7 @@ describe('ScopeNavigation', () => {
getters: getterSpies,
});
- wrapper = shallowMount(ScopeNavigation, {
+ wrapper = shallowMount(ScopeLegacyNavigation, {
store,
});
};
diff --git a/spec/frontend/search/sidebar/components/scope_new_navigation_spec.js b/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js
index 5207665f883..f31a7c8fa5d 100644
--- a/spec/frontend/search/sidebar/components/scope_new_navigation_spec.js
+++ b/spec/frontend/search/sidebar/components/scope_sidebar_navigation_spec.js
@@ -1,13 +1,13 @@
import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
-import ScopeNewNavigation from '~/search/sidebar/components/scope_new_navigation.vue';
+import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue';
import NavItem from '~/super_sidebar/components/nav_item.vue';
import { MOCK_QUERY, MOCK_NAVIGATION, MOCK_NAVIGATION_ITEMS } from '../../mock_data';
Vue.use(Vuex);
-describe('ScopeNewNavigation', () => {
+describe('ScopeSidebarNavigation', () => {
let wrapper;
const actionSpies = {
@@ -30,7 +30,7 @@ describe('ScopeNewNavigation', () => {
getters: getterSpies,
});
- wrapper = mount(ScopeNewNavigation, {
+ wrapper = mount(ScopeSidebarNavigation, {
store,
stubs: {
NavItem,
diff --git a/spec/graphql/types/ci/catalog/resource_type_spec.rb b/spec/graphql/types/ci/catalog/resource_type_spec.rb
index cdc863e0d90..d1f8adcd4fb 100644
--- a/spec/graphql/types/ci/catalog/resource_type_spec.rb
+++ b/spec/graphql/types/ci/catalog/resource_type_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe Types::Ci::Catalog::ResourceType, feature_category: :pipeline_com
versions
star_count
forks_count
+ root_namespace
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb
index 4b765191449..5dd5074801f 100644
--- a/spec/lib/banzai/filter/footnote_filter_spec.rb
+++ b/spec/lib/banzai/filter/footnote_filter_spec.rb
@@ -18,12 +18,12 @@ RSpec.describe Banzai::Filter::FootnoteFilter, feature_category: :team_planning
<section data-footnotes>
<ol>
<li id="fn-1">
- <p>one <a href="#fnref-1" aria-label="Back to content" data-footnote-backref>↩</a></p>
+ <p>one <a href="#fnref-1" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-second">
- <p>two <a href="#fnref-second" aria-label="Back to content" data-footnote-backref>↩</a></p>
+ <p>two <a href="#fnref-second" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2">↩</a></p>
</li>\n<li id="fn-_%F0%9F%98%84_">
- <p>three <a href="#fnref-_%F0%9F%98%84_" aria-label="Back to content" data-footnote-backref>↩</a></p>
+ <p>three <a href="#fnref-_%F0%9F%98%84_" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3">↩</a></p>
</li>
</ol>
EOF
@@ -35,13 +35,13 @@ RSpec.describe Banzai::Filter::FootnoteFilter, feature_category: :team_planning
<section data-footnotes class=\"footnotes\">
<ol>
<li id="fn-1-#{identifier}">
- <p>one <a href="#fnref-1-#{identifier}" aria-label="Back to content" data-footnote-backref class="footnote-backref">↩</a></p>
+ <p>one <a href="#fnref-1-#{identifier}" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1" class="footnote-backref">↩</a></p>
</li>
<li id="fn-second-#{identifier}">
- <p>two <a href="#fnref-second-#{identifier}" aria-label="Back to content" data-footnote-backref class="footnote-backref">↩</a></p>
+ <p>two <a href="#fnref-second-#{identifier}" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2" class="footnote-backref">↩</a></p>
</li>
<li id="fn-_%F0%9F%98%84_-#{identifier}">
- <p>three <a href="#fnref-_%F0%9F%98%84_-#{identifier}" aria-label="Back to content" data-footnote-backref class="footnote-backref">↩</a></p>
+ <p>three <a href="#fnref-_%F0%9F%98%84_-#{identifier}" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index 51832e60754..bad09732e00 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -144,6 +144,18 @@ RSpec.describe Banzai::Filter::SanitizationFilter, feature_category: :team_plann
end
describe 'footnotes' do
+ it 'allows the footnote attributes' do
+ exp = <<~HTML
+ <section data-footnotes>
+ <a href="#fn-first" id="fnref-first" data-footnote-ref data-footnote-backref data-footnote-backref-idx>foo/bar.md</a>
+ </section>
+ HTML
+
+ act = filter(exp)
+
+ expect(act.to_html).to eq exp
+ end
+
it 'allows correct footnote id property on links' do
exp = %q(<a href="#fn-first" id="fnref-first">foo/bar.md</a>)
act = filter(exp)
diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
index ca05a353d47..6654eec7241 100644
--- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
@@ -49,13 +49,13 @@ RSpec.describe Banzai::Pipeline::FullPipeline, feature_category: :team_planning
<section data-footnotes class="footnotes">
<ol>
<li id="fn-1-#{identifier}">
- <p>one <a href="#fnref-1-#{identifier}" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p>one <a href="#fnref-1-#{identifier}" data-footnote-backref data-footnote-backref-idx="1" aria-label="Back to reference 1" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
<li id="fn-%F0%9F%98%84second-#{identifier}">
- <p>two <a href="#fnref-%F0%9F%98%84second-#{identifier}" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p>two <a href="#fnref-%F0%9F%98%84second-#{identifier}" data-footnote-backref data-footnote-backref-idx="2" aria-label="Back to reference 2" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
<li id="fn-_twenty-#{identifier}">
- <p>twenty <a href="#fnref-_twenty-#{identifier}" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p>twenty <a href="#fnref-_twenty-#{identifier}" data-footnote-backref data-footnote-backref-idx="3" aria-label="Back to reference 3" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
</ol>
</section>
diff --git a/spec/lib/gitlab/checks/force_push_spec.rb b/spec/lib/gitlab/checks/force_push_spec.rb
index 49e02fe5cec..8cdee727d3d 100644
--- a/spec/lib/gitlab/checks/force_push_spec.rb
+++ b/spec/lib/gitlab/checks/force_push_spec.rb
@@ -6,14 +6,34 @@ RSpec.describe Gitlab::Checks::ForcePush do
let_it_be(:project) { create(:project, :repository) }
describe '.force_push?' do
- it 'returns false if the repo is empty' do
- allow(project).to receive(:empty_repo?).and_return(true)
+ let(:old_rev) { 'HEAD~' }
+ let(:new_rev) { 'HEAD' }
- expect(described_class.force_push?(project, 'HEAD', 'HEAD~')).to be(false)
+ subject(:force_push) { described_class.force_push?(project, old_rev, new_rev) }
+
+ context 'when the repo is empty' do
+ before do
+ allow(project).to receive(:empty_repo?).and_return(true)
+ end
+
+ it 'returns false' do
+ expect(force_push).to be(false)
+ end
end
- it 'checks if old rev is an anchestor' do
- expect(described_class.force_push?(project, 'HEAD', 'HEAD~')).to be(true)
+ context 'when new rev is a descendant of old rev' do
+ it 'returns false' do
+ expect(force_push).to be(false)
+ end
+ end
+
+ context 'when new rev is not a descendant of old rev' do
+ let(:old_rev) { 'HEAD' }
+ let(:new_rev) { 'HEAD~' }
+
+ it 'returns true' do
+ expect(force_push).to be(true)
+ end
end
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 4da5f899ea9..4544cb2eb26 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -661,6 +661,14 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures, feature_category: :servic
end
end
+ describe '.license_usage_data' do
+ subject { described_class.license_usage_data }
+
+ it 'gathers license data' do
+ expect(subject[:recorded_at]).to be_a(Time)
+ end
+ end
+
context 'when not relying on database records' do
describe '.features_usage_data_ce' do
subject { described_class.features_usage_data_ce }
diff --git a/spec/requests/api/usage_data_non_sql_metrics_spec.rb b/spec/requests/api/usage_data_non_sql_metrics_spec.rb
index 4ca6c5cace3..b2929caf676 100644
--- a/spec/requests/api/usage_data_non_sql_metrics_spec.rb
+++ b/spec/requests/api/usage_data_non_sql_metrics_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe API::UsageDataNonSqlMetrics, :aggregate_failures, feature_categor
stub_usage_data_connections
end
- describe 'GET /usage_data/non_sql_metrics', :with_license do
+ describe 'GET /usage_data/non_sql_metrics' do
let(:endpoint) { '/usage_data/non_sql_metrics' }
context 'with authentication' do
diff --git a/spec/requests/api/usage_data_queries_spec.rb b/spec/requests/api/usage_data_queries_spec.rb
index 584b0f31a07..ab3c38adb81 100644
--- a/spec/requests/api/usage_data_queries_spec.rb
+++ b/spec/requests/api/usage_data_queries_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe API::UsageDataQueries, :aggregate_failures, feature_category: :se
stub_database_flavor_check
end
- describe 'GET /usage_data/usage_data_queries', :with_license do
+ describe 'GET /usage_data/usage_data_queries' do
let(:endpoint) { '/usage_data/queries' }
context 'with authentication' do
diff --git a/spec/services/packages/ml_model/create_package_file_service_spec.rb b/spec/services/packages/ml_model/create_package_file_service_spec.rb
new file mode 100644
index 00000000000..d749aee227a
--- /dev/null
+++ b/spec/services/packages/ml_model/create_package_file_service_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::MlModel::CreatePackageFileService, feature_category: :mlops do
+ describe '#execute' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pipeline) { create(:ci_pipeline, user: user, project: project) }
+ let_it_be(:file_name) { 'myfile.tar.gz.1' }
+
+ let(:build) { instance_double(Ci::Build, pipeline: pipeline) }
+
+ let(:sha256) { '440e5e148a25331bbd7991575f7d54933c0ebf6cc735a18ee5066ac1381bb590' }
+ let(:temp_file) { Tempfile.new("test") }
+ let(:file) { UploadedFile.new(temp_file.path, sha256: sha256) }
+ let(:package_service) { double }
+
+ subject(:execute_service) { described_class.new(project, user, params).execute }
+
+ before do
+ FileUtils.touch(temp_file)
+ end
+
+ after do
+ FileUtils.rm_f(temp_file)
+ end
+
+ context 'without existing package' do
+ let(:params) do
+ {
+ package_name: 'new_model',
+ package_version: '1.0.0',
+ file: file,
+ file_name: file_name
+ }
+ end
+
+ it 'creates package file', :aggregate_failures do
+ expect { execute_service }
+ .to change { project.packages.ml_model.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ .and change { Packages::PackageFileBuildInfo.count }.by(0)
+
+ new_model = project.packages.ml_model.last
+ package_file = new_model.package_files.last
+
+ aggregate_failures do
+ expect(new_model.name).to eq('new_model')
+ expect(new_model.version).to eq('1.0.0')
+ expect(new_model.status).to eq('default')
+ expect(package_file.package).to eq(new_model)
+ expect(package_file.file_name).to eq(file_name)
+ expect(package_file.size).to eq(file.size)
+ expect(package_file.file_sha256).to eq(sha256)
+ end
+ end
+ end
+
+ context 'with existing package' do
+ let_it_be(:model) { create(:ml_model_package, creator: user, project: project, version: '0.1.0') }
+
+ let(:params) do
+ {
+ package_name: model.name,
+ package_version: model.version,
+ file: file,
+ file_name: file_name,
+ status: :hidden,
+ build: build
+ }
+ end
+
+ it 'adds the package file and updates status and ci_build', :aggregate_failures do
+ expect { execute_service }
+ .to change { project.packages.ml_model.count }.by(0)
+ .and change { model.package_files.count }.by(1)
+ .and change { Packages::PackageFileBuildInfo.count }.by(1)
+
+ model.reload
+
+ package_file = model.package_files.last
+
+ expect(model.build_infos.first.pipeline).to eq(build.pipeline)
+ expect(model.status).to eq('hidden')
+
+ expect(package_file.package).to eq(model)
+ expect(package_file.file_name).to eq(file_name)
+ expect(package_file.size).to eq(file.size)
+ expect(package_file.file_sha256).to eq(sha256)
+ end
+ end
+ end
+end
diff --git a/spec/services/packages/ml_model/find_or_create_package_service_spec.rb b/spec/services/packages/ml_model/find_or_create_package_service_spec.rb
new file mode 100644
index 00000000000..6e1e17da0e6
--- /dev/null
+++ b/spec/services/packages/ml_model/find_or_create_package_service_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Packages::MlModel::FindOrCreatePackageService, feature_category: :mlops do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.creator }
+ let_it_be(:ci_build) { create(:ci_build, :running, user: user, project: project) }
+
+ let(:base_params) do
+ {
+ name: 'mymodel',
+ version: '0.0.1'
+ }
+ end
+
+ let(:params) { base_params }
+
+ describe '#execute' do
+ subject(:execute_service) { described_class.new(project, user, params).execute }
+
+ context 'when model does not exist' do
+ it 'creates the model' do
+ expect { subject }.to change { project.packages.ml_model.count }.by(1)
+
+ package = project.packages.ml_model.last
+
+ aggregate_failures do
+ expect(package.creator).to eq(user)
+ expect(package.package_type).to eq('ml_model')
+ expect(package.name).to eq('mymodel')
+ expect(package.version).to eq('0.0.1')
+ expect(package.build_infos.count).to eq(0)
+ end
+ end
+
+ context 'when build is provided' do
+ let(:params) { base_params.merge(build: ci_build) }
+
+ it 'creates package and package build info' do
+ expect { subject }.to change { project.packages.ml_model.count }.by(1)
+
+ package = project.packages.ml_model.last
+
+ aggregate_failures do
+ expect(package.creator).to eq(user)
+ expect(package.package_type).to eq('ml_model')
+ expect(package.name).to eq('mymodel')
+ expect(package.version).to eq('0.0.1')
+ expect(package.build_infos.first.pipeline).to eq(ci_build.pipeline)
+ end
+ end
+ end
+ end
+
+ context 'when model already exists' do
+ it 'does not create a new model', :aggregate_failures do
+ model = project.packages.ml_model.create!(params)
+
+ expect do
+ new_model = subject
+ expect(new_model).to eq(model)
+ end.not_to change { project.packages.ml_model.count }
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/search_helpers.rb b/spec/support/helpers/search_helpers.rb
index 75853371c0f..30ffe3d6228 100644
--- a/spec/support/helpers/search_helpers.rb
+++ b/spec/support/helpers/search_helpers.rb
@@ -35,6 +35,8 @@ module SearchHelpers
end
def has_search_scope?(scope)
+ return false unless page.has_selector?('[data-testid="search-filter"]')
+
page.within '[data-testid="search-filter"]' do
has_link?(scope)
end
diff --git a/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb b/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
index b34d95519a2..cd792ccc4e3 100644
--- a/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
+++ b/spec/support/shared_contexts/services/service_ping/stubbed_service_ping_metrics_definitions_shared_context.rb
@@ -3,8 +3,9 @@
RSpec.shared_context 'stubbed service ping metrics definitions' do
include UsageDataHelpers
- let(:metrics_definitions) { standard_metrics + operational_metrics + optional_metrics }
+ let(:metrics_definitions) { standard_metrics + subscription_metrics + operational_metrics + optional_metrics }
# ToDo: remove during https://gitlab.com/gitlab-org/gitlab/-/issues/396824 (license metrics migration)
+ let(:subscription_metrics) { [] }
let(:standard_metrics) do
[
metric_attributes('recorded_at', 'standard'),
diff --git a/spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb b/spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb
index fd3c53f3675..8dcff99fb6f 100644
--- a/spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb
+++ b/spec/support/shared_examples/services/service_ping/complete_service_ping_payload_shared_examples.rb
@@ -3,7 +3,7 @@
RSpec.shared_examples 'complete service ping payload' do
it_behaves_like 'service ping payload with all expected metrics' do
let(:expected_metrics) do
- standard_metrics + operational_metrics + optional_metrics
+ standard_metrics + subscription_metrics + operational_metrics + optional_metrics
end
end
end
diff --git a/spec/tasks/gitlab/usage_data_rake_spec.rb b/spec/tasks/gitlab/usage_data_rake_spec.rb
index 11aab1b1b42..72f284b0b7f 100644
--- a/spec/tasks/gitlab/usage_data_rake_spec.rb
+++ b/spec/tasks/gitlab/usage_data_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gitlab:usage data take tasks', :silence_stdout, :with_license, feature_category: :service_ping do
+RSpec.describe 'gitlab:usage data take tasks', :silence_stdout, feature_category: :service_ping do
include StubRequests
include UsageDataHelpers