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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-05 21:17:47 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-05 21:17:47 +0300
commitbc4cd6ffb93ae695f20ea54f4e4803d50c78a69e (patch)
tree2364d0f880af998b70356628f79cda64f13a11e7 /app
parent6634288474d2a83cac7b4205f3ffc736cc6b36db (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/environments/mount_show.js2
-rw-r--r--app/assets/javascripts/graphql_shared/utils.js25
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue47
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js18
-rw-r--r--app/assets/javascripts/security_configuration/index.js6
-rw-r--r--app/assets/javascripts/security_configuration/utils.js8
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/constants.js1
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue42
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue7
-rw-r--r--app/assets/stylesheets/page_bundles/tree.scss7
-rw-r--r--app/assets/stylesheets/themes/dark_mode_overrides.scss5
-rw-r--r--app/controllers/projects/merge_requests_controller.rb14
-rw-r--r--app/helpers/sessions_helper.rb4
-rw-r--r--app/models/application_setting.rb3
-rw-r--r--app/models/bulk_imports/configuration.rb2
-rw-r--r--app/models/bulk_imports/entity.rb27
-rw-r--r--app/models/clusters/kubernetes_namespace.rb6
-rw-r--r--app/models/container_repository.rb17
-rw-r--r--app/models/cycle_analytics/project_level_stage_adapter.rb12
-rw-r--r--app/models/deployment.rb8
-rw-r--r--app/models/design_management/design.rb4
-rw-r--r--app/models/design_management/version.rb8
-rw-r--r--app/models/diff_discussion.rb14
-rw-r--r--app/models/diff_viewer/base.rb5
-rw-r--r--app/models/integrations/prometheus.rb7
-rw-r--r--app/models/organization.rb6
-rw-r--r--app/models/project.rb6
-rw-r--r--app/models/user.rb7
-rw-r--r--app/services/members/destroy_service.rb45
-rw-r--r--app/views/admin/sessions/_signin_box.html.haml2
-rw-r--r--app/views/admin/sessions/new.html.haml2
-rw-r--r--app/views/admin/sessions/two_factor.html.haml2
-rw-r--r--app/views/authentication/_authenticate.html.haml2
-rw-r--r--app/views/devise/sessions/_new_base.html.haml16
-rw-r--r--app/views/devise/sessions/_new_crowd.html.haml2
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml4
-rw-r--r--app/views/devise/sessions/two_factor.html.haml5
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml4
-rw-r--r--app/views/projects/_self_monitoring_deprecation_notice.html.haml13
-rw-r--r--app/views/projects/empty.html.haml1
-rw-r--r--app/views/projects/show.html.haml1
41 files changed, 180 insertions, 237 deletions
diff --git a/app/assets/javascripts/environments/mount_show.js b/app/assets/javascripts/environments/mount_show.js
index 364f68cefb7..cc13a237aca 100644
--- a/app/assets/javascripts/environments/mount_show.js
+++ b/app/assets/javascripts/environments/mount_show.js
@@ -94,7 +94,7 @@ export const initPage = async () => {
router,
provide: {
projectPath: dataSet.projectFullPath,
- graphqlEtagKey: dataSet.graphqlEtagPath,
+ graphqlEtagKey: dataSet.graphqlEtagKey,
},
render(createElement) {
return createElement('router-view');
diff --git a/app/assets/javascripts/graphql_shared/utils.js b/app/assets/javascripts/graphql_shared/utils.js
index 198d9f980f0..6a64e8a2fa8 100644
--- a/app/assets/javascripts/graphql_shared/utils.js
+++ b/app/assets/javascripts/graphql_shared/utils.js
@@ -16,7 +16,10 @@ export const isGid = (id) => {
return false;
};
-const parseGid = (gid) => parseInt(`${gid}`.replace(/gid:\/\/gitlab\/.*\//g, ''), 10);
+const parseGid = (gid) => {
+ const [type, id] = `${gid}`.replace(/gid:\/\/gitlab\//g, '').split('/');
+ return { type, id };
+};
/**
* Ids generated by GraphQL endpoints are usually in the format
@@ -27,8 +30,24 @@ const parseGid = (gid) => parseInt(`${gid}`.replace(/gid:\/\/gitlab\/.*\//g, '')
* @returns {Number}
*/
export const getIdFromGraphQLId = (gid = '') => {
- const parsedGid = parseGid(gid);
- return Number.isInteger(parsedGid) ? parsedGid : null;
+ const rawId = isGid(gid) ? parseGid(gid).id : gid;
+ const id = parseInt(rawId, 10);
+ return Number.isInteger(id) ? id : null;
+};
+
+/**
+ * Ids generated by GraphQL endpoints are usually in the format
+ * gid://gitlab/Environments/123. This method extracts Type string
+ * from the Id path
+ *
+ * @param {String} gid GraphQL global ID
+ * @returns {String}
+ */
+export const getTypeFromGraphQLId = (gid = '') => {
+ if (!isGid(gid)) return null;
+
+ const { type } = parseGid(gid);
+ return type || null;
};
export const MutationOperationMode = {
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
index 66b8db1f764..d57b3fda342 100644
--- a/app/assets/javascripts/security_configuration/components/app.vue
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -12,7 +12,6 @@ import FeatureCard from './feature_card.vue';
import TrainingProviderList from './training_provider_list.vue';
export const i18n = {
- compliance: s__('SecurityConfiguration|Compliance'),
configurationHistory: s__('SecurityConfiguration|Configuration history'),
securityTesting: s__('SecurityConfiguration|Security testing'),
latestPipelineDescription: s__(
@@ -59,10 +58,6 @@ export default {
type: Array,
required: true,
},
- augmentedComplianceFeatures: {
- type: Array,
- required: true,
- },
gitlabCiPresent: {
type: Boolean,
required: false,
@@ -101,9 +96,7 @@ export default {
},
computed: {
canUpgrade() {
- return [...this.augmentedSecurityFeatures, ...this.augmentedComplianceFeatures].some(
- ({ available }) => !available,
- );
+ return [...this.augmentedSecurityFeatures].some(({ available }) => !available);
},
canViewCiHistory() {
return Boolean(this.gitlabCiPresent && this.gitlabCiHistoryPath);
@@ -226,44 +219,6 @@ export default {
</section-layout>
</gl-tab>
<gl-tab
- data-testid="compliance-testing-tab"
- :title="$options.i18n.compliance"
- query-param-value="compliance-testing"
- >
- <section-layout :heading="$options.i18n.compliance">
- <template #description>
- <p>
- <span data-testid="latest-pipeline-info-compliance">
- <gl-sprintf
- v-if="latestPipelinePath"
- :message="$options.i18n.latestPipelineDescription"
- >
- <template #link="{ content }">
- <gl-link :href="latestPipelinePath">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </span>
-
- {{ $options.i18n.description }}
- </p>
- <p v-if="canViewCiHistory">
- <gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">{{
- $options.i18n.configurationHistory
- }}</gl-link>
- </p>
- </template>
- <template #features>
- <feature-card
- v-for="feature in augmentedComplianceFeatures"
- :key="feature.type"
- :feature="feature"
- class="gl-mb-6"
- @error="onError"
- />
- </template>
- </section-layout>
- </gl-tab>
- <gl-tab
data-testid="vulnerability-management-tab"
:title="$options.i18n.vulnerabilityManagement"
query-param-value="vulnerability-management"
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index d46e9983a44..3bf0401ef5e 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -13,7 +13,6 @@ import {
REPORT_TYPE_COVERAGE_FUZZING,
REPORT_TYPE_CORPUS_MANAGEMENT,
REPORT_TYPE_API_FUZZING,
- REPORT_TYPE_LICENSE_COMPLIANCE,
} from '~/vue_shared/security_reports/constants';
import kontraLogo from 'images/vulnerability/kontra-logo.svg';
@@ -150,14 +149,6 @@ export const API_FUZZING_NAME = __('API Fuzzing');
export const API_FUZZING_DESCRIPTION = __('Find bugs in your code with API fuzzing.');
export const API_FUZZING_HELP_PATH = helpPagePath('user/application_security/api_fuzzing/index');
-export const LICENSE_COMPLIANCE_NAME = __('License Compliance');
-export const LICENSE_COMPLIANCE_DESCRIPTION = __(
- 'Search your project dependencies for their licenses and apply policies.',
-);
-export const LICENSE_COMPLIANCE_HELP_PATH = helpPagePath(
- 'user/compliance/license_compliance/index',
-);
-
export const CLUSTER_IMAGE_SCANNING_NAME = s__('ciReport|Cluster Image Scanning');
export const SCANNER_NAMES_MAP = {
@@ -273,15 +264,6 @@ export const securityFeatures = [
},
];
-export const complianceFeatures = [
- {
- name: LICENSE_COMPLIANCE_NAME,
- description: LICENSE_COMPLIANCE_DESCRIPTION,
- helpPath: LICENSE_COMPLIANCE_HELP_PATH,
- type: REPORT_TYPE_LICENSE_COMPLIANCE,
- },
-];
-
export const featureToMutationMap = {
[REPORT_TYPE_SAST]: {
mutationId: 'configureSast',
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
index 637d510e684..aa3c9c87622 100644
--- a/app/assets/javascripts/security_configuration/index.js
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -3,7 +3,7 @@ import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBooleanDataAttributes } from '~/lib/utils/dom_utils';
import SecurityConfigurationApp from './components/app.vue';
-import { securityFeatures, complianceFeatures } from './components/constants';
+import { securityFeatures } from './components/constants';
import { augmentFeatures } from './utils';
export const initSecurityConfiguration = (el) => {
@@ -28,9 +28,8 @@ export const initSecurityConfiguration = (el) => {
vulnerabilityTrainingDocsPath,
} = el.dataset;
- const { augmentedSecurityFeatures, augmentedComplianceFeatures } = augmentFeatures(
+ const { augmentedSecurityFeatures } = augmentFeatures(
securityFeatures,
- complianceFeatures,
features ? JSON.parse(features) : [],
);
@@ -48,7 +47,6 @@ export const initSecurityConfiguration = (el) => {
render(createElement) {
return createElement(SecurityConfigurationApp, {
props: {
- augmentedComplianceFeatures,
augmentedSecurityFeatures,
latestPipelinePath,
gitlabCiHistoryPath,
diff --git a/app/assets/javascripts/security_configuration/utils.js b/app/assets/javascripts/security_configuration/utils.js
index df23698ba7e..72e6d870e13 100644
--- a/app/assets/javascripts/security_configuration/utils.js
+++ b/app/assets/javascripts/security_configuration/utils.js
@@ -2,19 +2,18 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
/**
- * This function takes in 3 arrays of objects, securityFeatures, complianceFeatures and features.
- * securityFeatures and complianceFeatures are static arrays living in the constants.
+ * This function takes in 3 arrays of objects, securityFeatures and features.
+ * securityFeatures are static arrays living in the constants.
* features is dynamic and coming from the backend.
* This function builds a superset of those arrays.
* It looks for matching keys within the dynamic and the static arrays
* and will enrich the objects with the available static data.
* @param [{}] securityFeatures
- * @param [{}] complianceFeatures
* @param [{}] features
* @returns {Object} Object with enriched features from constants divided into Security and Compliance Features
*/
-export const augmentFeatures = (securityFeatures, complianceFeatures, features = []) => {
+export const augmentFeatures = (securityFeatures, features = []) => {
const featuresByType = features.reduce((acc, feature) => {
acc[feature.type] = convertObjectPropsToCamelCase(feature, { deep: true });
return acc;
@@ -39,7 +38,6 @@ export const augmentFeatures = (securityFeatures, complianceFeatures, features =
return {
augmentedSecurityFeatures: securityFeatures.map((feature) => augmentFeature(feature)),
- augmentedComplianceFeatures: complianceFeatures.map((feature) => augmentFeature(feature)),
};
};
diff --git a/app/assets/javascripts/vue_shared/security_reports/constants.js b/app/assets/javascripts/vue_shared/security_reports/constants.js
index 8b523645973..a1d75e08be9 100644
--- a/app/assets/javascripts/vue_shared/security_reports/constants.js
+++ b/app/assets/javascripts/vue_shared/security_reports/constants.js
@@ -27,7 +27,6 @@ export const REPORT_TYPE_CONTAINER_SCANNING = 'container_scanning';
export const REPORT_TYPE_CLUSTER_IMAGE_SCANNING = 'cluster_image_scanning';
export const REPORT_TYPE_COVERAGE_FUZZING = 'coverage_fuzzing';
export const REPORT_TYPE_CORPUS_MANAGEMENT = 'corpus_management';
-export const REPORT_TYPE_LICENSE_COMPLIANCE = 'license_scanning';
export const REPORT_TYPE_API_FUZZING = 'api_fuzzing';
export const REPORT_TYPE_MANUALLY_ADDED = 'generic';
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index ddf7c789c09..ef99001c0e8 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -46,7 +46,8 @@ import workItemAssigneesSubscription from '../graphql/work_item_assignees.subscr
import workItemMilestoneSubscription from '../graphql/work_item_milestone.subscription.graphql';
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
import updateWorkItemTaskMutation from '../graphql/update_work_item_task.mutation.graphql';
-import { findHierarchyWidgetChildren, getWorkItemQuery } from '../utils';
+import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
+import { findHierarchyWidgetChildren } from '../utils';
import WorkItemTree from './work_item_links/work_item_tree.vue';
import WorkItemActions from './work_item_actions.vue';
@@ -137,18 +138,15 @@ export default {
},
apollo: {
workItem: {
- query() {
- return getWorkItemQuery(this.fetchByIid);
- },
+ query: workItemByIidQuery,
variables() {
return this.queryVariables;
},
skip() {
- return !this.workItemId && !this.workItemIid;
+ return !this.workItemIid;
},
update(data) {
- const workItem = this.fetchByIid ? data.workspace.workItems.nodes[0] : data.workItem;
- return workItem ?? {};
+ return data.workspace.workItems.nodes[0] ?? {};
},
error() {
this.setEmptyState();
@@ -316,18 +314,11 @@ export default {
workItemNotes() {
return this.isWidgetPresent(WIDGET_TYPE_NOTES);
},
- fetchByIid() {
- return true;
- },
queryVariables() {
- return this.fetchByIid
- ? {
- fullPath: this.fullPath,
- iid: this.workItemIid,
- }
- : {
- id: this.workItemId,
- };
+ return {
+ fullPath: this.fullPath,
+ iid: this.workItemIid,
+ };
},
children() {
return this.workItem ? findHierarchyWidgetChildren(this.workItem) : [];
@@ -408,14 +399,12 @@ export default {
},
toggleChildFromCache(workItem, childId, store) {
const sourceData = store.readQuery({
- query: getWorkItemQuery(this.fetchByIid),
+ query: workItemByIidQuery,
variables: this.queryVariables,
});
const newData = produce(sourceData, (draftState) => {
- const widgets = this.fetchByIid
- ? draftState.workspace.workItems.nodes[0].widgets
- : draftState.workItem.widgets;
+ const { widgets } = draftState.workspace.workItems.nodes[0];
const widgetHierarchy = widgets.find((widget) => widget.type === WIDGET_TYPE_HIERARCHY);
const index = widgetHierarchy.children.nodes.findIndex((child) => child.id === childId);
@@ -428,7 +417,7 @@ export default {
});
store.writeQuery({
- query: getWorkItemQuery(this.fetchByIid),
+ query: workItemByIidQuery,
variables: this.queryVariables,
data: newData,
});
@@ -475,12 +464,8 @@ export default {
this.$emit('has-notes');
},
updateUrl(modalWorkItem) {
- const params = this.fetchByIid
- ? { work_item_iid: modalWorkItem?.iid }
- : { work_item_id: getIdFromGraphQLId(modalWorkItem?.id) };
-
updateHistory({
- url: setUrlParams(params),
+ url: setUrlParams({ work_item_iid: modalWorkItem?.iid }),
replace: true,
});
},
@@ -722,7 +707,6 @@ export default {
:can-update="canUpdate"
:project-path="fullPath"
:confidential="workItem.confidential"
- :fetch-by-iid="fetchByIid"
@addWorkItemChild="addChild"
@removeChild="removeChild"
@show-modal="openInModal"
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue
index 3e5d9453fef..4dcc4d51957 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue
@@ -61,11 +61,6 @@ export default {
type: String,
required: true,
},
- fetchByIid: {
- type: Boolean,
- required: false,
- default: false,
- },
},
data() {
return {
@@ -174,7 +169,7 @@ export default {
:work-item-id="workItemId"
:work-item-iid="workItemIid"
:work-item-type="workItemType"
- :fetch-by-iid="fetchByIid"
+ fetch-by-iid
@removeChild="$emit('removeChild', $event)"
@show-modal="showModal"
/>
diff --git a/app/assets/stylesheets/page_bundles/tree.scss b/app/assets/stylesheets/page_bundles/tree.scss
index 9d13ccc676d..a13b8704095 100644
--- a/app/assets/stylesheets/page_bundles/tree.scss
+++ b/app/assets/stylesheets/page_bundles/tree.scss
@@ -219,10 +219,3 @@
width: calc(100% + 24px);
margin: -28px -12px 0;
}
-
-.ai-genie-chat-message {
- pre,
- code {
- @include gl-font-sm;
- }
-}
diff --git a/app/assets/stylesheets/themes/dark_mode_overrides.scss b/app/assets/stylesheets/themes/dark_mode_overrides.scss
index 619336686e8..3a18f735217 100644
--- a/app/assets/stylesheets/themes/dark_mode_overrides.scss
+++ b/app/assets/stylesheets/themes/dark_mode_overrides.scss
@@ -305,3 +305,8 @@ body.gl-dark {
// lightens chat bubble in darkmode as $gray-50 matches drawer background. See tanuki_bot_chat.scss
background-color: $gray-100;
}
+
+.ai-genie-chat,
+.ai-genie-chat .gl-form-input {
+ background-color: $gray-10;
+}
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index d967aa89eb7..dbcbd2467b6 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -51,7 +51,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:code_quality_inline_drawer, project)
push_frontend_feature_flag(:hide_create_issue_resolve_all, project)
push_frontend_feature_flag(:auto_merge_labels_mr_widget, project)
- push_frontend_feature_flag(:summarize_my_code_review, current_user)
+ push_force_frontend_feature_flag(:summarize_my_code_review, summarize_my_code_review_enabled?)
push_frontend_feature_flag(:mr_activity_filters, current_user)
end
@@ -603,6 +603,18 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
Date.strptime(date, "%Y-%m-%d")&.to_time&.to_i if date
rescue Date::Error, TypeError
end
+
+ def summarize_my_code_review_enabled?
+ namespace = project&.group&.root_ancestor
+ return false if namespace.nil?
+
+ Feature.enabled?(:summarize_my_code_review, current_user) &&
+ namespace.group_namespace? &&
+ namespace.licensed_feature_available?(:summarize_my_mr_code_review) &&
+ namespace.experiment_features_enabled &&
+ namespace.third_party_ai_features_enabled &&
+ merge_request.send_to_ai?
+ end
end
Projects::MergeRequestsController.prepend_mod_with('Projects::MergeRequestsController')
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
index 8251e1cba8a..9ef347fff16 100644
--- a/app/helpers/sessions_helper.rb
+++ b/app/helpers/sessions_helper.rb
@@ -48,4 +48,8 @@ module SessionsHelper
# Moved to Gitlab::Utils::Email in 15.9
Gitlab::Utils::Email.obfuscated_email(email)
end
+
+ def remember_me_enabled?
+ Gitlab::CurrentSettings.remember_me_enabled?
+ end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index aba8727c030..8f57d73a6f4 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -38,10 +38,7 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord
add_authentication_token_field :static_objects_external_storage_auth_token, encrypted: :required
add_authentication_token_field :error_tracking_access_token, encrypted: :required
- belongs_to :self_monitoring_project, class_name: "Project", foreign_key: :instance_administration_project_id,
- inverse_of: :application_setting
belongs_to :push_rule
- alias_attribute :self_monitoring_project_id, :instance_administration_project_id
belongs_to :instance_group, class_name: "Group", foreign_key: :instance_administrators_group_id,
inverse_of: :application_setting
diff --git a/app/models/bulk_imports/configuration.rb b/app/models/bulk_imports/configuration.rb
index 3b263ed0340..6d9f598583e 100644
--- a/app/models/bulk_imports/configuration.rb
+++ b/app/models/bulk_imports/configuration.rb
@@ -9,7 +9,7 @@ class BulkImports::Configuration < ApplicationRecord
validates :url, :access_token, length: { maximum: 255 }, presence: true
validates :url, public_url: { schemes: %w[http https], enforce_sanitization: true, ascii_only: true },
- allow_nil: true
+ allow_nil: true
attr_encrypted :url,
key: Settings.attr_encrypted_db_key_base_32,
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index b3540917197..94e4a8165eb 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -41,22 +41,14 @@ class BulkImports::Entity < ApplicationRecord
validates :project, absence: true, if: :group
validates :group, absence: true, if: :project
validates :source_type, presence: true
- validates :source_full_path,
- presence: true,
- format: { with: Gitlab::Regex.bulk_import_source_full_path_regex,
- message: Gitlab::Regex.bulk_import_source_full_path_regex_message }
+ validates :source_full_path, presence: true, format: {
+ with: Gitlab::Regex.bulk_import_source_full_path_regex,
+ message: Gitlab::Regex.bulk_import_source_full_path_regex_message
+ }
- validates :destination_name,
- presence: true,
- if: -> { group || project }
-
- validates :destination_namespace,
- exclusion: [nil],
- if: :group
-
- validates :destination_namespace,
- presence: true,
- if: :project?
+ validates :destination_name, presence: true, if: -> { group || project }
+ validates :destination_namespace, exclusion: [nil], if: :group
+ validates :destination_namespace, presence: true, if: :project?
validate :validate_parent_is_a_group, if: :parent
validate :validate_imported_entity_type
@@ -72,9 +64,8 @@ class BulkImports::Entity < ApplicationRecord
alias_attribute :destination_slug, :destination_name
- delegate :default_project_visibility,
- :default_group_visibility,
- to: :'Gitlab::CurrentSettings.current_application_settings'
+ delegate :default_project_visibility, :default_group_visibility,
+ to: :'Gitlab::CurrentSettings.current_application_settings'
state_machine :status, initial: :created do
state :created, value: 0
diff --git a/app/models/clusters/kubernetes_namespace.rb b/app/models/clusters/kubernetes_namespace.rb
index 42332bdc193..dfb5c4cc5eb 100644
--- a/app/models/clusters/kubernetes_namespace.rb
+++ b/app/models/clusters/kubernetes_namespace.rb
@@ -22,9 +22,9 @@ module Clusters
delegate :api_url, to: :platform_kubernetes, allow_nil: true
attr_encrypted :service_account_token,
- mode: :per_attribute_iv,
- key: Settings.attr_encrypted_db_key_base_truncated,
- algorithm: 'aes-256-cbc'
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-cbc'
scope :has_service_account_token, -> { where.not(encrypted_service_account_token: nil) }
scope :with_environment_name, -> (name) { joins(:environment).where(environments: { name: name }) }
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index 62b6effeb89..0f0abeae795 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -38,8 +38,8 @@ class ContainerRepository < ApplicationRecord
validates :migration_aborted_in_state, inclusion: { in: ABORTABLE_MIGRATION_STATES }, allow_nil: true
validates :migration_retries_count, presence: true,
- numericality: { greater_than_or_equal_to: 0 },
- allow_nil: false
+ numericality: { greater_than_or_equal_to: 0 },
+ allow_nil: false
enum status: { delete_scheduled: 0, delete_failed: 1, delete_ongoing: 2 }
enum expiration_policy_cleanup_status: { cleanup_unscheduled: 0, cleanup_scheduled: 1, cleanup_unfinished: 2, cleanup_ongoing: 3 }
@@ -124,9 +124,7 @@ class ContainerRepository < ApplicationRecord
state :import_done
state :import_skipped do
- validates :migration_skipped_reason,
- :migration_skipped_at,
- presence: true
+ validates :migration_skipped_reason, :migration_skipped_at, presence: true
end
state :import_aborted do
@@ -603,8 +601,7 @@ class ContainerRepository < ApplicationRecord
end
def self.build_from_path(path)
- self.new(project: path.repository_project,
- name: path.repository_name)
+ self.new(project: path.repository_project, name: path.repository_name)
end
def self.find_or_create_from_path(path)
@@ -622,13 +619,11 @@ class ContainerRepository < ApplicationRecord
end
def self.find_by_path!(path)
- self.find_by!(project: path.repository_project,
- name: path.repository_name)
+ self.find_by!(project: path.repository_project, name: path.repository_name)
end
def self.find_by_path(path)
- self.find_by(project: path.repository_project,
- name: path.repository_name)
+ self.find_by(project: path.repository_project, name: path.repository_name)
end
private
diff --git a/app/models/cycle_analytics/project_level_stage_adapter.rb b/app/models/cycle_analytics/project_level_stage_adapter.rb
index 9b9c0822f63..ae21a4a6bfe 100644
--- a/app/models/cycle_analytics/project_level_stage_adapter.rb
+++ b/app/models/cycle_analytics/project_level_stage_adapter.rb
@@ -16,12 +16,12 @@ module CycleAnalytics
presenter = Analytics::CycleAnalytics::StagePresenter.new(stage)
serializer.new.represent(ProjectLevelStage.new(
- title: presenter.title,
- description: presenter.description,
- legend: presenter.legend,
- name: stage.name,
- project_median: median
- ))
+ title: presenter.title,
+ description: presenter.description,
+ legend: presenter.legend,
+ name: stage.name,
+ project_median: median
+ ))
end
# rubocop: enable CodeReuse/Presenter
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index f8873d388a3..f3ee21ea4e0 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -372,9 +372,11 @@ class Deployment < ApplicationRecord
# i.e.:
# MergeRequest.select(1, 2).to_sql #=> SELECT 1, 2 FROM "merge_requests"
# MergeRequest.select(1, 1).to_sql #=> SELECT 1 FROM "merge_requests"
- select = relation.select('merge_requests.id',
- "#{id} as deployment_id",
- "#{environment_id} as environment_id").to_sql
+ select = relation.select(
+ 'merge_requests.id',
+ "#{id} as deployment_id",
+ "#{environment_id} as environment_id"
+ ).to_sql
# We don't use `ApplicationRecord.legacy_bulk_insert` here so that we don't need to
# first pluck lots of IDs into memory.
diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb
index cb6d4e72c80..505935bb230 100644
--- a/app/models/design_management/design.rb
+++ b/app/models/design_management/design.rb
@@ -31,8 +31,8 @@ module DesignManagement
has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_internal_id :iid, scope: :project, presence: true,
- hook_names: %i[create update], # Deal with old records
- track_if: -> { !importing? }
+ hook_names: %i[create update], # Deal with old records
+ track_if: -> { !importing? }
validates :project, :filename, presence: true
validates :issue, presence: true, unless: :importing?
diff --git a/app/models/design_management/version.rb b/app/models/design_management/version.rb
index 5819404efb9..dd6812f0eac 100644
--- a/app/models/design_management/version.rb
+++ b/app/models/design_management/version.rb
@@ -36,10 +36,10 @@ module DesignManagement
belongs_to :author, class_name: 'User'
has_many :actions
has_many :designs,
- through: :actions,
- class_name: "DesignManagement::Design",
- source: :design,
- inverse_of: :versions
+ through: :actions,
+ class_name: "DesignManagement::Design",
+ source: :design,
+ inverse_of: :versions
validates :designs, presence: true, unless: :importing?
validates :sha, presence: true
diff --git a/app/models/diff_discussion.rb b/app/models/diff_discussion.rb
index 041ec98ffc9..e2ee951522d 100644
--- a/app/models/diff_discussion.rb
+++ b/app/models/diff_discussion.rb
@@ -10,13 +10,13 @@ class DiffDiscussion < Discussion
DiffNote
end
- delegate :position,
- :original_position,
- :change_position,
- :diff_note_positions,
- :on_text?,
- :on_image?,
- to: :first_note
+ delegate :position,
+ :original_position,
+ :change_position,
+ :diff_note_positions,
+ :on_text?,
+ :on_image?,
+ to: :first_note
def legacy_diff_discussion?
false
diff --git a/app/models/diff_viewer/base.rb b/app/models/diff_viewer/base.rb
index 75aa51348c8..05552e83700 100644
--- a/app/models/diff_viewer/base.rb
+++ b/app/models/diff_viewer/base.rb
@@ -101,8 +101,9 @@ module DiffViewer
def render_error_options
options = []
- blob_url = Gitlab::Routing.url_helpers.project_blob_path(diff_file.repository.project,
- File.join(diff_file.content_sha, diff_file.file_path))
+ blob_url = Gitlab::Routing.url_helpers.project_blob_path(
+ diff_file.repository.project, File.join(diff_file.content_sha, diff_file.file_path)
+ )
options << ActionController::Base.helpers.link_to(_('view the blob'), blob_url)
options
diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb
index 2f0995e9ab0..b148539dec6 100644
--- a/app/models/integrations/prometheus.rb
+++ b/app/models/integrations/prometheus.rb
@@ -99,8 +99,7 @@ module Integrations
end
def allow_local_api_url?
- allow_local_requests_from_web_hooks_and_services? ||
- (self_monitoring_project? && internal_prometheus_url?)
+ allow_local_requests_from_web_hooks_and_services? || internal_prometheus_url?
end
def configured?
@@ -127,10 +126,6 @@ module Integrations
delegate :allow_local_requests_from_web_hooks_and_services?, to: :current_settings, private: true
- def self_monitoring_project?
- project && project.id == current_settings.self_monitoring_project_id
- end
-
def internal_prometheus_url?
api_url.present? && api_url == ::Gitlab::Prometheus::Internal.uri
end
diff --git a/app/models/organization.rb b/app/models/organization.rb
new file mode 100644
index 00000000000..73a7e84305f
--- /dev/null
+++ b/app/models/organization.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+# rubocop: disable Gitlab/NamespacedClass
+class Organization < ApplicationRecord
+end
+# rubocop: enable Gitlab/NamespacedClass
diff --git a/app/models/project.rb b/app/models/project.rb
index 8f9b7042a0e..16719316ede 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -173,7 +173,7 @@ class Project < ApplicationRecord
has_one :last_event, -> { order 'events.created_at DESC' }, class_name: 'Event'
has_many :boards
- has_many :application_setting, inverse_of: :self_monitoring_project
+ has_many :application_setting
def self.integration_association_name(name)
"#{name}_integration"
@@ -2857,10 +2857,6 @@ class Project < ApplicationRecord
Feature.enabled?(:group_protected_branches, group) || Feature.enabled?(:allow_protected_branches_for_group, group)
end
- def self_monitoring?
- Gitlab::CurrentSettings.self_monitoring_project_id == id
- end
-
def deploy_token_create_url(opts = {})
Gitlab::Routing.url_helpers.create_deploy_token_project_settings_repository_path(self, opts)
end
diff --git a/app/models/user.rb b/app/models/user.rb
index a5d8541c8ef..f0797e41c12 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1077,6 +1077,13 @@ class User < ApplicationRecord
update(otp_backup_codes: nil)
end
+ # Returns true if the user is allowed to sign in with either otp or recovery codes.
+ def sign_in_with_codes_allowed?
+ return two_factor_otp_enabled? unless Feature.enabled?(:webauthn_without_totp)
+
+ two_factor_enabled?
+ end
+
def two_factor_enabled?
two_factor_otp_enabled? || two_factor_webauthn_enabled?
end
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index dd84b890385..0f195663a61 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -15,18 +15,39 @@ module Members
@skip_auth = skip_authorization
if a_group_owner?(member)
- process_destroy_of_group_owner_member(member, skip_subresources, unassign_issuables)
+ process_destroy_of_group_owner_member(member, skip_subresources)
else
destroy_member(member)
- destroy_data_related_to_member(member, skip_subresources, unassign_issuables)
+ destroy_data_related_to_member(member, skip_subresources)
end
+ enqueue_jobs_that_needs_to_be_run_only_once_per_hierarchy(member, unassign_issuables)
+
member
end
+ # We use this to mark recursive calls made to this service from within the same service.
+ # We do this so as to help us run some tasks that needs to be run only once per hierarchy, and not recursively.
+ def mark_as_recursive_call
+ @recursive_call = true
+ end
+
private
- def process_destroy_of_group_owner_member(member, skip_subresources, unassign_issuables)
+ # These actions need to be executed only once per hierarchy because the underlying services
+ # apply these actions to the entire hierarchy anyway, so there is no need to execute them recursively.
+ def enqueue_jobs_that_needs_to_be_run_only_once_per_hierarchy(member, unassign_issuables)
+ return if recursive_call?
+
+ enqueue_delete_todos(member)
+ enqueue_unassign_issuables(member) if unassign_issuables
+ end
+
+ def recursive_call?
+ @recursive_call == true
+ end
+
+ def process_destroy_of_group_owner_member(member, skip_subresources)
# Deleting 2 different group owners via the API in quick succession could lead to
# wrong results for the `last_owner?` check due to race conditions. To prevent this
# we wrap both the last_owner? check and the deletes of owners within a lock.
@@ -40,23 +61,23 @@ module Members
end
# deletion of related data does not have to be within the lock.
- destroy_data_related_to_member(member, skip_subresources, unassign_issuables) unless last_group_owner
+ destroy_data_related_to_member(member, skip_subresources) unless last_group_owner
end
def destroy_member(member)
member.destroy
end
- def destroy_data_related_to_member(member, skip_subresources, unassign_issuables)
+ def destroy_data_related_to_member(member, skip_subresources)
member.user&.invalidate_cache_counts
- delete_member_associations(member, skip_subresources, unassign_issuables)
+ delete_member_associations(member, skip_subresources)
end
def a_group_owner?(member)
member.is_a?(GroupMember) && member.owner?
end
- def delete_member_associations(member, skip_subresources, unassign_issuables)
+ def delete_member_associations(member, skip_subresources)
if member.request? && member.user != current_user
notification_service.decline_access_request(member)
end
@@ -64,8 +85,6 @@ module Members
delete_subresources(member) unless skip_subresources
delete_project_invitations_by(member) unless skip_subresources
resolve_access_request_todos(current_user, member)
- enqueue_delete_todos(member)
- enqueue_unassign_issuables(member) if unassign_issuables
after_execute(member: member)
end
@@ -110,13 +129,17 @@ module Members
def destroy_project_members(members)
members.each do |project_member|
- self.class.new(current_user).execute(project_member, skip_authorization: @skip_auth)
+ service = self.class.new(current_user)
+ service.mark_as_recursive_call
+ service.execute(project_member, skip_authorization: @skip_auth)
end
end
def destroy_group_members(members)
members.each do |group_member|
- self.class.new(current_user).execute(group_member, skip_authorization: @skip_auth, skip_subresources: true)
+ service = self.class.new(current_user)
+ service.mark_as_recursive_call
+ service.execute(group_member, skip_authorization: @skip_auth, skip_subresources: true)
end
end
diff --git a/app/views/admin/sessions/_signin_box.html.haml b/app/views/admin/sessions/_signin_box.html.haml
index c7382266480..2cd2eabd4b7 100644
--- a/app/views/admin/sessions/_signin_box.html.haml
+++ b/app/views/admin/sessions/_signin_box.html.haml
@@ -7,7 +7,7 @@
- ldap_servers.each_with_index do |server, i|
.login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i == 0 && form_based_auth_provider_has_active_class?(:ldapmain)) }
.login-body
- = render 'devise/sessions/new_ldap', server: server, hide_remember_me: true, submit_message: _('Enter Admin Mode')
+ = render 'devise/sessions/new_ldap', server: server, render_remember_me: false, submit_message: _('Enter Admin Mode')
= render_if_exists 'devise/sessions/new_smartcard'
diff --git a/app/views/admin/sessions/new.html.haml b/app/views/admin/sessions/new.html.haml
index e9442cf6b53..21b2c6df014 100644
--- a/app/views/admin/sessions/new.html.haml
+++ b/app/views/admin/sessions/new.html.haml
@@ -20,4 +20,4 @@
- if omniauth_enabled? && button_based_providers_enabled?
.clearfix
- = render 'devise/shared/omniauth_box', hide_remember_me: true
+ = render 'devise/shared/omniauth_box', render_remember_me: false
diff --git a/app/views/admin/sessions/two_factor.html.haml b/app/views/admin/sessions/two_factor.html.haml
index d02090d4880..33d73745138 100644
--- a/app/views/admin/sessions/two_factor.html.haml
+++ b/app/views/admin/sessions/two_factor.html.haml
@@ -9,7 +9,7 @@
.tab-content
.login-box.tab-pane.gl-p-5.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
- - if current_user.two_factor_otp_enabled?
+ - if current_user.sign_in_with_codes_allowed?
= render 'admin/sessions/two_factor_otp'
- if current_user.two_factor_webauthn_enabled?
= render 'authentication/authenticate', render_remember_me: false, target_path: admin_session_path
diff --git a/app/views/authentication/_authenticate.html.haml b/app/views/authentication/_authenticate.html.haml
index 7d7bd395836..9e09bcd6e54 100644
--- a/app/views/authentication/_authenticate.html.haml
+++ b/app/views/authentication/_authenticate.html.haml
@@ -21,7 +21,7 @@
%div
%p= _("We heard back from your device. You have been authenticated.")
= form_tag(target_path, method: :post, id: 'js-login-token-2fa-form') do |f|
- - if render_remember_me
+ - if remember_me_enabled? && render_remember_me
- resource_params = params[resource_name].presence || params
= hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
= hidden_field_tag 'user[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 3aeb89979bb..1c40931c5bb 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -5,15 +5,15 @@
.form-group.gl-px-5
= f.label :password, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
= f.password_field :password, class: 'form-control gl-form-input bottom', autocomplete: 'current-password', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field', testid: 'password-field' }
- - if devise_mapping.rememberable?
- .gl-px-5
- .gl-display-inline-block
+ .gl-px-5
+ .gl-display-inline-block
+ - if remember_me_enabled?
= f.gitlab_ui_checkbox_component :remember_me, _('Remember me')
- .gl-float-right
- - if unconfirmed_email?
- = link_to _('Resend confirmation email'), new_user_confirmation_path
- - else
- = link_to _('Forgot your password?'), new_password_path(:user)
+ .gl-float-right
+ - if unconfirmed_email?
+ = link_to _('Resend confirmation email'), new_user_confirmation_path
+ - else
+ = link_to _('Forgot your password?'), new_password_path(:user)
%div
- if Feature.enabled?(:arkose_labs_login_challenge)
= render_if_exists 'devise/sessions/arkose_labs'
diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml
index bdf357c5f74..14038f3c3c7 100644
--- a/app/views/devise/sessions/_new_crowd.html.haml
+++ b/app/views/devise/sessions/_new_crowd.html.haml
@@ -5,7 +5,7 @@
.form-group.gl-px-5
= label_tag :password
= password_field_tag :password, nil, { autocomplete: 'current-password', class: "form-control bottom", title: _("This field is required."), required: true }
- - if devise_mapping.rememberable?
+ - if remember_me_enabled?
.remember-me.gl-px-5
%label{ for: "remember_me" }
= check_box_tag :remember_me, '1', false, id: 'remember_me'
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 7affbafbdeb..8f9d6ee556e 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -1,5 +1,5 @@
- server = local_assigns.fetch(:server)
-- hide_remember_me = local_assigns.fetch(:hide_remember_me, false)
+- render_remember_me = remember_me_enabled? && local_assigns.fetch(:render_remember_me, true)
- submit_message = local_assigns.fetch(:submit_message, _('Sign in'))
= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "gl-show-field-errors") do
@@ -9,7 +9,7 @@
.form-group.gl-px-5
= label_tag :password
= password_field_tag :password, nil, { autocomplete: 'current-password', class: "form-control gl-form-input bottom", title: _("This field is required."), data: { qa_selector: 'password_field' }, required: true }
- - if !hide_remember_me && devise_mapping.rememberable?
+ - if render_remember_me
.gl-px-5
= render Pajamas::CheckboxTagComponent.new(name: 'remember_me') do |c|
= c.label do
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index 12e5a7263f7..789f6072b68 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -2,10 +2,11 @@
= render 'devise/shared/tab_single', tab_title: _('Two-Factor Authentication') if Feature.disabled?(:restyle_login_page, @project)
.login-box.gl-p-5
.login-body
- - if @user.two_factor_otp_enabled? || (Feature.enabled?(:webauthn_without_totp) && @user.two_factor_enabled?)
+ - if @user.sign_in_with_codes_allowed?
= gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_enabled?}" }) do |f|
- resource_params = params[resource_name].presence || params
- = f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
+ - if remember_me_enabled?
+ = f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
%div
= f.label _('Enter verification code'), name: :otp_attempt, class: Feature.enabled?(:restyle_login_page, @project) ? 'gl-mb-1' : ''
= f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', inputmode: 'numeric', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 150f61a97e0..f59bdc67d17 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -1,4 +1,4 @@
-- hide_remember_me = local_assigns.fetch(:hide_remember_me, false)
+- render_remember_me = remember_me_enabled? && local_assigns.fetch(:render_remember_me, true)
- restyle_login_page_enabled = Feature.enabled?(:restyle_login_page, @project)
%div{ class: restyle_login_page_enabled ? 'omniauth-container gl-mt-5 gl-p-5 gl-text-center gl-w-90p gl-ml-auto gl-mr-auto' : 'omniauth-container gl-mt-5 gl-p-5' }
%label{ class: restyle_login_page_enabled ? 'gl-font-weight-normal' : 'gl-font-weight-bold' }
@@ -12,7 +12,7 @@
= provider_image_tag(provider)
%span.gl-button-text
= label_for_provider(provider)
- - unless hide_remember_me
+ - if render_remember_me
= render Pajamas::CheckboxTagComponent.new(name: 'remember_me_omniauth', value: nil) do |c|
= c.label do
= _('Remember me')
diff --git a/app/views/projects/_self_monitoring_deprecation_notice.html.haml b/app/views/projects/_self_monitoring_deprecation_notice.html.haml
deleted file mode 100644
index b9e32356688..00000000000
--- a/app/views/projects/_self_monitoring_deprecation_notice.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- return unless project.self_monitoring?
-
-= content_for :page_level_alert do
- .flash-container.flash-container-page.sticky
- %div{ class: [container_class, 'limit-container-width', 'gl-pt-5!'] }
- = render Pajamas::AlertComponent.new(title: _('Deprecation notice'),
- variant: :danger,
- alert_options: { class: 'gl-mb-3 gl-sticky' }) do |c|
- = c.body do
- - deprecation_link = '<a href="%{url}">'.html_safe % { url: help_page_path('update/deprecations', anchor: 'gitlab-self-monitoring-project') }
- - removal_link = '<a href="%{url}">'.html_safe % { url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348909' }
- - opstrace_link = '<a href="%{url}">'.html_safe % { url: 'https://gitlab.com/groups/gitlab-org/-/epics/6976' }
- = _("Self-monitoring was %{deprecation}deprecated%{link_end} in GitLab 14.9, and is %{removal}scheduled for removal%{link_end} in GitLab 16.0. For information on a possible replacement, %{opstrace}learn more about Opstrace%{link_end}.").html_safe % { deprecation: deprecation_link, removal: removal_link, opstrace: opstrace_link, link_end: '</a>'.html_safe }
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index b6c21588193..a51d1080d96 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -7,7 +7,6 @@
= render "home_panel"
= render "archived_notice", project: @project
-= render "self_monitoring_deprecation_notice", project: @project
= render "invite_members_empty_project" if can_admin_project_member?(@project)
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index ab2f6745dfd..e21bf7d318b 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -8,7 +8,6 @@
= render_if_exists 'shared/ultimate_feature_removal_banner', project: @project
= render partial: 'flash_messages', locals: { project: @project }
-= render "self_monitoring_deprecation_notice", project: @project
= render 'clusters_deprecation_alert'