Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
013d339e9a
commit
8212b8fd70
|
|
@ -587,11 +587,13 @@ lib/gitlab/checks/**
|
||||||
/doc/administration/package_information/ @axil
|
/doc/administration/package_information/ @axil
|
||||||
/doc/administration/packages/ @marcel.amirault
|
/doc/administration/packages/ @marcel.amirault
|
||||||
/doc/administration/packages/index.md @phillipwells
|
/doc/administration/packages/index.md @phillipwells
|
||||||
|
/doc/administration/pages/ @msedlakjakubowski
|
||||||
/doc/administration/polling.md @axil
|
/doc/administration/polling.md @axil
|
||||||
/doc/administration/postgresql/ @lciutacu
|
/doc/administration/postgresql/ @lciutacu
|
||||||
/doc/administration/raketasks/ @axil
|
/doc/administration/raketasks/ @axil
|
||||||
/doc/administration/raketasks/ldap.md @jglassman1
|
/doc/administration/raketasks/ldap.md @jglassman1
|
||||||
/doc/administration/raketasks/praefect.md @eread
|
/doc/administration/raketasks/praefect.md @eread
|
||||||
|
/doc/administration/raketasks/tokens/ @jglassman1
|
||||||
/doc/administration/read_only_gitlab.md @axil
|
/doc/administration/read_only_gitlab.md @axil
|
||||||
/doc/administration/redis/ @axil
|
/doc/administration/redis/ @axil
|
||||||
/doc/administration/reference_architectures/ @axil
|
/doc/administration/reference_architectures/ @axil
|
||||||
|
|
@ -646,6 +648,7 @@ lib/gitlab/checks/**
|
||||||
/doc/administration/troubleshooting/ @axil
|
/doc/administration/troubleshooting/ @axil
|
||||||
/doc/administration/uploads.md @axil
|
/doc/administration/uploads.md @axil
|
||||||
/doc/administration/user_settings.md @jglassman1
|
/doc/administration/user_settings.md @jglassman1
|
||||||
|
/doc/administration/wikis/ @msedlakjakubowski
|
||||||
/doc/api/access_requests.md @jglassman1
|
/doc/api/access_requests.md @jglassman1
|
||||||
/doc/api/admin_sidekiq_queues.md @axil
|
/doc/api/admin_sidekiq_queues.md @axil
|
||||||
/doc/api/api_resources.md @eread
|
/doc/api/api_resources.md @eread
|
||||||
|
|
@ -706,6 +709,7 @@ lib/gitlab/checks/**
|
||||||
/doc/api/group_releases.md @phillipwells
|
/doc/api/group_releases.md @phillipwells
|
||||||
/doc/api/group_repository_storage_moves.md @ashrafkhamis
|
/doc/api/group_repository_storage_moves.md @ashrafkhamis
|
||||||
/doc/api/group_ssh_certificates.md @msedlakjakubowski
|
/doc/api/group_ssh_certificates.md @msedlakjakubowski
|
||||||
|
/doc/api/group_wikis.md @msedlakjakubowski
|
||||||
/doc/api/groups.md @lciutacu
|
/doc/api/groups.md @lciutacu
|
||||||
/doc/api/import.md @eread
|
/doc/api/import.md @eread
|
||||||
/doc/api/index.md @eread
|
/doc/api/index.md @eread
|
||||||
|
|
@ -738,6 +742,8 @@ lib/gitlab/checks/**
|
||||||
/doc/api/openapi/ @eread
|
/doc/api/openapi/ @eread
|
||||||
/doc/api/packages.md @phillipwells
|
/doc/api/packages.md @phillipwells
|
||||||
/doc/api/packages/ @phillipwells
|
/doc/api/packages/ @phillipwells
|
||||||
|
/doc/api/pages.md @msedlakjakubowski
|
||||||
|
/doc/api/pages_domains.md @msedlakjakubowski
|
||||||
/doc/api/personal_access_tokens.md @jglassman1
|
/doc/api/personal_access_tokens.md @jglassman1
|
||||||
/doc/api/pipeline_schedules.md @marcel.amirault @lyspin
|
/doc/api/pipeline_schedules.md @marcel.amirault @lyspin
|
||||||
/doc/api/pipeline_triggers.md @marcel.amirault @lyspin
|
/doc/api/pipeline_triggers.md @marcel.amirault @lyspin
|
||||||
|
|
@ -800,6 +806,7 @@ lib/gitlab/checks/**
|
||||||
/doc/api/vulnerabilities.md @rdickenson
|
/doc/api/vulnerabilities.md @rdickenson
|
||||||
/doc/api/vulnerability_exports.md @rdickenson
|
/doc/api/vulnerability_exports.md @rdickenson
|
||||||
/doc/api/vulnerability_findings.md @rdickenson
|
/doc/api/vulnerability_findings.md @rdickenson
|
||||||
|
/doc/api/wikis.md @msedlakjakubowski
|
||||||
/doc/ci/ @marcel.amirault @lyspin
|
/doc/ci/ @marcel.amirault @lyspin
|
||||||
/doc/ci/chatops/ @phillipwells
|
/doc/ci/chatops/ @phillipwells
|
||||||
/doc/ci/cloud_deployment/ @phillipwells
|
/doc/ci/cloud_deployment/ @phillipwells
|
||||||
|
|
@ -899,6 +906,7 @@ lib/gitlab/checks/**
|
||||||
/doc/tutorials/dependency_scanning.md @rdickenson @phillipwells
|
/doc/tutorials/dependency_scanning.md @rdickenson @phillipwells
|
||||||
/doc/tutorials/export_sbom.md @rdickenson @phillipwells
|
/doc/tutorials/export_sbom.md @rdickenson @phillipwells
|
||||||
/doc/tutorials/fuzz_testing/ @rdickenson @phillipwells
|
/doc/tutorials/fuzz_testing/ @rdickenson @phillipwells
|
||||||
|
/doc/tutorials/hugo/ @msedlakjakubowski
|
||||||
/doc/tutorials/idea_management/ @msedlakjakubowski
|
/doc/tutorials/idea_management/ @msedlakjakubowski
|
||||||
/doc/tutorials/install_gitlab_single_node/ @axil
|
/doc/tutorials/install_gitlab_single_node/ @axil
|
||||||
/doc/tutorials/issue_triage/ @msedlakjakubowski
|
/doc/tutorials/issue_triage/ @msedlakjakubowski
|
||||||
|
|
@ -914,6 +922,7 @@ lib/gitlab/checks/**
|
||||||
/doc/tutorials/update_commit_messages/ @msedlakjakubowski
|
/doc/tutorials/update_commit_messages/ @msedlakjakubowski
|
||||||
/doc/tutorials/website_project_with_analytics/ @lciutacu
|
/doc/tutorials/website_project_with_analytics/ @lciutacu
|
||||||
/doc/update/ @axil
|
/doc/update/ @axil
|
||||||
|
/doc/user/ @msedlakjakubowski
|
||||||
/doc/user/analytics/ @lciutacu
|
/doc/user/analytics/ @lciutacu
|
||||||
/doc/user/analytics/ci_cd_analytics.md @phillipwells
|
/doc/user/analytics/ci_cd_analytics.md @phillipwells
|
||||||
/doc/user/application_security/ @rdickenson @phillipwells
|
/doc/user/application_security/ @rdickenson @phillipwells
|
||||||
|
|
@ -923,13 +932,11 @@ lib/gitlab/checks/**
|
||||||
/doc/user/application_security/security_dashboard/ @rdickenson
|
/doc/user/application_security/security_dashboard/ @rdickenson
|
||||||
/doc/user/application_security/vulnerabilities/ @rdickenson
|
/doc/user/application_security/vulnerabilities/ @rdickenson
|
||||||
/doc/user/application_security/vulnerability_report/ @rdickenson
|
/doc/user/application_security/vulnerability_report/ @rdickenson
|
||||||
/doc/user/asciidoc.md @msedlakjakubowski
|
|
||||||
/doc/user/clusters/ @phillipwells
|
/doc/user/clusters/ @phillipwells
|
||||||
/doc/user/compliance/ @eread
|
/doc/user/compliance/ @eread
|
||||||
/doc/user/compliance/license_approval_policies.md @rdickenson
|
/doc/user/compliance/license_approval_policies.md @rdickenson
|
||||||
/doc/user/compliance/license_scanning_of_cyclonedx_files/ @rdickenson @phillipwells
|
/doc/user/compliance/license_scanning_of_cyclonedx_files/ @rdickenson @phillipwells
|
||||||
/doc/user/discussions/ @aqualls
|
/doc/user/discussions/ @aqualls
|
||||||
/doc/user/emoji_reactions.md @msedlakjakubowski
|
|
||||||
/doc/user/enterprise_user/ @jglassman1
|
/doc/user/enterprise_user/ @jglassman1
|
||||||
/doc/user/get_started/get_started_managing_code.md @msedlakjakubowski
|
/doc/user/get_started/get_started_managing_code.md @msedlakjakubowski
|
||||||
/doc/user/get_started/get_started_managing_infrastructure.md @phillipwells
|
/doc/user/get_started/get_started_managing_infrastructure.md @phillipwells
|
||||||
|
|
@ -962,9 +969,7 @@ lib/gitlab/checks/**
|
||||||
/doc/user/infrastructure/ @phillipwells
|
/doc/user/infrastructure/ @phillipwells
|
||||||
/doc/user/infrastructure/clusters/manage/management_project_applications/ @phillipwells
|
/doc/user/infrastructure/clusters/manage/management_project_applications/ @phillipwells
|
||||||
/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md @ashrafkhamis
|
/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md @ashrafkhamis
|
||||||
/doc/user/markdown.md @msedlakjakubowski
|
|
||||||
/doc/user/namespace/ @lciutacu
|
/doc/user/namespace/ @lciutacu
|
||||||
/doc/user/okrs.md @msedlakjakubowski
|
|
||||||
/doc/user/operations_dashboard/ @phillipwells
|
/doc/user/operations_dashboard/ @phillipwells
|
||||||
/doc/user/organization/ @lciutacu
|
/doc/user/organization/ @lciutacu
|
||||||
/doc/user/packages/ @phillipwells
|
/doc/user/packages/ @phillipwells
|
||||||
|
|
@ -976,7 +981,6 @@ lib/gitlab/checks/**
|
||||||
/doc/user/profile/achievements.md @lciutacu
|
/doc/user/profile/achievements.md @lciutacu
|
||||||
/doc/user/profile/comment_templates.md @aqualls
|
/doc/user/profile/comment_templates.md @aqualls
|
||||||
/doc/user/profile/contributions_calendar.md @lciutacu
|
/doc/user/profile/contributions_calendar.md @lciutacu
|
||||||
/doc/user/project/ @msedlakjakubowski
|
|
||||||
/doc/user/project/badges.md @lciutacu
|
/doc/user/project/badges.md @lciutacu
|
||||||
/doc/user/project/clusters/ @phillipwells
|
/doc/user/project/clusters/ @phillipwells
|
||||||
/doc/user/project/code_intelligence.md @aqualls
|
/doc/user/project/code_intelligence.md @aqualls
|
||||||
|
|
@ -1028,11 +1032,9 @@ lib/gitlab/checks/**
|
||||||
/doc/user/public_access.md @lciutacu
|
/doc/user/public_access.md @lciutacu
|
||||||
/doc/user/reserved_names.md @lciutacu
|
/doc/user/reserved_names.md @lciutacu
|
||||||
/doc/user/search/ @ashrafkhamis
|
/doc/user/search/ @ashrafkhamis
|
||||||
/doc/user/snippets.md @msedlakjakubowski
|
|
||||||
/doc/user/ssh.md @jglassman1
|
/doc/user/ssh.md @jglassman1
|
||||||
/doc/user/ssh_troubleshooting.md @jglassman1
|
/doc/user/ssh_troubleshooting.md @jglassman1
|
||||||
/doc/user/storage_management_automation.md @fneill
|
/doc/user/storage_management_automation.md @fneill
|
||||||
/doc/user/tasks.md @msedlakjakubowski
|
|
||||||
/doc/user/usage_quotas.md @fneill
|
/doc/user/usage_quotas.md @fneill
|
||||||
/doc/user/workspace/ @ashrafkhamis
|
/doc/user/workspace/ @ashrafkhamis
|
||||||
# End rake-managed-docs-block
|
# End rake-managed-docs-block
|
||||||
|
|
|
||||||
3
Gemfile
3
Gemfile
|
|
@ -407,7 +407,8 @@ gem 'webrick', '~> 1.8.1', require: false # rubocop:todo Gemfile/MissingFeatureC
|
||||||
gem 'prometheus-client-mmap', '~> 1.1', '>= 1.1.1', require: 'prometheus/client' # rubocop:todo Gemfile/MissingFeatureCategory
|
gem 'prometheus-client-mmap', '~> 1.1', '>= 1.1.1', require: 'prometheus/client' # rubocop:todo Gemfile/MissingFeatureCategory
|
||||||
|
|
||||||
# Event-driven reactor for Ruby
|
# Event-driven reactor for Ruby
|
||||||
gem 'async', '~> 2.12.1' # rubocop:disable Gemfile/MissingFeatureCategory -- This is general utility gem
|
# Required manually in config/initializers/require_async_gem
|
||||||
|
gem 'async', '~> 2.12.1', require: false # rubocop:disable Gemfile/MissingFeatureCategory -- This is general utility gem
|
||||||
|
|
||||||
# OpenTelemetry
|
# OpenTelemetry
|
||||||
group :opentelemetry do
|
group :opentelemetry do
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils';
|
||||||
import { waitForElement } from '~/lib/utils/dom_utils';
|
import { waitForElement } from '~/lib/utils/dom_utils';
|
||||||
import findAndFollowLink from '~/lib/utils/navigation_utility';
|
import findAndFollowLink from '~/lib/utils/navigation_utility';
|
||||||
import { refreshCurrentPage } from '~/lib/utils/url_utility';
|
import { refreshCurrentPage } from '~/lib/utils/url_utility';
|
||||||
import { helpCenterState } from '~/super_sidebar/constants';
|
import { duoChatGlobalState } from '~/super_sidebar/constants';
|
||||||
import {
|
import {
|
||||||
keysFor,
|
keysFor,
|
||||||
TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,
|
TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,
|
||||||
|
|
@ -225,7 +225,7 @@ export default class Shortcuts {
|
||||||
|
|
||||||
static onToggleDuoChat(e) {
|
static onToggleDuoChat(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
helpCenterState.showTanukiBotChatDrawer = !helpCenterState.showTanukiBotChatDrawer;
|
duoChatGlobalState.isShown = !duoChatGlobalState.isShown;
|
||||||
}
|
}
|
||||||
|
|
||||||
static onTogglePerfBar(e) {
|
static onTogglePerfBar(e) {
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ export default {
|
||||||
modelData: null,
|
modelData: null,
|
||||||
versionData: null,
|
versionData: null,
|
||||||
markdownDocPath: helpPagePath('user/markdown'),
|
markdownDocPath: helpPagePath('user/markdown'),
|
||||||
|
markdownEditorRestrictedToolBarItems: ['full-screen'],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -242,7 +243,7 @@ export default {
|
||||||
:title="$options.modal.title"
|
:title="$options.modal.title"
|
||||||
:action-primary="actionPrimary"
|
:action-primary="actionPrimary"
|
||||||
:action-secondary="$options.modal.actionSecondary"
|
:action-secondary="$options.modal.actionSecondary"
|
||||||
size="sm"
|
size="lg"
|
||||||
@primary="create"
|
@primary="create"
|
||||||
@secondary="resetModal"
|
@secondary="resetModal"
|
||||||
>
|
>
|
||||||
|
|
@ -284,6 +285,7 @@ export default {
|
||||||
:markdown-docs-path="markdownDocPath"
|
:markdown-docs-path="markdownDocPath"
|
||||||
:disable-attachments="disableAttachments"
|
:disable-attachments="disableAttachments"
|
||||||
:placeholder="$options.modal.nameDescriptionPlaceholder"
|
:placeholder="$options.modal.nameDescriptionPlaceholder"
|
||||||
|
:restricted-tool-bar-items="markdownEditorRestrictedToolBarItems"
|
||||||
@input="setDescription"
|
@input="setDescription"
|
||||||
/>
|
/>
|
||||||
</gl-form-group>
|
</gl-form-group>
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ export default {
|
||||||
:title="$options.modal.title"
|
:title="$options.modal.title"
|
||||||
:action-primary="actionPrimary"
|
:action-primary="actionPrimary"
|
||||||
:action-secondary="$options.modal.actionSecondary"
|
:action-secondary="$options.modal.actionSecondary"
|
||||||
size="sm"
|
size="lg"
|
||||||
@primary="create"
|
@primary="create"
|
||||||
@secondary="resetModal"
|
@secondary="resetModal"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { FORUM_URL, PROMO_URL } from 'jh_else_ce/lib/utils/url_utility';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import { STORAGE_KEY } from '~/whats_new/utils/notification';
|
import { STORAGE_KEY } from '~/whats_new/utils/notification';
|
||||||
import Tracking from '~/tracking';
|
import Tracking from '~/tracking';
|
||||||
import { DROPDOWN_Y_OFFSET, HELP_MENU_TRACKING_DEFAULTS, helpCenterState } from '../constants';
|
import { DROPDOWN_Y_OFFSET, HELP_MENU_TRACKING_DEFAULTS, duoChatGlobalState } from '../constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -39,7 +39,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showWhatsNewNotification: this.shouldShowWhatsNewNotification(),
|
showWhatsNewNotification: this.shouldShowWhatsNewNotification(),
|
||||||
helpCenterState,
|
duoChatGlobalState,
|
||||||
toggleWhatsNewDrawer: null,
|
toggleWhatsNewDrawer: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,9 @@ export const sidebarState = Vue.observable({
|
||||||
wasHoverPeek: false,
|
wasHoverPeek: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const helpCenterState = Vue.observable({
|
export const duoChatGlobalState = Vue.observable({
|
||||||
showTanukiBotChatDrawer: false,
|
commands: [],
|
||||||
|
isShown: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SUPER_SIDEBAR_PEEK_OPEN_DELAY = 200;
|
export const SUPER_SIDEBAR_PEEK_OPEN_DELAY = 200;
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
|
restrictedToolBarItems: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const editingMode =
|
const editingMode =
|
||||||
|
|
@ -139,7 +144,9 @@ export default {
|
||||||
return this.autofocus && !this.autofocused ? 'end' : false;
|
return this.autofocus && !this.autofocused ? 'end' : false;
|
||||||
},
|
},
|
||||||
markdownFieldRestrictedToolBarItems() {
|
markdownFieldRestrictedToolBarItems() {
|
||||||
return this.disableAttachments ? ['attach-file'] : [];
|
const restrictAttachments = this.disableAttachments ? ['attach-file'] : [];
|
||||||
|
|
||||||
|
return [...this.restrictedToolBarItems, ...restrictAttachments];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
||||||
|
|
@ -187,10 +187,15 @@ class GraphqlController < ApplicationController
|
||||||
def disable_query_limiting
|
def disable_query_limiting
|
||||||
return unless Gitlab::QueryLimiting.enabled_for_env?
|
return unless Gitlab::QueryLimiting.enabled_for_env?
|
||||||
|
|
||||||
disable_issue = request.headers[DISABLE_SQL_QUERY_LIMIT_HEADER]
|
disable_reference = request.headers[DISABLE_SQL_QUERY_LIMIT_HEADER]
|
||||||
return unless disable_issue
|
return unless disable_reference
|
||||||
|
|
||||||
Gitlab::QueryLimiting.disable!(disable_issue)
|
disable_issue, new_threshold = disable_reference.split(';')
|
||||||
|
if new_threshold
|
||||||
|
Gitlab::QueryLimiting.disable!(disable_issue, new_threshold: new_threshold&.to_i)
|
||||||
|
else
|
||||||
|
Gitlab::QueryLimiting.disable!(disable_issue)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_user_last_activity
|
def set_user_last_activity
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,10 @@ class Import::GitlabGroupsController < ApplicationController
|
||||||
)
|
)
|
||||||
.with_defaults(organization_id: Current.organization_id)
|
.with_defaults(organization_id: Current.organization_id)
|
||||||
|
|
||||||
response = ::Groups::CreateService.new(current_user, group_data).execute
|
response = Namespace.with_disabled_organization_validation do
|
||||||
|
::Groups::CreateService.new(current_user, group_data).execute
|
||||||
|
end
|
||||||
|
|
||||||
group = response[:group]
|
group = response[:group]
|
||||||
|
|
||||||
if response.success?
|
if response.success?
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ class Ldap::OmniauthCallbacksController < OmniauthCallbacksController
|
||||||
return admin_mode_flow(Gitlab::Auth::Ldap::User) if current_user_mode.admin_mode_requested?
|
return admin_mode_flow(Gitlab::Auth::Ldap::User) if current_user_mode.admin_mode_requested?
|
||||||
end
|
end
|
||||||
|
|
||||||
sign_in_user_flow(Gitlab::Auth::Ldap::User)
|
Namespace.with_disabled_organization_validation do
|
||||||
|
sign_in_user_flow(Gitlab::Auth::Ldap::User)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
define_providers!
|
define_providers!
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,9 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
redirect_identity_exists
|
redirect_identity_exists
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sign_in_user_flow(auth_module::User)
|
Namespace.with_disabled_organization_validation do
|
||||||
|
sign_in_user_flow(auth_module::User)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,15 @@ class RegistrationsController < Devise::RegistrationsController
|
||||||
def create
|
def create
|
||||||
set_resource_fields
|
set_resource_fields
|
||||||
|
|
||||||
super do |new_user|
|
Namespace.with_disabled_organization_validation do
|
||||||
if new_user.persisted?
|
super do |new_user|
|
||||||
after_successful_create_hook(new_user)
|
if new_user.persisted?
|
||||||
else
|
after_successful_create_hook(new_user)
|
||||||
track_error(new_user)
|
else
|
||||||
|
track_error(new_user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Devise sets a flash message on both successful & failed signups,
|
# Devise sets a flash message on both successful & failed signups,
|
||||||
# but we only want to show a message if the resource is blocked by a pending approval.
|
# but we only want to show a message if the resource is blocked by a pending approval.
|
||||||
flash[:notice] = nil unless allow_flash_content?(resource)
|
flash[:notice] = nil unless allow_flash_content?(resource)
|
||||||
|
|
|
||||||
|
|
@ -7,79 +7,42 @@ module Types
|
||||||
|
|
||||||
graphql_name 'WorkItemWidget'
|
graphql_name 'WorkItemWidget'
|
||||||
|
|
||||||
field :type, ::Types::WorkItems::WidgetTypeEnum,
|
field :type,
|
||||||
|
::Types::WorkItems::WidgetTypeEnum,
|
||||||
null: true,
|
null: true,
|
||||||
description: 'Widget type.'
|
description: 'Widget type.'
|
||||||
|
|
||||||
ORPHAN_TYPES = [
|
|
||||||
::Types::WorkItems::Widgets::DescriptionType,
|
|
||||||
::Types::WorkItems::Widgets::HierarchyType,
|
|
||||||
::Types::WorkItems::Widgets::LabelsType,
|
|
||||||
::Types::WorkItems::Widgets::AssigneesType,
|
|
||||||
::Types::WorkItems::Widgets::StartAndDueDateType,
|
|
||||||
::Types::WorkItems::Widgets::MilestoneType,
|
|
||||||
::Types::WorkItems::Widgets::NotesType,
|
|
||||||
::Types::WorkItems::Widgets::NotificationsType,
|
|
||||||
::Types::WorkItems::Widgets::CurrentUserTodosType,
|
|
||||||
::Types::WorkItems::Widgets::AwardEmojiType,
|
|
||||||
::Types::WorkItems::Widgets::LinkedItemsType,
|
|
||||||
::Types::WorkItems::Widgets::ParticipantsType,
|
|
||||||
::Types::WorkItems::Widgets::TimeTracking::TimeTrackingType,
|
|
||||||
::Types::WorkItems::Widgets::DesignsType,
|
|
||||||
::Types::WorkItems::Widgets::DevelopmentType,
|
|
||||||
::Types::WorkItems::Widgets::CrmContactsType
|
|
||||||
].freeze
|
|
||||||
|
|
||||||
def self.ce_orphan_types
|
|
||||||
ORPHAN_TYPES
|
|
||||||
end
|
|
||||||
|
|
||||||
# Whenever a new widget is added make sure to update the spec to avoid N + 1 queries in
|
# Whenever a new widget is added make sure to update the spec to avoid N + 1 queries in
|
||||||
# spec/requests/api/graphql/project/work_items_spec.rb and add the necessary preloads
|
# spec/requests/api/graphql/project/work_items_spec.rb and add the necessary preloads
|
||||||
# in app/graphql/resolvers/work_items_resolver.rb
|
# in app/graphql/resolvers/work_items_resolver.rb
|
||||||
#
|
TYPE_MAPPINGS = {
|
||||||
# rubocop:disable Metrics/CyclomaticComplexity -- we'll have a lot of widgets to handle in the WidgetInterface
|
::WorkItems::Widgets::Description => ::Types::WorkItems::Widgets::DescriptionType,
|
||||||
def self.resolve_type(object, context)
|
::WorkItems::Widgets::Hierarchy => ::Types::WorkItems::Widgets::HierarchyType,
|
||||||
case object
|
::WorkItems::Widgets::Labels => ::Types::WorkItems::Widgets::LabelsType,
|
||||||
when ::WorkItems::Widgets::Description
|
::WorkItems::Widgets::Assignees => ::Types::WorkItems::Widgets::AssigneesType,
|
||||||
::Types::WorkItems::Widgets::DescriptionType
|
::WorkItems::Widgets::StartAndDueDate => ::Types::WorkItems::Widgets::StartAndDueDateType,
|
||||||
when ::WorkItems::Widgets::Hierarchy
|
::WorkItems::Widgets::Milestone => ::Types::WorkItems::Widgets::MilestoneType,
|
||||||
::Types::WorkItems::Widgets::HierarchyType
|
::WorkItems::Widgets::Notes => ::Types::WorkItems::Widgets::NotesType,
|
||||||
when ::WorkItems::Widgets::Assignees
|
::WorkItems::Widgets::Notifications => ::Types::WorkItems::Widgets::NotificationsType,
|
||||||
::Types::WorkItems::Widgets::AssigneesType
|
::WorkItems::Widgets::CurrentUserTodos => ::Types::WorkItems::Widgets::CurrentUserTodosType,
|
||||||
when ::WorkItems::Widgets::Labels
|
::WorkItems::Widgets::AwardEmoji => ::Types::WorkItems::Widgets::AwardEmojiType,
|
||||||
::Types::WorkItems::Widgets::LabelsType
|
::WorkItems::Widgets::LinkedItems => ::Types::WorkItems::Widgets::LinkedItemsType,
|
||||||
when ::WorkItems::Widgets::StartAndDueDate
|
::WorkItems::Widgets::Participants => ::Types::WorkItems::Widgets::ParticipantsType,
|
||||||
::Types::WorkItems::Widgets::StartAndDueDateType
|
::WorkItems::Widgets::TimeTracking => ::Types::WorkItems::Widgets::TimeTracking::TimeTrackingType,
|
||||||
when ::WorkItems::Widgets::Milestone
|
::WorkItems::Widgets::Designs => ::Types::WorkItems::Widgets::DesignsType,
|
||||||
::Types::WorkItems::Widgets::MilestoneType
|
::WorkItems::Widgets::Development => ::Types::WorkItems::Widgets::DevelopmentType,
|
||||||
when ::WorkItems::Widgets::Notes
|
::WorkItems::Widgets::CrmContacts => ::Types::WorkItems::Widgets::CrmContactsType
|
||||||
::Types::WorkItems::Widgets::NotesType
|
}.freeze
|
||||||
when ::WorkItems::Widgets::Notifications
|
|
||||||
::Types::WorkItems::Widgets::NotificationsType
|
|
||||||
when ::WorkItems::Widgets::CurrentUserTodos
|
|
||||||
::Types::WorkItems::Widgets::CurrentUserTodosType
|
|
||||||
when ::WorkItems::Widgets::AwardEmoji
|
|
||||||
::Types::WorkItems::Widgets::AwardEmojiType
|
|
||||||
when ::WorkItems::Widgets::LinkedItems
|
|
||||||
::Types::WorkItems::Widgets::LinkedItemsType
|
|
||||||
when ::WorkItems::Widgets::Participants
|
|
||||||
::Types::WorkItems::Widgets::ParticipantsType
|
|
||||||
when ::WorkItems::Widgets::TimeTracking
|
|
||||||
::Types::WorkItems::Widgets::TimeTracking::TimeTrackingType
|
|
||||||
when ::WorkItems::Widgets::Designs
|
|
||||||
::Types::WorkItems::Widgets::DesignsType
|
|
||||||
when ::WorkItems::Widgets::Development
|
|
||||||
::Types::WorkItems::Widgets::DevelopmentType
|
|
||||||
when ::WorkItems::Widgets::CrmContacts
|
|
||||||
::Types::WorkItems::Widgets::CrmContactsType
|
|
||||||
else
|
|
||||||
raise "Unknown GraphQL type for widget #{object}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# rubocop:enable Metrics/CyclomaticComplexity
|
|
||||||
|
|
||||||
orphan_types(*ORPHAN_TYPES)
|
def self.type_mappings
|
||||||
|
TYPE_MAPPINGS
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.resolve_type(object, context)
|
||||||
|
type_mappings[object.class] || raise("Unknown GraphQL type for widget #{object}")
|
||||||
|
end
|
||||||
|
|
||||||
|
orphan_types(*type_mappings.values)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ class Namespace < ApplicationRecord
|
||||||
has_one :import_user, class_name: 'User', through: :namespace_import_user, foreign_key: :user_id
|
has_one :import_user, class_name: 'User', through: :namespace_import_user, foreign_key: :user_id
|
||||||
|
|
||||||
validates :owner, presence: true, if: ->(n) { n.owner_required? }
|
validates :owner, presence: true, if: ->(n) { n.owner_required? }
|
||||||
|
validates :organization, presence: true, if: :require_organization?
|
||||||
validates :name,
|
validates :name,
|
||||||
presence: true,
|
presence: true,
|
||||||
length: { maximum: 255 }
|
length: { maximum: 255 }
|
||||||
|
|
@ -351,6 +352,15 @@ class Namespace < ApplicationRecord
|
||||||
coalesce = Arel::Nodes::NamedFunction.new('COALESCE', [sum, 0])
|
coalesce = Arel::Nodes::NamedFunction.new('COALESCE', [sum, 0])
|
||||||
coalesce.as(column.to_s)
|
coalesce.as(column.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_disabled_organization_validation
|
||||||
|
current_value = Gitlab::SafeRequestStore[:require_organization]
|
||||||
|
Gitlab::SafeRequestStore[:require_organization] = false
|
||||||
|
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
Gitlab::SafeRequestStore[:require_organization] = current_value
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_reference_base(from = nil, full: false, absolute_path: false)
|
def to_reference_base(from = nil, full: false, absolute_path: false)
|
||||||
|
|
@ -712,6 +722,12 @@ class Namespace < ApplicationRecord
|
||||||
:active_pages_deployments)
|
:active_pages_deployments)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def require_organization?
|
||||||
|
return false unless Feature.enabled?(:require_organization, Feature.current_request)
|
||||||
|
|
||||||
|
Gitlab::SafeRequestStore.fetch(:require_organization) { true } # rubocop:disable Style/RedundantFetchBlock -- This fetch has a different interface
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def cross_namespace_reference?(from)
|
def cross_namespace_reference?(from)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,9 @@ module Ci
|
||||||
|
|
||||||
runner = ::Ci::Runner.new(params)
|
runner = ::Ci::Runner.new(params)
|
||||||
|
|
||||||
return ServiceResponse.success(payload: { runner: runner }) if runner.save
|
if Namespace.with_disabled_organization_validation { runner.save }
|
||||||
|
return ServiceResponse.success(payload: { runner: runner })
|
||||||
|
end
|
||||||
|
|
||||||
ServiceResponse.error(message: runner.errors.full_messages, reason: :save_error)
|
ServiceResponse.error(message: runner.errors.full_messages, reason: :save_error)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ module Groups
|
||||||
@group.name ||= @group.path.dup
|
@group.name ||= @group.path.dup
|
||||||
|
|
||||||
create_chat_team
|
create_chat_team
|
||||||
create_group
|
Namespace.with_disabled_organization_validation { create_group }
|
||||||
|
|
||||||
return error_response unless @group.persisted?
|
return error_response unless @group.persisted?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ module Groups
|
||||||
group.assign_attributes(params)
|
group.assign_attributes(params)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
success = group.save
|
success = Namespace.with_disabled_organization_validation { group.save }
|
||||||
|
|
||||||
after_update if success
|
after_update if success
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ module MergeRequests
|
||||||
trigger_merge_request_reviewers_updated(merge_request)
|
trigger_merge_request_reviewers_updated(merge_request)
|
||||||
|
|
||||||
capture_suggested_reviewers_accepted(merge_request)
|
capture_suggested_reviewers_accepted(merge_request)
|
||||||
set_first_reviewer_assigned_at_metrics(merge_request, current_user) if new_reviewers.any?
|
set_first_reviewer_assigned_at_metrics(merge_request) if new_reviewers.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
def cleanup_environments(merge_request)
|
def cleanup_environments(merge_request)
|
||||||
|
|
@ -279,9 +279,7 @@ module MergeRequests
|
||||||
# Implemented in EE
|
# Implemented in EE
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_first_reviewer_assigned_at_metrics(merge_request, user)
|
def set_first_reviewer_assigned_at_metrics(merge_request)
|
||||||
return unless Feature.enabled?(:store_first_reviewer_assignment_timestamp_in_metrics, user, type: :beta)
|
|
||||||
|
|
||||||
metrics = merge_request.metrics
|
metrics = merge_request.metrics
|
||||||
return unless metrics
|
return unless metrics
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ module Users
|
||||||
user = build_class.new(current_user, params).execute
|
user = build_class.new(current_user, params).execute
|
||||||
reset_token = user.generate_reset_token if user.recently_sent_password_reset?
|
reset_token = user.generate_reset_token if user.recently_sent_password_reset?
|
||||||
|
|
||||||
after_create_hook(user, reset_token) if user.save
|
Namespace.with_disabled_organization_validation do
|
||||||
|
after_create_hook(user, reset_token) if user.save
|
||||||
|
end
|
||||||
|
|
||||||
user
|
user
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
name: store_first_reviewer_assignment_timestamp_in_metrics
|
name: require_organization
|
||||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/466383
|
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/411832
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/158422
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/155732
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/470926
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/470839
|
||||||
milestone: '17.2'
|
milestone: '17.3'
|
||||||
group: group::optimize
|
group: group::tenant scale
|
||||||
type: beta
|
type: gitlab_com_derisk
|
||||||
default_enabled: true
|
default_enabled: false
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
if RUBY_VERSION >= "3.3"
|
||||||
|
# No more such warnings in Ruby 3.3+
|
||||||
|
require 'async'
|
||||||
|
else
|
||||||
|
# Silences this warning while requiring async gem:
|
||||||
|
# `warning: IO::Buffer is experimental and both the Ruby and C interface may change in the future!`
|
||||||
|
# See also https://github.com/socketry/io-event/issues/82
|
||||||
|
Kernel.silence_warnings do
|
||||||
|
require 'async'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
migration_job_name: BackfillEvidencesProjectId
|
||||||
|
description: Backfills sharding key `evidences.project_id` from `releases`.
|
||||||
|
feature_category: release_evidence
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159580
|
||||||
|
milestone: '17.3'
|
||||||
|
queued_migration_version: 20240716133952
|
||||||
|
finalize_after: '2024-08-22'
|
||||||
|
finalized_by: # version of the migration that finalized this BBM
|
||||||
|
|
@ -17,3 +17,4 @@ desired_sharding_key:
|
||||||
table: releases
|
table: releases
|
||||||
sharding_key: project_id
|
sharding_key: project_id
|
||||||
belongs_to: release
|
belongs_to: release
|
||||||
|
desired_sharding_key_migration_job_name: BackfillEvidencesProjectId
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddProjectIdToEvidences < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '17.3'
|
||||||
|
|
||||||
|
def change
|
||||||
|
add_column :evidences, :project_id, :bigint
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class IndexEvidencesOnProjectId < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '17.3'
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
INDEX_NAME = 'index_evidences_on_project_id'
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_index :evidences, :project_id, name: INDEX_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_concurrent_index_by_name :evidences, INDEX_NAME
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddEvidencesProjectIdFk < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '17.3'
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_foreign_key :evidences, :projects, column: :project_id, on_delete: :cascade
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
with_lock_retries do
|
||||||
|
remove_foreign_key :evidences, column: :project_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddEvidencesProjectIdTrigger < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '17.3'
|
||||||
|
|
||||||
|
def up
|
||||||
|
install_sharding_key_assignment_trigger(
|
||||||
|
table: :evidences,
|
||||||
|
sharding_key: :project_id,
|
||||||
|
parent_table: :releases,
|
||||||
|
parent_sharding_key: :project_id,
|
||||||
|
foreign_key: :release_id
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_sharding_key_assignment_trigger(
|
||||||
|
table: :evidences,
|
||||||
|
sharding_key: :project_id,
|
||||||
|
parent_table: :releases,
|
||||||
|
parent_sharding_key: :project_id,
|
||||||
|
foreign_key: :release_id
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class QueueBackfillEvidencesProjectId < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '17.3'
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
|
||||||
|
|
||||||
|
MIGRATION = "BackfillEvidencesProjectId"
|
||||||
|
DELAY_INTERVAL = 2.minutes
|
||||||
|
BATCH_SIZE = 1000
|
||||||
|
SUB_BATCH_SIZE = 100
|
||||||
|
|
||||||
|
def up
|
||||||
|
queue_batched_background_migration(
|
||||||
|
MIGRATION,
|
||||||
|
:evidences,
|
||||||
|
:id,
|
||||||
|
:project_id,
|
||||||
|
:releases,
|
||||||
|
:project_id,
|
||||||
|
:release_id,
|
||||||
|
job_interval: DELAY_INTERVAL,
|
||||||
|
batch_size: BATCH_SIZE,
|
||||||
|
sub_batch_size: SUB_BATCH_SIZE
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
delete_batched_background_migration(
|
||||||
|
MIGRATION,
|
||||||
|
:evidences,
|
||||||
|
:id,
|
||||||
|
[
|
||||||
|
:project_id,
|
||||||
|
:releases,
|
||||||
|
:project_id,
|
||||||
|
:release_id
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
db1a5709484f2352e0858fb1efc4191e408c361aba1d3b94a50f943c508fd941
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
4b6c8960d7eab5e62087b56afb1855b277eab8bd38662f7fc8c269392638ff06
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
8680f5ef0acbc1e9b4bebf9b8c81e7d72f72f7f2bdc68d6aab247dd9b8ad4416
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1798657b951493363ac8bd42596b3ff2b6007a0e80f026a2f1890543b1d2f7bf
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
b88c38cc0991bda066f569bbb3e6a1519bccc19219dde3782eb7afdffbe4063c
|
||||||
|
|
@ -1757,6 +1757,22 @@ RETURN NEW;
|
||||||
END
|
END
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
CREATE FUNCTION trigger_cac7c0698291() RETURNS trigger
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS $$
|
||||||
|
BEGIN
|
||||||
|
IF NEW."project_id" IS NULL THEN
|
||||||
|
SELECT "project_id"
|
||||||
|
INTO NEW."project_id"
|
||||||
|
FROM "releases"
|
||||||
|
WHERE "releases"."id" = NEW."release_id";
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
CREATE FUNCTION trigger_d4487a75bd44() RETURNS trigger
|
CREATE FUNCTION trigger_d4487a75bd44() RETURNS trigger
|
||||||
LANGUAGE plpgsql
|
LANGUAGE plpgsql
|
||||||
AS $$
|
AS $$
|
||||||
|
|
@ -10457,7 +10473,8 @@ CREATE TABLE evidences (
|
||||||
created_at timestamp with time zone NOT NULL,
|
created_at timestamp with time zone NOT NULL,
|
||||||
updated_at timestamp with time zone NOT NULL,
|
updated_at timestamp with time zone NOT NULL,
|
||||||
summary_sha bytea,
|
summary_sha bytea,
|
||||||
summary jsonb DEFAULT '{}'::jsonb NOT NULL
|
summary jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||||
|
project_id bigint
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE SEQUENCE evidences_id_seq
|
CREATE SEQUENCE evidences_id_seq
|
||||||
|
|
@ -27366,6 +27383,8 @@ CREATE INDEX index_events_on_project_id_and_id ON events USING btree (project_id
|
||||||
|
|
||||||
CREATE UNIQUE INDEX index_events_on_target_type_and_target_id_and_fingerprint ON events USING btree (target_type, target_id, fingerprint);
|
CREATE UNIQUE INDEX index_events_on_target_type_and_target_id_and_fingerprint ON events USING btree (target_type, target_id, fingerprint);
|
||||||
|
|
||||||
|
CREATE INDEX index_evidences_on_project_id ON evidences USING btree (project_id);
|
||||||
|
|
||||||
CREATE INDEX index_evidences_on_release_id ON evidences USING btree (release_id);
|
CREATE INDEX index_evidences_on_release_id ON evidences USING btree (release_id);
|
||||||
|
|
||||||
CREATE INDEX index_expired_and_not_notified_personal_access_tokens ON personal_access_tokens USING btree (id, expires_at) WHERE ((impersonation = false) AND (revoked = false) AND (expire_notification_delivered = false));
|
CREATE INDEX index_expired_and_not_notified_personal_access_tokens ON personal_access_tokens USING btree (id, expires_at) WHERE ((impersonation = false) AND (revoked = false) AND (expire_notification_delivered = false));
|
||||||
|
|
@ -31914,6 +31933,8 @@ CREATE TRIGGER trigger_c8bc8646bce9 BEFORE INSERT OR UPDATE ON vulnerability_sta
|
||||||
|
|
||||||
CREATE TRIGGER trigger_c9090feed334 BEFORE INSERT OR UPDATE ON boards_epic_lists FOR EACH ROW EXECUTE FUNCTION trigger_c9090feed334();
|
CREATE TRIGGER trigger_c9090feed334 BEFORE INSERT OR UPDATE ON boards_epic_lists FOR EACH ROW EXECUTE FUNCTION trigger_c9090feed334();
|
||||||
|
|
||||||
|
CREATE TRIGGER trigger_cac7c0698291 BEFORE INSERT OR UPDATE ON evidences FOR EACH ROW EXECUTE FUNCTION trigger_cac7c0698291();
|
||||||
|
|
||||||
CREATE TRIGGER trigger_catalog_resource_sync_event_on_project_update AFTER UPDATE ON projects FOR EACH ROW WHEN ((((old.name)::text IS DISTINCT FROM (new.name)::text) OR (old.description IS DISTINCT FROM new.description) OR (old.visibility_level IS DISTINCT FROM new.visibility_level))) EXECUTE FUNCTION insert_catalog_resource_sync_event();
|
CREATE TRIGGER trigger_catalog_resource_sync_event_on_project_update AFTER UPDATE ON projects FOR EACH ROW WHEN ((((old.name)::text IS DISTINCT FROM (new.name)::text) OR (old.description IS DISTINCT FROM new.description) OR (old.visibility_level IS DISTINCT FROM new.visibility_level))) EXECUTE FUNCTION insert_catalog_resource_sync_event();
|
||||||
|
|
||||||
CREATE TRIGGER trigger_d4487a75bd44 BEFORE INSERT OR UPDATE ON terraform_state_versions FOR EACH ROW EXECUTE FUNCTION trigger_d4487a75bd44();
|
CREATE TRIGGER trigger_d4487a75bd44 BEFORE INSERT OR UPDATE ON terraform_state_versions FOR EACH ROW EXECUTE FUNCTION trigger_d4487a75bd44();
|
||||||
|
|
@ -33125,6 +33146,9 @@ ALTER TABLE ONLY personal_access_tokens
|
||||||
ALTER TABLE ONLY jira_tracker_data
|
ALTER TABLE ONLY jira_tracker_data
|
||||||
ADD CONSTRAINT fk_c98abcd54c FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
|
ADD CONSTRAINT fk_c98abcd54c FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY evidences
|
||||||
|
ADD CONSTRAINT fk_ca4bbc114d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
ALTER TABLE ONLY subscription_add_on_purchases
|
ALTER TABLE ONLY subscription_add_on_purchases
|
||||||
ADD CONSTRAINT fk_caed789645 FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
ADD CONSTRAINT fk_caed789645 FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ exceptions:
|
||||||
- ANSI
|
- ANSI
|
||||||
- APAC
|
- APAC
|
||||||
- API
|
- API
|
||||||
|
- ARIA
|
||||||
- APM
|
- APM
|
||||||
- ARM
|
- ARM
|
||||||
- ARN
|
- ARN
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ Instead of checking repositories manually, GitLab can be configured to run the c
|
||||||
1. Enable **Enable repository checks**.
|
1. Enable **Enable repository checks**.
|
||||||
|
|
||||||
When enabled, GitLab periodically runs a repository check on all project repositories and wiki
|
When enabled, GitLab periodically runs a repository check on all project repositories and wiki
|
||||||
repositories to detect possible data corruption. A project is checked no more than once per month.
|
repositories to detect possible data corruption. A project is checked no more than once per month, and new projects aren't checked for at least 24 hours.
|
||||||
|
|
||||||
Administrators can configure the frequency of repository checks. To edit the frequency:
|
Administrators can configure the frequency of repository checks. To edit the frequency:
|
||||||
|
|
||||||
- For Linux package installations, edit `gitlab_rails['repository_check_worker_cron']` in
|
- For Linux package installations, edit `gitlab_rails['repository_check_worker_cron']` in
|
||||||
|
|
|
||||||
|
|
@ -118,45 +118,38 @@ Chat interface. The following example shows how to open the GitLab Duo Chat
|
||||||
drawer by using an event listener and the GitLab Duo Chat global state:
|
drawer by using an event listener and the GitLab Duo Chat global state:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { helpCenterState } from '~/super_sidebar/constants';
|
import { duoChatGlobalState } from '~/super_sidebar/constants';
|
||||||
myFancyToggleToOpenChat.addEventListener('click', () => {
|
myFancyToggleToOpenChat.addEventListener('click', () => {
|
||||||
helpCenterState.showTanukiBotChatDrawer = true;
|
duoChatGlobalState.isShown = true;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Initiating GitLab Duo Chat with a pre-defined prompt
|
#### Initiating GitLab Duo Chat with a pre-defined prompt
|
||||||
|
|
||||||
In some scenarios, you may want to direct users towards a specific topic or
|
In some scenarios, you may want to direct users towards a specific topic or
|
||||||
query when they open GitLab Duo Chat. The following example method:
|
query when they open GitLab Duo Chat. We have a utility function that will
|
||||||
|
open DuoChat drawer and send a command in a queue for DuoChat to execute on.
|
||||||
1. Opens the GitLab Duo Chat drawer.
|
This should trigger the loading state and the streaming with the given prompt.
|
||||||
1. Sends a pre-defined prompt to GitLab Duo Chat.
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
|
import { sendDuoChatCommand } from 'ee/ai/utils';
|
||||||
import { helpCenterState } from '~/super_sidebar/constants';
|
|
||||||
[...]
|
[...]
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
openChatWithPrompt() {
|
openChatWithPrompt() {
|
||||||
const myPrompt = "What is the meaning of life?"
|
sendDuoChatCommand(
|
||||||
helpCenterState.showTanukiBotChatDrawer = true;
|
{
|
||||||
|
question: '/feedback' // This is your prompt
|
||||||
this.$apollo
|
resourceId: 'gid:://gitlab/WorkItem/1', // A unique ID to identify the action for streaming
|
||||||
.mutate({
|
variables: {} // Any additional graphql variables you want to pass to ee/app/assets/javascripts/ai/graphql/chat.mutation.graphql when executing the query
|
||||||
mutation: chatMutation,
|
}
|
||||||
variables: {
|
)
|
||||||
question: myPrompt,
|
|
||||||
resourceId: this.resourceId,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
// handle potential errors here
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that `sendDuoChatCommand` cannot be chained, meaning that you can send one command to DuoChat and have to wait until this action is done before sending a different command or the previous command might not work as expected.
|
||||||
|
|
||||||
This enhancement allows for a more tailored user experience by guiding the
|
This enhancement allows for a more tailored user experience by guiding the
|
||||||
conversation in GitLab Duo Chat towards predefined areas of interest or concern.
|
conversation in GitLab Duo Chat towards predefined areas of interest or concern.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ All tables with the following `gitlab_schema` are considered "cell-local":
|
||||||
|
|
||||||
- `gitlab_main_cell`
|
- `gitlab_main_cell`
|
||||||
- `gitlab_ci`
|
- `gitlab_ci`
|
||||||
|
- `gitlab_sec`
|
||||||
|
|
||||||
All newly created cell-local tables are required to have a `sharding_key`
|
All newly created cell-local tables are required to have a `sharding_key`
|
||||||
defined in the corresponding `db/docs/` file for that table.
|
defined in the corresponding `db/docs/` file for that table.
|
||||||
|
|
|
||||||
|
|
@ -12,4 +12,15 @@ The following feature flags exist in GitLab. These flags determine the availabil
|
||||||
|
|
||||||
For self-managed instances, [GitLab administrators can change the state of the flag](../administration/feature_flags.md).
|
For self-managed instances, [GitLab administrators can change the state of the flag](../administration/feature_flags.md).
|
||||||
|
|
||||||
|
<!-- markdownlint-disable MD044 -->
|
||||||
|
<!-- MD044/proper-names test disabled after this line to make page compatible with markdownlint-cli 0.29.0. -->
|
||||||
|
<!-- See https://docs.gitlab.com/ee/development/documentation/testing/markdownlint.html#disable-markdownlint-tests -->
|
||||||
|
|
||||||
|
<div class="d-none">
|
||||||
|
<strong>If you don't see the feature flag tables below, view them at <a href="https://docs.gitlab.com/ee/user/feature_flags.html">docs.gitlab.com</a>.</strong>
|
||||||
|
</div>
|
||||||
|
<!-- the div above will not display on the docs site but will display on /help -->
|
||||||
|
|
||||||
|
<!-- markdownlint-enable MD044 -->
|
||||||
|
|
||||||
<!-- When published, everything below this line is generated by 'layouts/feature_flags_table.md.erb' in the 'gitlab-docs' repository -->
|
<!-- When published, everything below this line is generated by 'layouts/feature_flags_table.md.erb' in the 'gitlab-docs' repository -->
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,9 @@ module Gitlab
|
||||||
|
|
||||||
block_after_save = needs_blocking?
|
block_after_save = needs_blocking?
|
||||||
|
|
||||||
Users::UpdateService.new(gl_user, user: gl_user).execute!
|
Namespace.with_disabled_organization_validation do
|
||||||
|
Users::UpdateService.new(gl_user, user: gl_user).execute!
|
||||||
|
end
|
||||||
|
|
||||||
gl_user.block_pending_approval if block_after_save
|
gl_user.block_pending_approval if block_after_save
|
||||||
activate_user_if_user_cap_not_reached
|
activate_user_if_user_cap_not_reached
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
module BackgroundMigration
|
||||||
|
class BackfillEvidencesProjectId < BackfillDesiredShardingKeyJob
|
||||||
|
operation_name :backfill_evidences_project_id
|
||||||
|
feature_category :release_evidence
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -19,7 +19,9 @@ module Gitlab
|
||||||
)
|
)
|
||||||
|
|
||||||
user.assign_personal_namespace(Organizations::Organization.default_organization)
|
user.assign_personal_namespace(Organizations::Organization.default_organization)
|
||||||
user.save!
|
Namespace.with_disabled_organization_validation do
|
||||||
|
user.save!
|
||||||
|
end
|
||||||
user
|
user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ module Gitlab
|
||||||
|
|
||||||
modify_attributes
|
modify_attributes
|
||||||
|
|
||||||
@importable.save!(touch: false)
|
Namespace.with_disabled_organization_validation { @importable.save!(touch: false) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_attributes(params)
|
def filter_attributes(params)
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,9 @@ module Gitlab
|
||||||
def create_group(**args)
|
def create_group(**args)
|
||||||
logger.info(message: 'Creating group', **args)
|
logger.info(message: 'Creating group', **args)
|
||||||
|
|
||||||
ensure_success(::Groups::CreateService.new(@user, **args).execute[:group])
|
Namespace.with_disabled_organization_validation do
|
||||||
|
ensure_success(::Groups::CreateService.new(@user, **args).execute[:group])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_project(name:, namespace_id:, **args)
|
def ensure_project(name:, namespace_id:, **args)
|
||||||
|
|
@ -194,7 +196,9 @@ module Gitlab
|
||||||
def create_project(**args)
|
def create_project(**args)
|
||||||
logger.info(message: 'Creating project', **args)
|
logger.info(message: 'Creating project', **args)
|
||||||
|
|
||||||
ensure_success(::Projects::CreateService.new(@user, **args).execute)
|
Namespace.with_disabled_organization_validation do
|
||||||
|
ensure_success(::Projects::CreateService.new(@user, **args).execute)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def register_record(record, records)
|
def register_record(record, records)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ namespace :tw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# For groups without an assigned TW, comment out the line.
|
||||||
CODE_OWNER_RULES = [
|
CODE_OWNER_RULES = [
|
||||||
# CodeOwnerRule.new('Activation', ''),
|
# CodeOwnerRule.new('Activation', ''),
|
||||||
# CodeOwnerRule.new('Acquisition', ''),
|
# CodeOwnerRule.new('Acquisition', ''),
|
||||||
|
|
@ -56,7 +57,7 @@ namespace :tw do
|
||||||
CodeOwnerRule.new('Remote Development', '@ashrafkhamis'),
|
CodeOwnerRule.new('Remote Development', '@ashrafkhamis'),
|
||||||
CodeOwnerRule.new('Import and Integrate', '@eread'),
|
CodeOwnerRule.new('Import and Integrate', '@eread'),
|
||||||
CodeOwnerRule.new('Infrastructure', '@sselhorn'),
|
CodeOwnerRule.new('Infrastructure', '@sselhorn'),
|
||||||
# CodeOwnerRule.new('Knowledge', ''),
|
CodeOwnerRule.new('Knowledge', '@msedlakjakubowski'),
|
||||||
CodeOwnerRule.new('MLOps', '@sselhorn @jglassman1 @fneill'),
|
CodeOwnerRule.new('MLOps', '@sselhorn @jglassman1 @fneill'),
|
||||||
# CodeOwnerRule.new('Observability', ''),
|
# CodeOwnerRule.new('Observability', ''),
|
||||||
CodeOwnerRule.new('Optimize', '@lciutacu'),
|
CodeOwnerRule.new('Optimize', '@lciutacu'),
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,9 @@ namespace :gitlab do
|
||||||
|
|
||||||
tmp_namespace_path = "tmp-project-import-#{Time.now.to_i}"
|
tmp_namespace_path = "tmp-project-import-#{Time.now.to_i}"
|
||||||
puts "Creating temporary namespace #{tmp_namespace_path}"
|
puts "Creating temporary namespace #{tmp_namespace_path}"
|
||||||
tmp_namespace = Namespace.create!(owner: admin, name: tmp_namespace_path, path: tmp_namespace_path, type: Namespaces::UserNamespace.sti_name)
|
tmp_namespace = Namespace.with_disabled_organization_validation do
|
||||||
|
Namespace.create!(owner: admin, name: tmp_namespace_path, path: tmp_namespace_path, type: Namespaces::UserNamespace.sti_name)
|
||||||
|
end
|
||||||
|
|
||||||
templates = if template_names.empty?
|
templates = if template_names.empty?
|
||||||
Gitlab::ProjectTemplate.all
|
Gitlab::ProjectTemplate.all
|
||||||
|
|
@ -54,7 +56,7 @@ namespace :gitlab do
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "Creating project for #{template.title}"
|
puts "Creating project for #{template.title}"
|
||||||
project = Projects::CreateService.new(admin, params).execute
|
project = Namespace.with_disabled_organization_validation { Projects::CreateService.new(admin, params).execute }
|
||||||
|
|
||||||
unless project.persisted?
|
unless project.persisted?
|
||||||
raise "Failed to create project: #{project.errors.messages}"
|
raise "Failed to create project: #{project.errors.messages}"
|
||||||
|
|
|
||||||
|
|
@ -2156,12 +2156,6 @@ msgstr ""
|
||||||
msgid "AISummary|View summary"
|
msgid "AISummary|View summary"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "AI|An error occurred while explaining the code."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "AI|An error occurred while troubleshooting the failed job."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "AI|Apply AI-generated description"
|
msgid "AI|Apply AI-generated description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ gem 'capybara', '~> 3.40.0'
|
||||||
gem 'capybara-screenshot', '~> 1.0.26'
|
gem 'capybara-screenshot', '~> 1.0.26'
|
||||||
gem 'rake', '~> 13', '>= 13.2.1'
|
gem 'rake', '~> 13', '>= 13.2.1'
|
||||||
gem 'rspec', '~> 3.13'
|
gem 'rspec', '~> 3.13'
|
||||||
gem 'selenium-webdriver', '= 4.22.0'
|
gem 'selenium-webdriver', '= 4.23.0'
|
||||||
gem 'airborne', '~> 0.3.7', require: false # airborne is messing with rspec sandboxed mode so not requiring by default
|
gem 'airborne', '~> 0.3.7', require: false # airborne is messing with rspec sandboxed mode so not requiring by default
|
||||||
gem 'rest-client', '~> 2.1.0'
|
gem 'rest-client', '~> 2.1.0'
|
||||||
gem 'rspec_junit_formatter', '~> 0.6.0'
|
gem 'rspec_junit_formatter', '~> 0.6.0'
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ GEM
|
||||||
sawyer (0.9.2)
|
sawyer (0.9.2)
|
||||||
addressable (>= 2.3.5)
|
addressable (>= 2.3.5)
|
||||||
faraday (>= 0.17.3, < 3)
|
faraday (>= 0.17.3, < 3)
|
||||||
selenium-webdriver (4.22.0)
|
selenium-webdriver (4.23.0)
|
||||||
base64 (~> 0.2)
|
base64 (~> 0.2)
|
||||||
logger (~> 1.4)
|
logger (~> 1.4)
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
|
|
@ -423,7 +423,7 @@ DEPENDENCIES
|
||||||
rspec-parameterized (~> 1.0.2)
|
rspec-parameterized (~> 1.0.2)
|
||||||
rspec_junit_formatter (~> 0.6.0)
|
rspec_junit_formatter (~> 0.6.0)
|
||||||
ruby-debug-ide (~> 0.7.3)
|
ruby-debug-ide (~> 0.7.3)
|
||||||
selenium-webdriver (= 4.22.0)
|
selenium-webdriver (= 4.23.0)
|
||||||
slack-notifier (~> 2.4)
|
slack-notifier (~> 2.4)
|
||||||
terminal-table (~> 3.0.2)
|
terminal-table (~> 3.0.2)
|
||||||
warning (~> 1.4)
|
warning (~> 1.4)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ FactoryBot.define do
|
||||||
|
|
||||||
owner { association(:user, strategy: :build, namespace: instance, username: path) }
|
owner { association(:user, strategy: :build, namespace: instance, username: path) }
|
||||||
|
|
||||||
|
association :organization
|
||||||
|
|
||||||
after(:create) do |namespace, evaluator|
|
after(:create) do |namespace, evaluator|
|
||||||
# simulating ::Namespaces::ProcessSyncEventsWorker because most tests don't run Sidekiq inline
|
# simulating ::Namespaces::ProcessSyncEventsWorker because most tests don't run Sidekiq inline
|
||||||
# Note: we need to get refreshed `traversal_ids` it is updated via SQL query
|
# Note: we need to get refreshed `traversal_ids` it is updated via SQL query
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,6 @@ describe('ModelCreate', () => {
|
||||||
it('should show markdown editor', () => {
|
it('should show markdown editor', () => {
|
||||||
createWrapper();
|
createWrapper();
|
||||||
|
|
||||||
expect(findMarkdownEditor().exists()).toBe(true);
|
|
||||||
|
|
||||||
expect(findMarkdownEditor().props()).toMatchObject({
|
expect(findMarkdownEditor().props()).toMatchObject({
|
||||||
enableContentEditor: true,
|
enableContentEditor: true,
|
||||||
formFieldProps: {
|
formFieldProps: {
|
||||||
|
|
@ -127,6 +125,7 @@ describe('ModelCreate', () => {
|
||||||
markdownDocsPath: '/help/user/markdown',
|
markdownDocsPath: '/help/user/markdown',
|
||||||
renderMarkdownPath: '/markdown-preview',
|
renderMarkdownPath: '/markdown-preview',
|
||||||
uploadsPath: '',
|
uploadsPath: '',
|
||||||
|
restrictedToolBarItems: ['full-screen'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -238,7 +237,7 @@ describe('ModelCreate', () => {
|
||||||
expect(findGlModal().props()).toMatchObject({
|
expect(findGlModal().props()).toMatchObject({
|
||||||
modalId: 'create-model-modal',
|
modalId: 'create-model-modal',
|
||||||
title: 'Create model, version & import artifacts',
|
title: 'Create model, version & import artifacts',
|
||||||
size: 'sm',
|
size: 'lg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ describe('ModelVersionCreate', () => {
|
||||||
expect(findGlModal().props()).toMatchObject({
|
expect(findGlModal().props()).toMatchObject({
|
||||||
modalId: 'create-model-version-modal',
|
modalId: 'create-model-version-modal',
|
||||||
title: 'Create model version & import artifacts',
|
title: 'Create model version & import artifacts',
|
||||||
size: 'sm',
|
size: 'lg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,31 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when additional restricted tool bar items are given', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
buildWrapper({ propsData: { restrictedToolBarItems: ['full-screen'] } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes them to restrictedToolBarItems', () => {
|
||||||
|
expect(findMarkdownField().props().restrictedToolBarItems).toContain('full-screen');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when attachments are disabled', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
buildWrapper({
|
||||||
|
propsData: { disableAttachments: true, restrictedToolBarItems: ['full-screen'] },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('passes `attach-file` and `full-screen` restrictedToolBarItems', () => {
|
||||||
|
expect(findMarkdownField().props().restrictedToolBarItems).toEqual([
|
||||||
|
'full-screen',
|
||||||
|
'attach-file',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('disabled', () => {
|
describe('disabled', () => {
|
||||||
it('disables markdown field when disabled prop is true', () => {
|
it('disables markdown field when disabled prop is true', () => {
|
||||||
buildWrapper({ propsData: { disabled: true } });
|
buildWrapper({ propsData: { disabled: true } });
|
||||||
|
|
|
||||||
|
|
@ -266,13 +266,5 @@ RSpec.describe GitlabSchema.types['Group'], feature_category: :groups_and_projec
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when group does not have an organization associated with it' do
|
|
||||||
let_it_be(:group) { create(:group, :public, organization: nil) }
|
|
||||||
|
|
||||||
it 'returns nil' do
|
|
||||||
expect(organization_edit_path).to be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1305,13 +1305,5 @@ RSpec.describe GitlabSchema.types['Project'], feature_category: :groups_and_proj
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when project does not have an organization associated with it' do
|
|
||||||
let_it_be(:project) { create(:project, :public, organization: nil) }
|
|
||||||
|
|
||||||
it 'returns nil' do
|
|
||||||
expect(organization_edit_path).to be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Types::WorkItems::WidgetInterface, feature_category: :team_planning do
|
RSpec.describe Types::WorkItems::WidgetInterface, feature_category: :team_planning do
|
||||||
include GraphqlHelpers
|
include GraphqlHelpers
|
||||||
|
using RSpec::Parameterized::TableSyntax
|
||||||
|
|
||||||
it 'exposes the expected fields' do
|
it 'exposes the expected fields' do
|
||||||
expected_fields = %i[type]
|
expected_fields = %i[type]
|
||||||
|
|
@ -11,42 +12,45 @@ RSpec.describe Types::WorkItems::WidgetInterface, feature_category: :team_planni
|
||||||
expect(described_class).to have_graphql_fields(*expected_fields)
|
expect(described_class).to have_graphql_fields(*expected_fields)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".resolve_type" do
|
where(:widget_class, :widget_type_name) do
|
||||||
using RSpec::Parameterized::TableSyntax
|
WorkItems::Widgets::Description | Types::WorkItems::Widgets::DescriptionType
|
||||||
|
WorkItems::Widgets::Hierarchy | Types::WorkItems::Widgets::HierarchyType
|
||||||
|
WorkItems::Widgets::Assignees | Types::WorkItems::Widgets::AssigneesType
|
||||||
|
WorkItems::Widgets::Labels | Types::WorkItems::Widgets::LabelsType
|
||||||
|
WorkItems::Widgets::Notes | Types::WorkItems::Widgets::NotesType
|
||||||
|
WorkItems::Widgets::Notifications | Types::WorkItems::Widgets::NotificationsType
|
||||||
|
WorkItems::Widgets::CurrentUserTodos | Types::WorkItems::Widgets::CurrentUserTodosType
|
||||||
|
WorkItems::Widgets::AwardEmoji | Types::WorkItems::Widgets::AwardEmojiType
|
||||||
|
WorkItems::Widgets::LinkedItems | Types::WorkItems::Widgets::LinkedItemsType
|
||||||
|
WorkItems::Widgets::LinkedItems | Types::WorkItems::Widgets::LinkedItemsType
|
||||||
|
WorkItems::Widgets::StartAndDueDate | Types::WorkItems::Widgets::StartAndDueDateType
|
||||||
|
WorkItems::Widgets::Milestone | Types::WorkItems::Widgets::MilestoneType
|
||||||
|
WorkItems::Widgets::Participants | Types::WorkItems::Widgets::ParticipantsType
|
||||||
|
WorkItems::Widgets::TimeTracking | Types::WorkItems::Widgets::TimeTracking::TimeTrackingType
|
||||||
|
WorkItems::Widgets::Designs | Types::WorkItems::Widgets::DesignsType
|
||||||
|
WorkItems::Widgets::CrmContacts | Types::WorkItems::Widgets::CrmContactsType
|
||||||
|
end
|
||||||
|
|
||||||
where(:widget_class, :widget_type_name) do
|
with_them do
|
||||||
WorkItems::Widgets::Description | Types::WorkItems::Widgets::DescriptionType
|
describe ".resolve_type" do
|
||||||
WorkItems::Widgets::Hierarchy | Types::WorkItems::Widgets::HierarchyType
|
|
||||||
WorkItems::Widgets::Assignees | Types::WorkItems::Widgets::AssigneesType
|
|
||||||
WorkItems::Widgets::Labels | Types::WorkItems::Widgets::LabelsType
|
|
||||||
WorkItems::Widgets::Notes | Types::WorkItems::Widgets::NotesType
|
|
||||||
WorkItems::Widgets::Notifications | Types::WorkItems::Widgets::NotificationsType
|
|
||||||
WorkItems::Widgets::CurrentUserTodos | Types::WorkItems::Widgets::CurrentUserTodosType
|
|
||||||
WorkItems::Widgets::AwardEmoji | Types::WorkItems::Widgets::AwardEmojiType
|
|
||||||
WorkItems::Widgets::LinkedItems | Types::WorkItems::Widgets::LinkedItemsType
|
|
||||||
WorkItems::Widgets::LinkedItems | Types::WorkItems::Widgets::LinkedItemsType
|
|
||||||
WorkItems::Widgets::StartAndDueDate | Types::WorkItems::Widgets::StartAndDueDateType
|
|
||||||
WorkItems::Widgets::Milestone | Types::WorkItems::Widgets::MilestoneType
|
|
||||||
WorkItems::Widgets::Participants | Types::WorkItems::Widgets::ParticipantsType
|
|
||||||
WorkItems::Widgets::TimeTracking | Types::WorkItems::Widgets::TimeTracking::TimeTrackingType
|
|
||||||
WorkItems::Widgets::Designs | Types::WorkItems::Widgets::DesignsType
|
|
||||||
WorkItems::Widgets::Development | Types::WorkItems::Widgets::DevelopmentType
|
|
||||||
WorkItems::Widgets::CrmContacts | Types::WorkItems::Widgets::CrmContactsType
|
|
||||||
end
|
|
||||||
|
|
||||||
with_them do
|
|
||||||
it 'knows the correct type for objects' do
|
it 'knows the correct type for objects' do
|
||||||
expect(
|
expect(
|
||||||
described_class.resolve_type(widget_class.new(build(:work_item)), {})
|
described_class.resolve_type(widget_class.new(build(:work_item)), {})
|
||||||
).to eq(widget_type_name)
|
).to eq(widget_type_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'raises an error for an unknown type' do
|
||||||
|
project = build(:project)
|
||||||
|
|
||||||
|
expect { described_class.resolve_type(project, {}) }
|
||||||
|
.to raise_error("Unknown GraphQL type for widget #{project}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an error for an unknown type' do
|
describe '.orphan_types' do
|
||||||
project = build(:project)
|
it 'includes the type' do
|
||||||
|
expect(described_class.orphan_types).to include(widget_type_name)
|
||||||
expect { described_class.resolve_type(project, {}) }
|
end
|
||||||
.to raise_error("Unknown GraphQL type for widget #{project}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ RSpec.describe Gitlab::Auth::Ldap::User do
|
||||||
|
|
||||||
describe '#valid_sign_in?' do
|
describe '#valid_sign_in?' do
|
||||||
before do
|
before do
|
||||||
gl_user.save!
|
Namespace.with_disabled_organization_validation { gl_user.save! }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns true' do
|
it 'returns true' do
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ RSpec.describe Gitlab::Auth::OAuth::User, feature_category: :system_access do
|
||||||
let(:ldap_user) { Gitlab::Auth::Ldap::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
|
let(:ldap_user) { Gitlab::Auth::Ldap::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
|
||||||
let(:ldap_user_2) { Gitlab::Auth::Ldap::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
|
let(:ldap_user_2) { Gitlab::Auth::Ldap::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
|
||||||
|
|
||||||
|
around do |example|
|
||||||
|
Namespace.with_disabled_organization_validation { example.run }
|
||||||
|
end
|
||||||
|
|
||||||
describe '.find_by_uid_and_provider' do
|
describe '.find_by_uid_and_provider' do
|
||||||
let(:provider) { 'provider' }
|
let(:provider) { 'provider' }
|
||||||
let(:uid) { 'uid' }
|
let(:uid) { 'uid' }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Gitlab::BackgroundMigration::BackfillEvidencesProjectId,
|
||||||
|
feature_category: :release_evidence,
|
||||||
|
schema: 20240716133948 do
|
||||||
|
include_examples 'desired sharding key backfill job' do
|
||||||
|
let(:batch_table) { :evidences }
|
||||||
|
let(:backfill_column) { :project_id }
|
||||||
|
let(:backfill_via_table) { :releases }
|
||||||
|
let(:backfill_via_column) { :project_id }
|
||||||
|
let(:backfill_via_foreign_key) { :release_id }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -43,18 +43,8 @@ RSpec.describe Gitlab::Git::ObjectPool, feature_category: :source_code_managemen
|
||||||
subject.create # rubocop:disable Rails/SaveBang
|
subject.create # rubocop:disable Rails/SaveBang
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the pool doesn't exist yet" do
|
it 'creates the pool' do
|
||||||
it 'creates the pool' do
|
expect(subject.exists?).to be(true)
|
||||||
expect(subject.exists?).to be(true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when the pool already exists' do
|
|
||||||
it 'raises an FailedPrecondition' do
|
|
||||||
expect do
|
|
||||||
subject.create # rubocop:disable Rails/SaveBang
|
|
||||||
end.to raise_error(GRPC::FailedPrecondition)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
require_migration!
|
||||||
|
|
||||||
|
RSpec.describe QueueBackfillEvidencesProjectId, feature_category: :release_evidence do
|
||||||
|
let!(:batched_migration) { described_class::MIGRATION }
|
||||||
|
|
||||||
|
it 'schedules a new batched migration' do
|
||||||
|
reversible_migration do |migration|
|
||||||
|
migration.before -> {
|
||||||
|
expect(batched_migration).not_to have_scheduled_batched_migration
|
||||||
|
}
|
||||||
|
|
||||||
|
migration.after -> {
|
||||||
|
expect(batched_migration).to have_scheduled_batched_migration(
|
||||||
|
table_name: :evidences,
|
||||||
|
column_name: :id,
|
||||||
|
interval: described_class::DELAY_INTERVAL,
|
||||||
|
batch_size: described_class::BATCH_SIZE,
|
||||||
|
sub_batch_size: described_class::SUB_BATCH_SIZE,
|
||||||
|
gitlab_schema: :gitlab_main_cell,
|
||||||
|
job_arguments: [
|
||||||
|
:project_id,
|
||||||
|
:releases,
|
||||||
|
:project_id,
|
||||||
|
:release_id
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -42,8 +42,8 @@ RSpec.describe Analytics::CycleAnalytics::Stage, feature_category: :value_stream
|
||||||
|
|
||||||
describe '.distinct_stages_within_hierarchy' do
|
describe '.distinct_stages_within_hierarchy' do
|
||||||
let_it_be(:group) { create(:group) }
|
let_it_be(:group) { create(:group) }
|
||||||
let_it_be(:sub_group) { create(:group, parent: group) }
|
let_it_be(:sub_group) { create(:group, organization: group.organization, parent: group) }
|
||||||
let_it_be(:project) { create(:project, group: sub_group).reload }
|
let_it_be(:project) { create(:project, organization: group.organization, group: sub_group).reload }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
# event identifiers are the same
|
# event identifiers are the same
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ RSpec.describe Namespaces::ProjectNamespace, 'Routable', :with_clean_rails_cache
|
||||||
|
|
||||||
it 'skips route creation for the resource' do
|
it 'skips route creation for the resource' do
|
||||||
expect do
|
expect do
|
||||||
described_class.create!(project: nil, parent: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC, path: 'foo', name: 'foo')
|
described_class.create!(project: nil, organization: group.organization, parent: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC, path: 'foo', name: 'foo')
|
||||||
end.not_to change { Route.count }
|
end.not_to change { Route.count }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ RSpec.describe Group, feature_category: :groups_and_projects do
|
||||||
|
|
||||||
it 'does not allow a subgroup to have the same name as an existing subgroup' do
|
it 'does not allow a subgroup to have the same name as an existing subgroup' do
|
||||||
sub_group1 = create(:group, parent: group, name: "SG", path: 'api')
|
sub_group1 = create(:group, parent: group, name: "SG", path: 'api')
|
||||||
sub_group2 = described_class.new(parent: group, name: "SG", path: 'api2')
|
sub_group2 = described_class.new(parent: group, name: "SG", path: 'api2', organization: sub_group1.organization)
|
||||||
|
|
||||||
expect(sub_group1).to be_valid
|
expect(sub_group1).to be_valid
|
||||||
expect(sub_group2).not_to be_valid
|
expect(sub_group2).not_to be_valid
|
||||||
|
|
|
||||||
|
|
@ -1277,7 +1277,7 @@ RSpec.describe Member, feature_category: :groups_and_projects do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for updating organization_users' do
|
context 'for updating organization_users' do
|
||||||
let_it_be(:group) { create(:group, :with_organization) }
|
let_it_be(:group) { create(:group) }
|
||||||
let_it_be(:user) { create(:user) }
|
let_it_be(:user) { create(:user) }
|
||||||
let(:member) { create(:group_member, source: group, user: user) }
|
let(:member) { create(:group_member, source: group, user: user) }
|
||||||
|
|
||||||
|
|
@ -1362,12 +1362,6 @@ RSpec.describe Member, feature_category: :groups_and_projects do
|
||||||
|
|
||||||
it_behaves_like 'does not create an organization_user entry'
|
it_behaves_like 'does not create an organization_user entry'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when organization does not exist' do
|
|
||||||
let(:member) { create(:group_member, user: user) }
|
|
||||||
|
|
||||||
it_behaves_like 'does not create an organization_user entry'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when updating' do
|
context 'when updating' do
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
|
||||||
it { is_expected.to validate_presence_of(:path) }
|
it { is_expected.to validate_presence_of(:path) }
|
||||||
it { is_expected.to validate_length_of(:path).is_at_most(255) }
|
it { is_expected.to validate_length_of(:path).is_at_most(255) }
|
||||||
it { is_expected.to validate_presence_of(:owner) }
|
it { is_expected.to validate_presence_of(:owner) }
|
||||||
|
it { is_expected.to validate_presence_of(:organization) }
|
||||||
it { is_expected.to validate_numericality_of(:max_artifacts_size).only_integer.is_greater_than(0) }
|
it { is_expected.to validate_numericality_of(:max_artifacts_size).only_integer.is_greater_than(0) }
|
||||||
|
|
||||||
context 'validating the parent of a namespace' do
|
context 'validating the parent of a namespace' do
|
||||||
|
|
@ -702,6 +703,54 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
|
||||||
it { is_expected.to include_module(Namespaces::Traversal::LinearScopes) }
|
it { is_expected.to include_module(Namespaces::Traversal::LinearScopes) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when feature flag require_organization is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(require_organization: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not require organization' do
|
||||||
|
namespace.organization = nil
|
||||||
|
|
||||||
|
expect(namespace.valid?).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when feature flag require_organization is enabled' do
|
||||||
|
it 'does require organization' do
|
||||||
|
namespace.organization = nil
|
||||||
|
|
||||||
|
Namespace.with_disabled_organization_validation do
|
||||||
|
expect(namespace.valid?).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.with_disabled_organization_validation', :request_store do
|
||||||
|
it 'does not require organization' do
|
||||||
|
namespace.organization = nil
|
||||||
|
|
||||||
|
Namespace.with_disabled_organization_validation do
|
||||||
|
expect(namespace.valid?).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with nested calls' do
|
||||||
|
it 'only last call will enable the validation' do
|
||||||
|
result = []
|
||||||
|
Namespace.with_disabled_organization_validation do
|
||||||
|
result << described_class.new.require_organization?
|
||||||
|
Namespace.with_disabled_organization_validation do
|
||||||
|
result << described_class.new.require_organization?
|
||||||
|
end
|
||||||
|
result << described_class.new.require_organization?
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(result.any?(true)).to be false
|
||||||
|
expect(described_class.new.require_organization?).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#traversal_ids' do
|
describe '#traversal_ids' do
|
||||||
let(:namespace) { build(:group) }
|
let(:namespace) { build(:group) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Namespaces::ProjectNamespace, type: :model do
|
RSpec.describe Namespaces::ProjectNamespace, type: :model, feature_category: :groups_and_projects do
|
||||||
let_it_be(:organization) { create(:organization) }
|
let_it_be(:organization) { create(:organization) }
|
||||||
|
|
||||||
describe 'relationships' do
|
describe 'relationships' do
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ RSpec.describe Preloaders::ProjectPolicyPreloader do
|
||||||
control = ActiveRecord::QueryRecorder.new { authorize_all_projects(user) }
|
control = ActiveRecord::QueryRecorder.new { authorize_all_projects(user) }
|
||||||
|
|
||||||
new_project1 = create(:project, :private, maintainers: user)
|
new_project1 = create(:project, :private, maintainers: user)
|
||||||
new_project2 = create(:project, :private, namespace: root_parent)
|
new_project2 = create(:project, :private, namespace: root_parent, maintainers: user)
|
||||||
|
|
||||||
another_root = create(:group, :private, name: 'root-3', path: 'root-3')
|
another_root = create(:group, :private, name: 'root-3', path: 'root-3')
|
||||||
new_project3 = create(:project, :private, namespace: another_root, maintainers: user)
|
new_project3 = create(:project, :private, namespace: another_root, maintainers: user)
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ RSpec.describe 'getting merge request listings nested in a project', feature_cat
|
||||||
# We cannot disable SQL query limiting here, since the transaction does not
|
# We cannot disable SQL query limiting here, since the transaction does not
|
||||||
# begin until we enter the controller.
|
# begin until we enter the controller.
|
||||||
headers = {
|
headers = {
|
||||||
'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/322979'
|
'X-GITLAB-DISABLE-SQL-QUERY-LIMIT' => 'https://gitlab.com/gitlab-org/gitlab/-/issues/469250;205'
|
||||||
}
|
}
|
||||||
|
|
||||||
post_graphql(query, current_user: current_user, headers: headers)
|
post_graphql(query, current_user: current_user, headers: headers)
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ RSpec.describe API::ProjectImport, :aggregate_failures, feature_category: :impor
|
||||||
it 'executes a limited number of queries', :use_clean_rails_redis_caching do
|
it 'executes a limited number of queries', :use_clean_rails_redis_caching do
|
||||||
control = ActiveRecord::QueryRecorder.new { perform_archive_upload }
|
control = ActiveRecord::QueryRecorder.new { perform_archive_upload }
|
||||||
|
|
||||||
expect(control.count).to be <= 114
|
expect(control.count).to be <= 115
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'schedules an import using a namespace' do
|
it 'schedules an import using a namespace' do
|
||||||
|
|
|
||||||
|
|
@ -700,15 +700,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re
|
||||||
describe 'recording the first reviewer assigned at timestamp' do
|
describe 'recording the first reviewer assigned at timestamp' do
|
||||||
subject(:metrics) { merge_request.reload.metrics }
|
subject(:metrics) { merge_request.reload.metrics }
|
||||||
|
|
||||||
context 'when store_first_reviewer_assignment_timestamp_in_metrics feature flag is off' do
|
|
||||||
it 'does not record anything' do
|
|
||||||
stub_feature_flags(store_first_reviewer_assignment_timestamp_in_metrics: false)
|
|
||||||
update_merge_request(reviewer_ids: [user2.id])
|
|
||||||
|
|
||||||
expect(metrics.reviewer_first_assigned_at).to eq(nil)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the current timestamp' do
|
it 'sets the current timestamp' do
|
||||||
freeze_time do
|
freeze_time do
|
||||||
update_merge_request(reviewer_ids: [user2.id])
|
update_merge_request(reviewer_ids: [user2.id])
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ RSpec.describe ResourceAccessTokens::CreateService, feature_category: :system_ac
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when resource organization is not set', :enable_admin_mode do
|
context 'when resource organization is not set', :enable_admin_mode do
|
||||||
let_it_be(:resource) { create(:project, :private, organization: nil) }
|
let_it_be(:resource) { create(:project, :private, organization_id: nil) }
|
||||||
let_it_be(:default_organization) { Organizations::Organization.default_organization }
|
let_it_be(:default_organization) { Organizations::Organization.default_organization }
|
||||||
let(:user) { create(:admin) }
|
let(:user) { create(:admin) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ RSpec.describe Users::RegistrationsBuildService, feature_category: :system_acces
|
||||||
it 'creates the user_detail record' do
|
it 'creates the user_detail record' do
|
||||||
user = service.execute
|
user = service.execute
|
||||||
|
|
||||||
expect { user.save! }.to change { UserDetail.count }.by(1)
|
expect { Namespace.with_disabled_organization_validation { user.save! } }.to change { UserDetail.count }.by(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,7 @@ RSpec.configure do |config|
|
||||||
config.include UserWithNamespaceShim
|
config.include UserWithNamespaceShim
|
||||||
config.include OrphanFinalArtifactsCleanupHelpers, :orphan_final_artifacts_cleanup
|
config.include OrphanFinalArtifactsCleanupHelpers, :orphan_final_artifacts_cleanup
|
||||||
config.include ClickHouseHelpers, :click_house
|
config.include ClickHouseHelpers, :click_house
|
||||||
|
config.include DisableNamespaceOrganizationValidationHelper
|
||||||
|
|
||||||
config.include_context 'when rendered has no HTML escapes', type: :view
|
config.include_context 'when rendered has no HTML escapes', type: :view
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
---
|
||||||
|
- ee/spec/controllers/ee/groups_controller_spec.rb
|
||||||
|
- ee/spec/controllers/ee/registrations_controller_spec.rb
|
||||||
|
- ee/spec/controllers/ee/omniauth_callbacks_controller_spec.rb
|
||||||
|
- ee/spec/controllers/groups/omniauth_callbacks_controller_spec.rb
|
||||||
|
- ee/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb
|
||||||
|
- ee/spec/controllers/registrations/groups_controller_spec.rb
|
||||||
|
- ee/spec/features/groups_spec.rb
|
||||||
|
- ee/spec/features/projects/settings/merge_requests_settings_spec.rb
|
||||||
|
- ee/spec/features/registrations/combined_registration_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/sso_signin_standard_flow_company_creating_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/standard_flow_company_creating_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/standard_flow_just_me_creating_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/standard_flow_just_me_importing_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/subscription_flow_company_paid_plan_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/subscription_flow_just_me_paid_plan_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/trial_flow_company_creating_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/trial_flow_company_importing_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/trial_flow_just_me_creating_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/saas/trial_flow_just_me_importing_project_spec.rb
|
||||||
|
- ee/spec/features/registrations/sign_up_with_trial_from_external_site_without_confirmation_spec.rb
|
||||||
|
- ee/spec/features/registrations/start_trial_from_external_site_without_confirmation_spec.rb
|
||||||
|
- ee/spec/features/subscriptions/subscription_flow_for_existing_user_with_eligible_group_spec.rb
|
||||||
|
- ee/spec/features/trials/saas/creation_with_multiple_existing_namespace_flow_spec.rb
|
||||||
|
- ee/spec/features/trials/saas/creation_with_no_existing_namespace_flow_spec.rb
|
||||||
|
- ee/spec/features/trials/saas/creation_with_one_existing_namespace_flow_spec.rb
|
||||||
|
- ee/spec/lib/gitlab/auth/group_saml/user_spec.rb
|
||||||
|
- ee/spec/lib/gitlab/auth/ldap/user_spec.rb
|
||||||
|
- ee/spec/lib/gitlab/auth/oidc/user_spec.rb
|
||||||
|
- ee/spec/lib/gitlab/auth/saml/user_spec.rb
|
||||||
|
- ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb
|
||||||
|
- ee/spec/lib/ee/gitlab/scim/group/provisioning_service_spec.rb
|
||||||
|
- ee/spec/services/ee/groups/create_service_spec.rb
|
||||||
|
- ee/spec/services/ee/users/create_service_spec.rb
|
||||||
|
- ee/spec/services/users/service_accounts/create_service_spec.rb
|
||||||
|
- ee/spec/services/epics/update_dates_service_spec.rb
|
||||||
|
- ee/spec/services/gitlab_subscriptions/trials/create_service_spec.rb
|
||||||
|
- ee/spec/services/registrations/import_namespace_create_service_spec.rb
|
||||||
|
- ee/spec/services/registrations/standard_namespace_create_service_spec.rb
|
||||||
|
- spec/controllers/admin/groups_controller_spec.rb
|
||||||
|
- spec/controllers/admin/users_controller_spec.rb
|
||||||
|
- spec/controllers/groups_controller_spec.rb
|
||||||
|
- spec/controllers/import/bitbucket_controller_spec.rb
|
||||||
|
- spec/controllers/omniauth_callbacks_controller_spec.rb
|
||||||
|
- spec/controllers/registrations_controller_spec.rb
|
||||||
|
- spec/features/admin/admin_groups_spec.rb
|
||||||
|
- spec/features/dashboard/group_spec.rb
|
||||||
|
- spec/features/file_uploads/group_import_spec.rb
|
||||||
|
- spec/features/groups/import_export/import_file_spec.rb
|
||||||
|
- spec/features/groups_spec.rb
|
||||||
|
- spec/frontend/fixtures/groups.rb
|
||||||
|
- spec/graphql/types/group_type_spec.rb
|
||||||
|
- spec/graphql/types/project_type_spec.rb
|
||||||
|
- spec/lib/gitlab/auth/atlassian/user_spec.rb
|
||||||
|
- spec/lib/gitlab/auth/ldap/user_spec.rb
|
||||||
|
- spec/lib/gitlab/auth/o_auth/user_spec.rb
|
||||||
|
- spec/lib/gitlab/auth/saml/user_spec.rb
|
||||||
|
- spec/lib/gitlab/import/placeholder_user_creator_spec.rb
|
||||||
|
- spec/lib/gitlab/import/source_user_mapper_spec.rb
|
||||||
|
- spec/lib/gitlab/seeders/ci/runner/runner_fleet_seeder_spec.rb
|
||||||
|
- spec/models/hooks/system_hook_spec.rb
|
||||||
|
- spec/requests/api/groups_spec.rb
|
||||||
|
- spec/requests/import/gitlab_groups_controller_spec.rb
|
||||||
|
- spec/services/users/create_service_spec.rb
|
||||||
|
- spec/services/users/registrations_build_service_spec.rb
|
||||||
|
- spec/services/groups/create_service_spec.rb
|
||||||
|
- spec/services/groups/nested_create_service_spec.rb
|
||||||
|
- spec/services/resource_access_tokens/create_service_spec.rb
|
||||||
|
- spec/tasks/gitlab/seed/runner_fleet_rake_spec.rb
|
||||||
|
- spec/tasks/gitlab/update_templates_rake_spec.rb
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module DisableNamespaceOrganizationValidationHelper
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
SPECS_FOR_CODE_TO_FIX = File.join(__dir__, 'disable_namespace_organization_validation.yml')
|
||||||
|
|
||||||
|
class << self
|
||||||
|
include Gitlab::Utils::StrongMemoize
|
||||||
|
|
||||||
|
def todo_list
|
||||||
|
YAML.load_file(SPECS_FOR_CODE_TO_FIX).filter_map { |path| full_path(path) } || []
|
||||||
|
end
|
||||||
|
strong_memoize_attr :todo_list
|
||||||
|
|
||||||
|
def full_path(path)
|
||||||
|
return unless File.exist?(path)
|
||||||
|
|
||||||
|
Pathname.new(path).realpath.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
included do
|
||||||
|
spec_file = Pathname.new(example.metadata[:example_group][:file_path]).realpath.to_s
|
||||||
|
|
||||||
|
if spec_file.in?(DisableNamespaceOrganizationValidationHelper.todo_list)
|
||||||
|
around do |example|
|
||||||
|
::Gitlab::SafeRequestStore.ensure_request_store { example.run }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in New Issue