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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-17 18:14:54 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-17 18:14:54 +0300
commit46d07ca5c2b729d6396723290a875a317b2845ee (patch)
treecb4c7572244aa2ed873c848b4794ddb1dcfa45a5
parentdb30b31f056d0de120d9238a7786e19cafbce69f (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/deprecated_notes.js2
-rw-r--r--app/assets/javascripts/lib/utils/error_message.js20
-rw-r--r--app/assets/javascripts/persistent_user_callouts.js1
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue9
-rw-r--r--app/controllers/admin/cohorts_controller.rb2
-rw-r--r--app/controllers/admin/dev_ops_report_controller.rb2
-rw-r--r--app/controllers/admin/usage_trends_controller.rb2
-rw-r--r--app/controllers/concerns/product_analytics_tracking.rb32
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/cycle_analytics_controller.rb2
-rw-r--r--app/controllers/projects/graphs_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb2
-rw-r--r--app/controllers/search_controller.rb2
-rw-r--r--app/graphql/types/project_type.rb2
-rw-r--r--app/helpers/users/callouts_helper.rb5
-rw-r--r--app/models/users/callout.rb3
-rw-r--r--app/services/security/ci_configuration/base_create_service.rb3
-rw-r--r--app/views/admin/application_settings/appearances/show.html.haml1
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml1
-rw-r--r--app/views/admin/application_settings/general.html.haml1
-rw-r--r--app/views/admin/application_settings/integrations.html.haml1
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml1
-rw-r--r--app/views/admin/application_settings/network.html.haml1
-rw-r--r--app/views/admin/application_settings/preferences.html.haml1
-rw-r--r--app/views/admin/application_settings/reporting.html.haml1
-rw-r--r--app/views/admin/application_settings/repository.html.haml1
-rw-r--r--app/views/admin/application_settings/service_usage_data.html.haml1
-rw-r--r--app/views/admin/health_check/show.html.haml5
-rw-r--r--app/views/projects/branches/_branch_rules_info.haml12
-rw-r--r--app/views/projects/branches/index.html.haml12
-rw-r--r--data/removals/15_10/15_10-non-public-artifacts.yml25
-rw-r--r--doc/api/graphql/reference/index.md1
-rw-r--r--doc/api/packages.md3
-rw-r--r--doc/ci/testing/unit_test_report_examples.md21
-rw-r--r--doc/development/api_styleguide.md11
-rw-r--r--doc/development/fe_guide/style/javascript.md19
-rw-r--r--doc/development/service_ping/implement.md8
-rw-r--r--doc/integration/partner_marketplace.md40
-rw-r--r--doc/update/removals.md12
-rw-r--r--doc/user/packages/package_registry/reduce_package_registry_storage.md3
-rw-r--r--doc/user/packages/package_registry/supported_functionality.md23
-rw-r--r--doc/user/project/protected_tags.md26
-rw-r--r--lib/gitlab/utils/error_message.rb13
-rw-r--r--locale/gitlab.pot12
-rw-r--r--spec/controllers/concerns/product_analytics_tracking_spec.rb15
-rw-r--r--spec/features/admin/admin_health_check_spec.rb6
-rw-r--r--spec/features/projects/branches_spec.rb24
-rw-r--r--spec/frontend/lib/utils/error_message_spec.js65
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js24
-rw-r--r--spec/frontend/security_configuration/components/feature_card_spec.js5
-rw-r--r--spec/frontend/security_configuration/constants.js1
-rw-r--r--spec/graphql/types/project_type_spec.rb2
-rw-r--r--spec/lib/gitlab/utils/error_message_spec.rb23
-rw-r--r--spec/support/shared_examples/services/security/ci_configuration/create_service_shared_examples.rb2
54 files changed, 443 insertions, 73 deletions
diff --git a/app/assets/javascripts/deprecated_notes.js b/app/assets/javascripts/deprecated_notes.js
index 32a91506ab4..0008c3504ce 100644
--- a/app/assets/javascripts/deprecated_notes.js
+++ b/app/assets/javascripts/deprecated_notes.js
@@ -1408,7 +1408,7 @@ export default class Notes {
* Load notes ids
*/
static loadNotesIds(note_ids) {
- const $notesList = $('.main-notes-list').children();
+ const $notesList = $('.main-notes-list li[id^=note_]');
for (const $noteItem of $notesList) {
if (Notes.isNodeTypeElement($noteItem)) {
const noteId = parseInt($noteItem.id.split('_')[1], 10);
diff --git a/app/assets/javascripts/lib/utils/error_message.js b/app/assets/javascripts/lib/utils/error_message.js
new file mode 100644
index 00000000000..4cea4257e7b
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/error_message.js
@@ -0,0 +1,20 @@
+export const USER_FACING_ERROR_MESSAGE_PREFIX = 'UF:';
+
+const getMessageFromError = (error = '') => {
+ return error.message || error;
+};
+
+export const parseErrorMessage = (error = '') => {
+ const messageString = getMessageFromError(error);
+
+ if (messageString.startsWith(USER_FACING_ERROR_MESSAGE_PREFIX)) {
+ return {
+ message: messageString.replace(USER_FACING_ERROR_MESSAGE_PREFIX, '').trim(),
+ userFacing: true,
+ };
+ }
+ return {
+ message: messageString,
+ userFacing: false,
+ };
+};
diff --git a/app/assets/javascripts/persistent_user_callouts.js b/app/assets/javascripts/persistent_user_callouts.js
index a16e93d0541..3130fe42c3c 100644
--- a/app/assets/javascripts/persistent_user_callouts.js
+++ b/app/assets/javascripts/persistent_user_callouts.js
@@ -23,6 +23,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-geo-enable-hashed-storage-callout',
'.js-geo-migrate-hashed-storage-callout',
'.js-unlimited-members-during-trial-alert',
+ '.js-branch-rules-info-callout',
];
const initCallouts = () => {
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
index e96f71981e5..ccfaa678201 100644
--- a/app/assets/javascripts/security_configuration/components/app.vue
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -1,6 +1,7 @@
<script>
import { GlTab, GlTabs, GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
import { __, s__ } from '~/locale';
+import { parseErrorMessage } from '~/lib/utils/error_message';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
import SectionLayout from '~/vue_shared/security_configuration/components/section_layout.vue';
@@ -33,6 +34,9 @@ export const i18n = {
'SecurityConfiguration|Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability.',
),
securityTrainingDoc: s__('SecurityConfiguration|Learn more about vulnerability training'),
+ genericErrorText: s__(
+ `SecurityConfiguration|Something went wrong. Please refresh the page, or try again later.`,
+ ),
};
export default {
@@ -124,8 +128,9 @@ export default {
dismissedProjects.add(this.projectFullPath);
this.autoDevopsEnabledAlertDismissedProjects = Array.from(dismissedProjects);
},
- onError(message) {
- this.errorMessage = message;
+ onError(error) {
+ const { message, userFacing } = parseErrorMessage(error);
+ this.errorMessage = userFacing ? message : i18n.genericErrorText;
},
dismissAlert() {
this.errorMessage = '';
diff --git a/app/controllers/admin/cohorts_controller.rb b/app/controllers/admin/cohorts_controller.rb
index ce3d769f35e..3948d3635fe 100644
--- a/app/controllers/admin/cohorts_controller.rb
+++ b/app/controllers/admin/cohorts_controller.rb
@@ -7,7 +7,7 @@ class Admin::CohortsController < Admin::ApplicationController
urgency :low
- track_custom_event :index,
+ track_event :index,
name: 'i_analytics_cohorts',
action: 'perform_analytics_usage_action',
label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
diff --git a/app/controllers/admin/dev_ops_report_controller.rb b/app/controllers/admin/dev_ops_report_controller.rb
index 71ee19ddf39..2e47dfcb0db 100644
--- a/app/controllers/admin/dev_ops_report_controller.rb
+++ b/app/controllers/admin/dev_ops_report_controller.rb
@@ -5,7 +5,7 @@ class Admin::DevOpsReportController < Admin::ApplicationController
helper_method :show_adoption?
- track_custom_event :show,
+ track_event :show,
name: 'i_analytics_dev_ops_score',
action: 'perform_analytics_usage_action',
label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
diff --git a/app/controllers/admin/usage_trends_controller.rb b/app/controllers/admin/usage_trends_controller.rb
index 082b38ac3a8..f88028535c1 100644
--- a/app/controllers/admin/usage_trends_controller.rb
+++ b/app/controllers/admin/usage_trends_controller.rb
@@ -3,7 +3,7 @@
class Admin::UsageTrendsController < Admin::ApplicationController
include ProductAnalyticsTracking
- track_custom_event :index,
+ track_event :index,
name: 'i_analytics_instance_statistics',
action: 'perform_analytics_usage_action',
label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb
index 6a286a1ca26..5ed2b2a82eb 100644
--- a/app/controllers/concerns/product_analytics_tracking.rb
+++ b/app/controllers/concerns/product_analytics_tracking.rb
@@ -30,45 +30,23 @@ module ProductAnalyticsTracking
].freeze
class_methods do
- # TODO: Remove once all the events are migrated to #track_custom_event
- # during https://gitlab.com/groups/gitlab-org/-/epics/8641
- def track_event(*controller_actions, name:, conditions: nil, destinations: [:redis_hll], &block)
+ def track_event(*controller_actions, name:, action: nil, label: nil, conditions: nil, destinations: [:redis_hll], &block)
custom_conditions = [:trackable_html_request?, *conditions]
after_action only: controller_actions, if: custom_conditions do
- route_events_to(destinations, name, &block)
- end
- end
-
- def track_custom_event(*controller_actions, name:, action:, label:, conditions: nil, destinations: [:redis_hll], &block)
- custom_conditions = [:trackable_html_request?, *conditions]
-
- after_action only: controller_actions, if: custom_conditions do
- route_custom_events_to(destinations, name, action, label, &block)
+ route_events_to(destinations, name, action, label, &block)
end
end
end
private
- def route_events_to(destinations, name, &block)
- track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll)
-
- return unless destinations.include?(:snowplow) && event_enabled?(name)
-
- Gitlab::Tracking.event(
- self.class.to_s,
- name,
- namespace: tracking_namespace_source,
- user: current_user,
- context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: name).to_context]
- )
- end
-
- def route_custom_events_to(destinations, name, action, label, &block)
+ def route_events_to(destinations, name, action, label, &block)
track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll)
return unless destinations.include?(:snowplow) && event_enabled?(name)
+ raise "action is required when destination is snowplow" unless action
+ raise "label is required when destination is snowplow" unless label
optional_arguments = {
namespace: tracking_namespace_source,
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 79c27904542..3413aeb6f8a 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -37,7 +37,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action :validate_diff_params, only: :diff
before_action :set_last_commit_sha, only: [:edit, :update]
- track_custom_event :create, :update,
+ track_event :create, :update,
name: 'g_edit_by_sfe',
action: 'perform_sfe_action',
label: 'usage_activity_by_stage_monthly.create.action_monthly_active_users_sfe_edit',
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index 6e19c0e45bf..dbed5adf2e8 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -11,7 +11,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
before_action :authorize_read_cycle_analytics!
before_action :load_value_stream, only: :show
- track_custom_event :show,
+ track_event :show,
name: 'p_analytics_valuestream',
action: 'perform_analytics_usage_action',
label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb
index d072381933a..e73e2a38149 100644
--- a/app/controllers/projects/graphs_controller.rb
+++ b/app/controllers/projects/graphs_controller.rb
@@ -9,7 +9,7 @@ class Projects::GraphsController < Projects::ApplicationController
before_action :assign_ref_vars
before_action :authorize_read_repository_graphs!
- track_custom_event :charts,
+ track_event :charts,
name: 'p_analytics_repo',
action: 'perform_analytics_usage_action',
label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index a80aa9f4ac7..6fdd4906613 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -29,7 +29,7 @@ class Projects::PipelinesController < Projects::ApplicationController
around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
- track_custom_event :charts,
+ track_event :charts,
name: 'p_analytics_pipelines',
action: 'perform_analytics_usage_action',
label: 'redis_hll_counters.analytics.analytics_total_unique_counts_monthly',
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 549b6286d96..688c56e56e0 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -10,7 +10,7 @@ class SearchController < ApplicationController
RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show, :autocomplete, :aggregations].freeze
CODE_SEARCH_LITERALS = %w[blob: extension: path: filename:].freeze
- track_custom_event :show,
+ track_event :show,
name: 'i_search_total',
label: 'redis_hll_counters.search.search_total_unique_counts_monthly',
action: 'executed',
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 4593f5e5925..4ca2bc8b1b5 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -665,7 +665,7 @@ module Types
if project.repository.empty?
raise Gitlab::Graphql::Errors::MutationError,
- _(format('You must %s before using Security features.', add_file_docs_link.html_safe)).html_safe
+ Gitlab::Utils::ErrorMessage.to_user_facing(_(format('You must %s before using Security features.', add_file_docs_link.html_safe)).html_safe)
end
::Security::CiConfiguration::SastParserService.new(object).configuration
diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb
index 0ad1cbdff3e..af3ac495164 100644
--- a/app/helpers/users/callouts_helper.rb
+++ b/app/helpers/users/callouts_helper.rb
@@ -15,6 +15,7 @@ module Users
REGISTRATION_ENABLED_CALLOUT_ALLOWED_CONTROLLER_PATHS = [/^root/, /^dashboard\S*/, /^admin\S*/].freeze
WEB_HOOK_DISABLED = 'web_hook_disabled'
ULTIMATE_FEATURE_REMOVAL_BANNER = 'ultimate_feature_removal_banner'
+ BRANCH_RULES_INFO_CALLOUT = 'branch_rules_info_callout'
def show_gke_cluster_integration_callout?(project)
active_nav_link?(controller: sidebar_operations_paths) &&
@@ -74,6 +75,10 @@ module Users
!user_dismissed?(PAGES_MOVED_CALLOUT)
end
+ def show_branch_rules_info?
+ !user_dismissed?(BRANCH_RULES_INFO_CALLOUT)
+ end
+
def ultimate_feature_removal_banner_dismissed?(project)
return false unless project
diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb
index 3f9353214ee..70c31f0a8ec 100644
--- a/app/models/users/callout.rb
+++ b/app/models/users/callout.rb
@@ -65,7 +65,8 @@ module Users
new_top_level_group_alert: 61,
artifacts_management_page_feedback_banner: 62,
vscode_web_ide: 63,
- vscode_web_ide_callout: 64
+ vscode_web_ide_callout: 64,
+ branch_rules_info_callout: 65
}
validates :feature_name,
diff --git a/app/services/security/ci_configuration/base_create_service.rb b/app/services/security/ci_configuration/base_create_service.rb
index c5fbabf487c..0534925aaec 100644
--- a/app/services/security/ci_configuration/base_create_service.rb
+++ b/app/services/security/ci_configuration/base_create_service.rb
@@ -19,7 +19,8 @@ module Security
target: '_blank',
rel: 'noopener noreferrer'
raise Gitlab::Graphql::Errors::MutationError,
- _(format('You must %s before using Security features.', docs_link.html_safe)).html_safe
+ Gitlab::Utils::ErrorMessage.to_user_facing(
+ _(format('You must %s before using Security features.', docs_link.html_safe)).html_safe)
end
project.repository.add_branch(current_user, branch_name, project.default_branch)
diff --git a/app/views/admin/application_settings/appearances/show.html.haml b/app/views/admin/application_settings/appearances/show.html.haml
index 1e55190d53b..cd255d961f4 100644
--- a/app/views/admin/application_settings/appearances/show.html.haml
+++ b/app/views/admin/application_settings/appearances/show.html.haml
@@ -1,5 +1,4 @@
- page_title _("Appearance")
-- @content_class = "limit-container-width" unless fluid_layout
- add_page_specific_style 'page_bundles/settings'
= render 'form'
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index bd0ce766f81..a7119af7ece 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title _("CI/CD")
- page_title _("CI/CD")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
%section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index a4af1913d22..a7c80abdbc9 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title _("General")
- page_title _("General")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
%section.settings.as-visibility-access.no-animate#js-visibility-settings{ class: ('expanded' if expanded_by_default?), data: { testid: 'admin-visibility-access-settings' } }
.settings-header
diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml
index fd1ad5cd304..396e6f3e7d6 100644
--- a/app/views/admin/application_settings/integrations.html.haml
+++ b/app/views/admin/application_settings/integrations.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title s_('Integrations|Instance-level integration management')
- page_title s_('Integrations|Instance-level integration management')
- add_page_specific_style 'page_bundles/settings'
-- @content_class = 'limit-container-width' unless fluid_layout
%h3= s_('Integrations|Instance-level integration management')
diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml
index b5981578866..711b2c97d65 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -3,7 +3,6 @@
- breadcrumb_title _("Metrics and profiling")
- page_title _("Metrics and profiling")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
%section.settings.as-prometheus.no-animate#js-prometheus-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index b20fc703f18..32b10fd36e8 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title _("Network")
- page_title _("Network")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
%section.settings.as-performance.no-animate#js-performance-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/preferences.html.haml b/app/views/admin/application_settings/preferences.html.haml
index dd6666542ca..3843fc8e863 100644
--- a/app/views/admin/application_settings/preferences.html.haml
+++ b/app/views/admin/application_settings/preferences.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title _("Preferences")
- page_title _("Preferences")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
%section.settings.as-email.no-animate#js-email-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'email_content' } }
.settings-header
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index 3d803e95cd0..0046275c7d1 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title _("Reporting")
- page_title _("Reporting")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
%section.settings.as-spam.no-animate#js-spam-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/repository.html.haml b/app/views/admin/application_settings/repository.html.haml
index 50798ad476c..518b40a0326 100644
--- a/app/views/admin/application_settings/repository.html.haml
+++ b/app/views/admin/application_settings/repository.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title _("Repository")
- page_title _("Repository")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
%section.settings.as-default-branch-name.no-animate#js-default-branch-name{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/service_usage_data.html.haml b/app/views/admin/application_settings/service_usage_data.html.haml
index d6860cc08ac..af646d79c29 100644
--- a/app/views/admin/application_settings/service_usage_data.html.haml
+++ b/app/views/admin/application_settings/service_usage_data.html.haml
@@ -3,7 +3,6 @@
- breadcrumb_title name
- page_title name
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
- payload_class = 'js-service-ping-payload'
%section.js-search-settings-section
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index 98427cb6419..e7aa4f38634 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -8,9 +8,8 @@
#{ s_('HealthCheck|Access token is') }
%code#health-check-token= Gitlab::CurrentSettings.health_check_access_token
.gl-mt-3
- = button_to _("Reset health check access token"), reset_health_check_token_admin_application_settings_path,
- method: :put, class: 'gl-button btn btn-default',
- data: { confirm: _('Are you sure you want to reset the health check token?') }
+ = render Pajamas::ButtonComponent.new(href: reset_health_check_token_admin_application_settings_path, method: :put, button_options: { data: { confirm: _('Are you sure you want to reset the health check token?') } }) do
+ = _("Reset health check access token")
%p.light
#{ _('Health information can be retrieved from the following endpoints. More information is available') }
= link_to s_('More information is available|here'), help_page_path('user/admin_area/monitoring/health_check')
diff --git a/app/views/projects/branches/_branch_rules_info.haml b/app/views/projects/branches/_branch_rules_info.haml
new file mode 100644
index 00000000000..15bee31c596
--- /dev/null
+++ b/app/views/projects/branches/_branch_rules_info.haml
@@ -0,0 +1,12 @@
+- return unless show_branch_rules_info?
+= render Pajamas::AlertComponent.new(variant: :info,
+ title: s_("Branches|See all branch-related settings together with branch rules"),
+ alert_options: { class: 'js-branch-rules-info-callout gl-mb-6 gl-mt-4', data: { feature_id: Users::CalloutsHelper::BRANCH_RULES_INFO_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
+ = c.body do
+ = s_("Branches|You can now find an overview of settings for protected branches, merge request approvals, status checks, and security approvals conveniently in one spot.")
+
+ = c.actions do
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: project_settings_repository_path(@project, anchor: 'js-branch-rules'), button_options: { class: 'deferred-link gl-alert-action' }) do
+ = s_("Branches|View branch rules")
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-close'}) do
+ = _('Dismiss')
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index f43d19e2542..518292effd8 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -1,6 +1,8 @@
- add_page_specific_style 'page_bundles/branches'
- page_title _('Branches')
- add_to_breadcrumbs(_('Repository'), project_tree_path(@project))
+- is_branch_rules_available = (can? current_user, :maintainer_access, @project) && Feature.enabled?(:branch_rules, @project)
+- can_push_code = (can? current_user, :push_code, @project)
-# Possible values for variables passed down from the projects/branches_controller.rb
-#
@@ -22,16 +24,24 @@
sorted_by: @sort }
}
- - if can? current_user, :push_code, @project
+ - if can_push_code
.js-delete-merged-branches{ data: {
default_branch: @project.repository.root_ref,
form_path: project_merged_branches_path(@project) }
}
+ - if is_branch_rules_available
+ = link_to project_settings_repository_path(@project, anchor: 'js-branch-rules'), class: 'gl-button btn btn-default' do
+ = s_('Branches|View branch rules')
+
+ - if can_push_code
= link_to new_project_branch_path(@project), class: 'gl-button btn btn-confirm' do
= s_('Branches|New branch')
= render_if_exists 'projects/commits/mirror_status'
+- if is_branch_rules_available
+ = render 'branch_rules_info'
+
.js-branch-list{ data: { diverging_counts_endpoint: diverging_commit_counts_namespace_project_branches_path(@project.namespace, @project, format: :json), default_branch: @project.default_branch } }
- if @gitaly_unavailable
diff --git a/data/removals/15_10/15_10-non-public-artifacts.yml b/data/removals/15_10/15_10-non-public-artifacts.yml
new file mode 100644
index 00000000000..bea672d2f22
--- /dev/null
+++ b/data/removals/15_10/15_10-non-public-artifacts.yml
@@ -0,0 +1,25 @@
+#
+# REQUIRED FIELDS
+#
+- title: "`artifacts:public` CI/CD keyword refactored" # (required) Clearly explain the change. For example, "The `confidential` field for a `Note` is removed" or "CI/CD job names are limited to 250 characters."
+ announcement_milestone: "15.10" # (required) The milestone when this feature was deprecated.
+ announcement_date: "2023-03-22" # (required) The date of the milestone release when this feature was deprecated. This should almost always be the 22nd of a month (YYYY-MM-DD), unless you did an out of band blog post.
+ removal_milestone: "15.8" # (required) The milestone when this feature is being removed.
+ removal_date: "2023-01-22" # (required) This should almost always be the 22nd of a month (YYYY-MM-DD), the date of the milestone release when this feature will be removed.
+ breaking_change: true # (required) Change to false if this is not a breaking change.
+ reporter: jocelynjane # (required) GitLab username of the person reporting the removal
+ stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322454 # (required) Link to the deprecation issue in GitLab
+ body: | # (required) Do not modify this line, instead modify the lines below.
+ The [`artifacts:public` CI/CD keyword](https://docs.gitlab.com/ee/ci/yaml/#artifactspublic) was discovered to be not working properly since GitLab 15.8 and needed to be refactored. This feature is disabled on GitLab.com, and disabled by default on self-managed instances. If an administrator for an instance running GitLab 15.8 or 15.9 enabled this feature via the `non_public_artifacts` feature flag, it is likely that artifacts created with the `public:false` setting are being treated as `public:true`.
+
+ If you have projects that use this setting, you should delete artifacts that must not be public, or [change the visibility](https://docs.gitlab.com/ee/user/public_access.html#change-project-visibility) of affected projects to private, before updating to GitLab 15.8 or later.
+
+ In GitLab 15.10, this feature's code was refactored. On instances with this feature enabled, new artifacts created with `public:false` are now working as expected, though still disabled by default. Avoid testing this feature with production data until it is enabled by default and made generally available.
+#
+# OPTIONAL FIELDS
+#
+ tiers: Free # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ documentation_url: https://docs.gitlab.com/ee/ci/yaml/#artifactspublic # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index cb9f225f03f..d5b73291666 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -24376,6 +24376,7 @@ Name of the feature that the callout is for.
| ----- | ----------- |
| <a id="usercalloutfeaturenameenumactive_user_count_threshold"></a>`ACTIVE_USER_COUNT_THRESHOLD` | Callout feature name for active_user_count_threshold. |
| <a id="usercalloutfeaturenameenumartifacts_management_page_feedback_banner"></a>`ARTIFACTS_MANAGEMENT_PAGE_FEEDBACK_BANNER` | Callout feature name for artifacts_management_page_feedback_banner. |
+| <a id="usercalloutfeaturenameenumbranch_rules_info_callout"></a>`BRANCH_RULES_INFO_CALLOUT` | Callout feature name for branch_rules_info_callout. |
| <a id="usercalloutfeaturenameenumbuy_pipeline_minutes_notification_dot"></a>`BUY_PIPELINE_MINUTES_NOTIFICATION_DOT` | Callout feature name for buy_pipeline_minutes_notification_dot. |
| <a id="usercalloutfeaturenameenumcanary_deployment"></a>`CANARY_DEPLOYMENT` | Callout feature name for canary_deployment. |
| <a id="usercalloutfeaturenameenumci_deprecation_warning_for_types_keyword"></a>`CI_DEPRECATION_WARNING_FOR_TYPES_KEYWORD` | Callout feature name for ci_deprecation_warning_for_types_keyword. |
diff --git a/doc/api/packages.md b/doc/api/packages.md
index 32b21ce354d..86eaf3028cf 100644
--- a/doc/api/packages.md
+++ b/doc/api/packages.md
@@ -352,6 +352,9 @@ Can return the following status codes:
- `204 No Content`, if the package was deleted successfully.
- `404 Not Found`, if the package was not found.
+If [request forwarding](../user/packages/package_registry/supported_functionality.md#forwarding-requests) is enabled,
+deleting a package can introduce a [dependency confusion risk](../user/packages/package_registry/supported_functionality.md#deleting-packages).
+
## Delete a package file
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32107) in GitLab 13.12.
diff --git a/doc/ci/testing/unit_test_report_examples.md b/doc/ci/testing/unit_test_report_examples.md
index 41dfc8fc60b..c63e225a2a7 100644
--- a/doc/ci/testing/unit_test_report_examples.md
+++ b/doc/ci/testing/unit_test_report_examples.md
@@ -274,3 +274,24 @@ phpunit:
reports:
junit: report.xml
```
+
+## Rust
+
+This example uses [cargo2junit](https://crates.io/crates/cargo2junit),
+which is installed in the current directory.
+To retrieve JSON output from `cargo test`, you must enable the nightly compiler.
+
+```yaml
+run unittests:
+ image: rust:latest
+ stage: test
+ before_script:
+ - cargo install --root . cargo2junit
+ script:
+ - cargo test -- -Z unstable-options --format json --report-time | bin/cargo2junit > report.xml
+ artifacts:
+ when: always
+ reports:
+ junit:
+ - report.xml
+```
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index 006d0a01abb..828ef21ba9a 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -333,6 +333,17 @@ expect(response).to match_response_schema('merge_requests')
Also see [verifying N+1 performance](#verifying-with-tests) in tests.
+## Error handling
+
+When throwing an error with a message that is meant to be user-facing, you should
+use the error message utility function contained in `lib/gitlab/utils/error_message.rb`.
+It adds a prefix to the error message, making it distinguishable from non-user-facing error messages.
+Please make sure that the Frontend is aware of the prefix usage and is using the according utils.
+
+```ruby
+Gitlab::Utils::ErrorMessage.to_user_facing('Example user-facing error-message')
+```
+
## Include a changelog entry
All client-facing changes **must** include a [changelog entry](changelog.md).
diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md
index 3e3a79dd7bb..b35ffdd8669 100644
--- a/doc/development/fe_guide/style/javascript.md
+++ b/doc/development/fe_guide/style/javascript.md
@@ -329,3 +329,22 @@ Only export the constants as a collection (array, or object) when there is a nee
// good, if the constants need to be iterated over
export const VARIANTS = [VARIANT_WARNING, VARIANT_ERROR];
```
+
+## Error handling
+
+When catching a server-side error you should use the error message
+utility function contained in `app/assets/javascripts/lib/utils/error_message.js`.
+This utility parses the received error message and checks for a prefix that indicates
+whether the message is meant to be user-facing or not. The utility returns
+an object with the message, and a boolean indicating whether the message is meant to be user-facing or not. Please make sure that the Backend is aware of the utils usage and is adding the prefix
+to the error message accordingly.
+
+```javascript
+import { parseErrorMessage } from '~/lib/utils/error_message';
+
+onError(error) {
+ const { message, userFacing } = parseErrorMessage(error);
+
+ const errorMessage = userFacing ? message : genericErrorText;
+}
+```
diff --git a/doc/development/service_ping/implement.md b/doc/development/service_ping/implement.md
index 40fbeeaa7f0..5bfb81c1d00 100644
--- a/doc/development/service_ping/implement.md
+++ b/doc/development/service_ping/implement.md
@@ -351,16 +351,16 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd/) and [P
- In the controller using the `ProductAnalyticsTracking` module and the following format:
```ruby
- track_custom_event(*controller_actions, name:, action:, label:, conditions: nil, destinations: [:redis_hll], &block)
+ track_event(*controller_actions, name:, action:, label:, conditions: nil, destinations: [:redis_hll], &block)
```
Arguments:
- `controller_actions`: the controller actions to track.
- `name`: the event name.
+ - `action`: required if destination is `:snowplow. Action name for the triggered event. See [event schema](../snowplow/index.md#event-schema) for more details.
+ - `label`: required if destination is `:snowplow. Label for the triggered event. See [event schema](../snowplow/index.md#event-schema) for more details.
- `conditions`: optional custom conditions. Uses the same format as Rails callbacks.
- - `action`: optional action name for the triggered event. See [event schema](../snowplow/index.md#event-schema) for more details.
- - `label`: optional label for the triggered event. See [event schema](../snowplow/index.md#event-schema) for more details.
- `destinations`: optional list of destinations. Currently supports `:redis_hll` and `:snowplow`. Default: `:redis_hll`.
- `&block`: optional block that computes and returns the `custom_id` that we want to track. This overrides the `visitor_id`.
@@ -372,7 +372,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd/) and [P
include ProductAnalyticsTracking
skip_before_action :authenticate_user!, only: :show
- track_custom_event :index, :show,
+ track_event :index, :show,
name: 'users_visiting_projects',
action: 'user_perform_visit',
label: 'redis_hll_counters.users_visiting_project_monthly',
diff --git a/doc/integration/partner_marketplace.md b/doc/integration/partner_marketplace.md
index 2cc306cdf44..5ed131145f4 100644
--- a/doc/integration/partner_marketplace.md
+++ b/doc/integration/partner_marketplace.md
@@ -118,3 +118,43 @@ curl \
--url "https://customers.staging.gitlab.com/api/v1/marketplace/subscriptions/:external_subscription_id" \
--header "Authorization: Bearer NHb_VhZhPOnBTSNfBSzmCmt28lLDWb2xtwr_c3DL148"
```
+
+## Create a new customer subscription
+
+To create a new customer subscription from a GitLab Partner client application,
+
+- Make an authorized POST request to the
+[`/api/v1/marketplace/subscriptions`](https://customers.staging.gitlab.com/openapi_docs/marketplace#/marketplace/post_api_v1_marketplace_subscriptions)
+endpoint in the Customers Portal with the following parameters in JSON format:
+
+| Parameter | Type | Required | Description |
+|--------------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `externalSubscriptionId` | string | yes | ID of the subscription on the GitLab Partner system. |
+| `tradingPartnerId` | string | yes | ID of the GitLab Partner account on the Customers Portal. |
+| `customer` | object | yes | Information about the customer. Must include company name. Contact must include `firstName`, `lastName` and `email`. Address must include `country`. |
+| `orderLines` | array | yes | Specifies the product purchased. Must include `quantity` and `productId`. |
+
+If the request is successful, the response body includes the newly created subscription number. For an example of a full request body,
+see the [Marketplace interactive API documentation](https://customers.staging.gitlab.com/openapi_docs/marketplace).
+
+If the subscription creation is unsuccessful, the response body includes an error message with details about the cause of the error.
+
+## Check the status of a subscription
+
+To get the status of a given subscription,
+
+- Make an authorized GET request to the
+[`/api/v1/marketplace/subscriptions/{external_subscription_id}`](https://customers.staging.gitlab.com/openapi_docs/marketplace#/marketplace/get_api_v1_marketplace_subscriptions__external_subscription_id_)
+endpoint in the Customers Portal.
+
+The request must include the GitLab partner system ID of the subscription to fetch the status for.
+
+If the request is successful, the response body contains the status of the subscription provision. The status can be:
+
+- Creating
+- Created
+- Failed
+- Provisioned
+
+If the subscription cannot be found using the passed `external_subscription_id`, the response has
+a 404 Not Found status.
diff --git a/doc/update/removals.md b/doc/update/removals.md
index 110a3ee29e8..248d03cbbcb 100644
--- a/doc/update/removals.md
+++ b/doc/update/removals.md
@@ -55,6 +55,18 @@ If you want to preserve this functionality, you can follow one of these two path
1. Fork the [GitLab Auto Deploy Helm chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app) into the `chart/` path within your project
1. Set `AUTO_DEPLOY_IMAGE_VERSION` and `DAST_AUTO_DEPLOY_IMAGE_VERSION` to the most recent version of the image that included the CiliumNetworkPolicy
+### `artifacts:public` CI/CD keyword refactored
+
+WARNING:
+This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
+Review the details carefully before upgrading.
+
+The [`artifacts:public` CI/CD keyword](https://docs.gitlab.com/ee/ci/yaml/#artifactspublic) was discovered to be not working properly since GitLab 15.8 and needed to be refactored. This feature is disabled on GitLab.com, and disabled by default on self-managed instances. If an administrator for an instance running GitLab 15.8 or 15.9 enabled this feature via the `non_public_artifacts` feature flag, it is likely that artifacts created with the `public:false` setting are being treated as `public:true`.
+
+If you have projects that use this setting, you should delete artifacts that must not be public, or [change the visibility](https://docs.gitlab.com/ee/user/public_access.html#change-project-visibility) of affected projects to private, before updating to GitLab 15.8 or later.
+
+In GitLab 15.10, this feature's code was refactored. On instances with this feature enabled, new artifacts created with `public:false` are now working as expected, though still disabled by default. Avoid testing this feature with production data until it is enabled by default and made generally available.
+
## Removed in 15.7
### File Type variable expansion in `.gitlab-ci.yml`
diff --git a/doc/user/packages/package_registry/reduce_package_registry_storage.md b/doc/user/packages/package_registry/reduce_package_registry_storage.md
index 673196ebad5..020cad5ac14 100644
--- a/doc/user/packages/package_registry/reduce_package_registry_storage.md
+++ b/doc/user/packages/package_registry/reduce_package_registry_storage.md
@@ -35,6 +35,9 @@ To delete a package in the UI, from your group or project:
The package is permanently deleted.
+If [request forwarding](supported_functionality.md#forwarding-requests) is enabled,
+deleting a package can introduce a [dependency confusion risk](supported_functionality.md#deleting-packages).
+
## Delete assets associated with a package
To delete package assets, you must have suitable [permissions](../../permissions.md).
diff --git a/doc/user/packages/package_registry/supported_functionality.md b/doc/user/packages/package_registry/supported_functionality.md
index e56ae88872a..0c7813beae0 100644
--- a/doc/user/packages/package_registry/supported_functionality.md
+++ b/doc/user/packages/package_registry/supported_functionality.md
@@ -53,10 +53,10 @@ Requests for packages not found in your GitLab project are forwarded to the publ
| Package type | Supports request forwarding |
|-----------------------------------------------------|-----------------------------|
-| [Maven](../maven_repository/index.md) | Y |
-| [npm](../npm_registry/index.md) | Y |
+| [Maven](../maven_repository/index.md) | [Yes (disabled by default)](../../admin_area/settings/continuous_integration.md#maven-forwarding) |
+| [npm](../npm_registry/index.md) | [Yes](../../admin_area/settings/continuous_integration.md#npm-forwarding) |
| [NuGet](../nuget_repository/index.md) | N |
-| [PyPI](../pypi_repository/index.md) | Y |
+| [PyPI](../pypi_repository/index.md) | [Yes](../../admin_area/settings/continuous_integration.md#pypi-forwarding) |
| [Generic packages](../generic_packages/index.md) | N |
| [Terraform](../terraform_module_registry/index.md) | N |
| [Composer](../composer_repository/index.md) | N |
@@ -66,6 +66,23 @@ Requests for packages not found in your GitLab project are forwarded to the publ
| [Go](../go_proxy/index.md) | N |
| [Ruby gems](../rubygems_registry/index.md) | N |
+### Deleting packages
+
+When package requests are forwarded to a public registry, deleting packages can
+be a [dependency confusion vulnerability](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610).
+
+If a system tries to pull a deleted package, the request is forwarded to the public
+registry. If a package with the same name and version is found in the public registry, that package
+is pulled instead. There is a risk that the package pulled from the registry might not be
+what is expected, and could even be malicious.
+
+To reduce the associated security risks, before deleting a package you can:
+
+- Verify the package is not being actively used.
+- Disable request forwarding:
+ - Instance administrators can disable forwarding in the [**Continuous Integration** section](../../admin_area/settings/continuous_integration.md#package-registry-configuration) of the Admin Area.
+ - Group owners can disable forwarding in the **Packages and Registries** section of the group settings.
+
## Allow or prevent duplicates **(FREE)**
By default, the GitLab package registry either allows or prevents duplicates based on the default of that specific package manager format.
diff --git a/doc/user/project/protected_tags.md b/doc/user/project/protected_tags.md
index aa0852565fd..1256599c521 100644
--- a/doc/user/project/protected_tags.md
+++ b/doc/user/project/protected_tags.md
@@ -86,6 +86,32 @@ To prevent this problem:
Users can still create branches, but not tags, with the protected names.
+## Allow deploy keys to create protected tags
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325415) in GitLab 15.11.
+
+You can permit the owner of a [deploy key](deploy_keys/index.md) to create protected tags.
+The deploy key works, even if the user isn't a member of the related project. However, the owner of the deploy
+key must have at least read access to the project.
+
+Prerequisites:
+
+- The deploy key must be enabled for your project. A project deploy key is enabled by default when
+ it is created. However, a public deploy key must be
+ [granted](deploy_keys/index.md#grant-project-access-to-a-public-deploy-key) access to the
+ project.
+- The deploy key must have [write access](deploy_keys/index.md#permissions) to your project
+ repository.
+
+To allow a deploy key to create a protected tag:
+
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Protected tags**.
+1. From the **Tag** dropdown list, select the tag you want to protect.
+1. From the **Allowed to create** list, select the deploy key.
+1. Select **Protect**.
+
## Delete a protected tag
You can manually delete protected tags with the GitLab API, or the
diff --git a/lib/gitlab/utils/error_message.rb b/lib/gitlab/utils/error_message.rb
new file mode 100644
index 00000000000..e9c6f8a5847
--- /dev/null
+++ b/lib/gitlab/utils/error_message.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Utils
+ module ErrorMessage
+ extend self
+
+ def to_user_facing(message)
+ "UF: #{message}"
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d37b657ec8f..56e1df81c06 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -7498,6 +7498,9 @@ msgstr ""
msgid "Branches|Plese type the following to confirm: %{codeStart}delete%{codeEnd}."
msgstr ""
+msgid "Branches|See all branch-related settings together with branch rules"
+msgstr ""
+
msgid "Branches|Show active branches"
msgstr ""
@@ -7543,6 +7546,9 @@ msgstr ""
msgid "Branches|Unable to load branches"
msgstr ""
+msgid "Branches|View branch rules"
+msgstr ""
+
msgid "Branches|Yes, delete branch"
msgstr ""
@@ -7552,6 +7558,9 @@ msgstr ""
msgid "Branches|You are about to %{strongStart}delete all branches%{strongEnd} that were merged into %{codeStart}%{defaultBranch}%{codeEnd}."
msgstr ""
+msgid "Branches|You can now find an overview of settings for protected branches, merge request approvals, status checks, and security approvals conveniently in one spot."
+msgstr ""
+
msgid "Branches|You're about to permanently delete the branch %{branchName}."
msgstr ""
@@ -38848,6 +38857,9 @@ msgstr ""
msgid "SecurityConfiguration|Security training"
msgstr ""
+msgid "SecurityConfiguration|Something went wrong. Please refresh the page, or try again later."
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
diff --git a/spec/controllers/concerns/product_analytics_tracking_spec.rb b/spec/controllers/concerns/product_analytics_tracking_spec.rb
index ed730d5c7f6..b0074b52aa2 100644
--- a/spec/controllers/concerns/product_analytics_tracking_spec.rb
+++ b/spec/controllers/concerns/product_analytics_tracking_spec.rb
@@ -8,7 +8,11 @@ RSpec.describe ProductAnalyticsTracking, :snowplow, feature_category: :product_a
let(:user) { create(:user) }
let(:event_name) { 'an_event' }
+ let(:event_action) { 'an_action' }
+ let(:event_label) { 'a_label' }
+
let!(:group) { create(:group) }
+ let_it_be(:project) { create(:project) }
before do
allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
@@ -23,6 +27,8 @@ RSpec.describe ProductAnalyticsTracking, :snowplow, feature_category: :product_a
:index,
:show,
name: 'an_event',
+ action: 'an_action',
+ label: 'a_label',
destinations: [:redis_hll, :snowplow],
conditions: [:custom_condition_one?, :custom_condition_two?]
) { |controller| controller.get_custom_id }
@@ -49,6 +55,10 @@ RSpec.describe ProductAnalyticsTracking, :snowplow, feature_category: :product_a
Group.first
end
+ def tracking_project_source
+ Project.first
+ end
+
def custom_condition_one?
true
end
@@ -69,7 +79,10 @@ RSpec.describe ProductAnalyticsTracking, :snowplow, feature_category: :product_a
expect_snowplow_event(
category: anything,
- action: event_name,
+ action: event_action,
+ property: event_name,
+ label: event_label,
+ project: project,
namespace: group,
user: user,
context: [context]
diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb
index de71a48d2dc..23a9ab74a7a 100644
--- a/spec/features/admin/admin_health_check_spec.rb
+++ b/spec/features/admin/admin_health_check_spec.rb
@@ -2,8 +2,9 @@
require 'spec_helper'
-RSpec.describe "Admin Health Check", feature_category: :continuous_verification do
+RSpec.describe "Admin Health Check", :js, feature_category: :continuous_verification do
include StubENV
+ include Spec::Support::Helpers::ModalHelpers
let_it_be(:admin) { create(:admin) }
before do
@@ -30,7 +31,8 @@ RSpec.describe "Admin Health Check", feature_category: :continuous_verification
describe 'reload access token' do
it 'changes the access token' do
orig_token = Gitlab::CurrentSettings.health_check_access_token
- click_button 'Reset health check access token'
+ click_link 'Reset health check access token'
+ accept_gl_confirm('Are you sure you want to reset the health check token?')
expect(page).to have_content('New health check access token has been generated!')
expect(find('#health-check-token').text).not_to eq orig_token
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index fc7833809b3..e1f1a63565c 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -201,6 +201,12 @@ RSpec.describe 'Branches', feature_category: :projects do
end
end
+ describe 'Link to branch rules' do
+ it 'does not have possibility to navigate to branch rules', :js do
+ expect(page).not_to have_content(s_("Branches|View branch rules"))
+ end
+ end
+
context 'on project with 0 branch' do
let(:project) { create(:project, :public, :empty_repo) }
let(:repository) { project.repository }
@@ -239,6 +245,17 @@ RSpec.describe 'Branches', feature_category: :projects do
expect(page).not_to have_content 'Merge request'
end
end
+
+ describe 'Navigate to branch rules from branches page' do
+ it 'shows repository settings page with Branch rules section expanded' do
+ visit project_branches_path(project)
+
+ view_branch_rules
+
+ expect(page).to have_content(
+ _('Define rules for who can push, merge, and the required approvals for each branch.'))
+ end
+ end
end
end
@@ -353,4 +370,11 @@ RSpec.describe 'Branches', feature_category: :projects do
click_button 'Yes, delete branch'
end
end
+
+ def view_branch_rules
+ page.within('.nav-controls') do
+ click_link s_("Branches|View branch rules")
+ end
+ wait_for_requests
+ end
end
diff --git a/spec/frontend/lib/utils/error_message_spec.js b/spec/frontend/lib/utils/error_message_spec.js
new file mode 100644
index 00000000000..17b5168c32f
--- /dev/null
+++ b/spec/frontend/lib/utils/error_message_spec.js
@@ -0,0 +1,65 @@
+import { parseErrorMessage, USER_FACING_ERROR_MESSAGE_PREFIX } from '~/lib/utils/error_message';
+
+const defaultErrorMessage = 'Something caused this error';
+const userFacingErrorMessage = 'User facing error message';
+const nonUserFacingErrorMessage = 'NonUser facing error message';
+const genericErrorMessage = 'Some error message';
+
+describe('error message', () => {
+ describe('when given an errormessage object', () => {
+ const errorMessageObject = {
+ options: {
+ cause: defaultErrorMessage,
+ },
+ filename: 'error.js',
+ linenumber: 7,
+ };
+
+ it('returns the correct values for userfacing errors', () => {
+ const userFacingObject = errorMessageObject;
+ userFacingObject.message = `${USER_FACING_ERROR_MESSAGE_PREFIX} ${userFacingErrorMessage}`;
+
+ expect(parseErrorMessage(userFacingObject)).toEqual({
+ message: userFacingErrorMessage,
+ userFacing: true,
+ });
+ });
+
+ it('returns the correct values for non userfacing errors', () => {
+ const nonUserFacingObject = errorMessageObject;
+ nonUserFacingObject.message = nonUserFacingErrorMessage;
+
+ expect(parseErrorMessage(nonUserFacingObject)).toEqual({
+ message: nonUserFacingErrorMessage,
+ userFacing: false,
+ });
+ });
+ });
+
+ describe('when given an errormessage string', () => {
+ it('returns the correct values for userfacing errors', () => {
+ expect(
+ parseErrorMessage(`${USER_FACING_ERROR_MESSAGE_PREFIX} ${genericErrorMessage}`),
+ ).toEqual({
+ message: genericErrorMessage,
+ userFacing: true,
+ });
+ });
+
+ it('returns the correct values for non userfacing errors', () => {
+ expect(parseErrorMessage(genericErrorMessage)).toEqual({
+ message: genericErrorMessage,
+ userFacing: false,
+ });
+ });
+ });
+
+ describe('when given nothing', () => {
+ it('returns an empty error message', () => {
+ expect(parseErrorMessage()).toEqual({
+ message: '',
+ userFacing: false,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index 5ef387adf39..0ca350f9ed7 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -26,6 +26,8 @@ import {
REPORT_TYPE_LICENSE_COMPLIANCE,
REPORT_TYPE_SAST,
} from '~/vue_shared/security_reports/constants';
+import { USER_FACING_ERROR_MESSAGE_PREFIX } from '~/lib/utils/error_message';
+import { manageViaMRErrorMessage } from '../constants';
const upgradePath = '/upgrade';
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
@@ -200,18 +202,21 @@ describe('App component', () => {
});
});
- describe('when error occurs', () => {
+ describe('when user facing error occurs', () => {
it('should show Alert with error Message', async () => {
expect(findManageViaMRErrorAlert().exists()).toBe(false);
- findFeatureCards().at(1).vm.$emit('error', 'There was a manage via MR error');
+ // Prefixed with USER_FACING_ERROR_MESSAGE_PREFIX as used in lib/gitlab/utils/error_message.rb to indicate a user facing error
+ findFeatureCards()
+ .at(1)
+ .vm.$emit('error', `${USER_FACING_ERROR_MESSAGE_PREFIX} ${manageViaMRErrorMessage}`);
await nextTick();
expect(findManageViaMRErrorAlert().exists()).toBe(true);
- expect(findManageViaMRErrorAlert().text()).toEqual('There was a manage via MR error');
+ expect(findManageViaMRErrorAlert().text()).toEqual(manageViaMRErrorMessage);
});
it('should hide Alert when it is dismissed', async () => {
- findFeatureCards().at(1).vm.$emit('error', 'There was a manage via MR error');
+ findFeatureCards().at(1).vm.$emit('error', manageViaMRErrorMessage);
await nextTick();
expect(findManageViaMRErrorAlert().exists()).toBe(true);
@@ -221,6 +226,17 @@ describe('App component', () => {
expect(findManageViaMRErrorAlert().exists()).toBe(false);
});
});
+
+ describe('when non-user facing error occurs', () => {
+ it('should show Alert with generic error Message', async () => {
+ expect(findManageViaMRErrorAlert().exists()).toBe(false);
+ findFeatureCards().at(1).vm.$emit('error', manageViaMRErrorMessage);
+
+ await nextTick();
+ expect(findManageViaMRErrorAlert().exists()).toBe(true);
+ expect(findManageViaMRErrorAlert().text()).toEqual(i18n.genericErrorText);
+ });
+ });
});
describe('Auto DevOps hint alert', () => {
diff --git a/spec/frontend/security_configuration/components/feature_card_spec.js b/spec/frontend/security_configuration/components/feature_card_spec.js
index 7c91c13c6d7..23edd8a69de 100644
--- a/spec/frontend/security_configuration/components/feature_card_spec.js
+++ b/spec/frontend/security_configuration/components/feature_card_spec.js
@@ -5,6 +5,7 @@ import FeatureCard from '~/security_configuration/components/feature_card.vue';
import FeatureCardBadge from '~/security_configuration/components/feature_card_badge.vue';
import ManageViaMr from '~/vue_shared/security_configuration/components/manage_via_mr.vue';
import { REPORT_TYPE_SAST } from '~/vue_shared/security_reports/constants';
+import { manageViaMRErrorMessage } from '../constants';
import { makeFeature } from './utils';
describe('FeatureCard component', () => {
@@ -106,8 +107,8 @@ describe('FeatureCard component', () => {
});
it('should catch and emit manage-via-mr-error', () => {
- findManageViaMr().vm.$emit('error', 'There was a manage via MR error');
- expect(wrapper.emitted('error')).toEqual([['There was a manage via MR error']]);
+ findManageViaMr().vm.$emit('error', manageViaMRErrorMessage);
+ expect(wrapper.emitted('error')).toEqual([[manageViaMRErrorMessage]]);
});
});
diff --git a/spec/frontend/security_configuration/constants.js b/spec/frontend/security_configuration/constants.js
new file mode 100644
index 00000000000..d31036a2534
--- /dev/null
+++ b/spec/frontend/security_configuration/constants.js
@@ -0,0 +1 @@
+export const manageViaMRErrorMessage = 'There was a manage via MR error';
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 7f26190830e..0bfca9a290b 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -291,7 +291,7 @@ RSpec.describe GitlabSchema.types['Project'] do
let_it_be(:project) { create(:project_empty_repo) }
it 'raises an error' do
- expect(subject['errors'][0]['message']).to eq('You must <a target="_blank" rel="noopener noreferrer" ' \
+ expect(subject['errors'][0]['message']).to eq('UF: You must <a target="_blank" rel="noopener noreferrer" ' \
'href="http://localhost/help/user/project/repository/index.md#' \
'add-files-to-a-repository">add at least one file to the ' \
'repository</a> before using Security features.')
diff --git a/spec/lib/gitlab/utils/error_message_spec.rb b/spec/lib/gitlab/utils/error_message_spec.rb
new file mode 100644
index 00000000000..2c2d16656e8
--- /dev/null
+++ b/spec/lib/gitlab/utils/error_message_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Utils::ErrorMessage, feature_category: :error_tracking do
+ let(:klass) do
+ Class.new do
+ include Gitlab::Utils::ErrorMessage
+ end
+ end
+
+ subject(:object) { klass.new }
+
+ describe 'error message' do
+ subject { object.to_user_facing(string) }
+
+ let(:string) { 'Error Message' }
+
+ it "returns input prefixed with UF:" do
+ is_expected.to eq 'UF: Error Message'
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/security/ci_configuration/create_service_shared_examples.rb b/spec/support/shared_examples/services/security/ci_configuration/create_service_shared_examples.rb
index 8bfe57f4549..9fcdd296ebe 100644
--- a/spec/support/shared_examples/services/security/ci_configuration/create_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/security/ci_configuration/create_service_shared_examples.rb
@@ -168,7 +168,7 @@ RSpec.shared_examples_for 'services security ci configuration create service' do
it 'returns an error' do
expect { result }.to raise_error { |error|
expect(error).to be_a(Gitlab::Graphql::Errors::MutationError)
- expect(error.message).to eq('You must <a target="_blank" rel="noopener noreferrer" ' \
+ expect(error.message).to eq('UF: You must <a target="_blank" rel="noopener noreferrer" ' \
'href="http://localhost/help/user/project/repository/index.md' \
'#add-files-to-a-repository">add at least one file to the repository' \
'</a> before using Security features.')