Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-06-03 21:07:19 +00:00
parent 087a4d4a11
commit 4e0a9fbb9b
63 changed files with 441 additions and 445 deletions

View File

@ -2,16 +2,6 @@
# Cop supports --autocorrect.
Lint/SymbolConversion:
Exclude:
- 'app/controllers/groups_controller.rb'
- 'app/controllers/projects/issues_controller.rb'
- 'app/controllers/projects_controller.rb'
- 'app/controllers/uploads_controller.rb'
- 'app/graphql/mutations/members/bulk_update_base.rb'
- 'app/graphql/mutations/snippets/base.rb'
- 'app/graphql/resolvers/award_emoji/base_votes_count_resolver.rb'
- 'app/graphql/resolvers/environments/last_deployment_resolver.rb'
- 'app/graphql/resolvers/user_notes_count_resolver.rb'
- 'app/helpers/notifications_helper.rb'
- 'app/helpers/projects_helper.rb'
- 'app/models/application_record.rb'
- 'app/models/concerns/cache_markdown_field.rb'

View File

@ -257,7 +257,6 @@ gem 'gitlab-active-context', path: 'gems/gitlab-active-context', require: 'activ
gem 'html-pipeline', '~> 2.14.3', feature_category: :markdown
gem 'deckar01-task_list', '2.3.4', feature_category: :markdown
gem 'gitlab-markup', '~> 2.0.0', require: 'github/markup', feature_category: :markdown
gem 'commonmarker', '~> 0.23.10', feature_category: :markdown
gem 'kramdown', '~> 2.5.0', feature_category: :markdown
gem 'RedCloth', '~> 4.3.3', feature_category: :markdown
gem 'org-ruby', '~> 0.9.12', feature_category: :markdown

View File

@ -447,7 +447,7 @@
{"name":"observer","version":"0.1.2","platform":"ruby","checksum":"d8a3107131ba661138d748e7be3dbafc0d82e732fffba9fccb3d7829880950ac"},
{"name":"octokit","version":"9.2.0","platform":"ruby","checksum":"4fa47ff35ce654127edf2c836ab9269bcc8829f5542dc1e86871f697ce7f4316"},
{"name":"ohai","version":"18.1.18","platform":"ruby","checksum":"42ee8196945cb935fdeec93ba7aaee757d1d552f7b933912a1f25863c3cc1ff0"},
{"name":"oj","version":"3.16.10","platform":"ruby","checksum":"7f26bed974e331e16d579b470b0865010757f6fe6ee30ea9b67df653fbe13d7c"},
{"name":"oj","version":"3.16.11","platform":"ruby","checksum":"2aab609d2bc896529bd3c70d737f591c13932a640ba6164a0f7e414efdb052b1"},
{"name":"oj-introspect","version":"0.8.0","platform":"ruby","checksum":"5cbb15309d60294881e5c2f65ceb22e3b5798f26d0a1e65ae47a6342b87d9264"},
{"name":"omniauth","version":"2.1.2","platform":"ruby","checksum":"def03277298b8f8a5d3ff16cdb2eb5edb9bffed60ee7dda24cc0c89b3ae6a0ce"},
{"name":"omniauth-alicloud","version":"3.0.0","platform":"ruby","checksum":"9c5c4f3abb40d774b946015f177d503fbde99b2b57c0858284c25cc39369013e"},

View File

@ -1264,7 +1264,7 @@ GEM
plist (~> 3.1)
train-core
wmi-lite (~> 1.0)
oj (3.16.10)
oj (3.16.11)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
oj-introspect (0.8.0)
@ -2099,7 +2099,6 @@ DEPENDENCIES
circuitbox (= 2.0.0)
click_house-client!
cloud_profiler_agent (~> 0.0.0)!
commonmarker (~> 0.23.10)
concurrent-ruby (~> 1.1)
connection_pool (~> 2.5.3)
countries (~> 4.0.0)

View File

@ -447,7 +447,7 @@
{"name":"observer","version":"0.1.2","platform":"ruby","checksum":"d8a3107131ba661138d748e7be3dbafc0d82e732fffba9fccb3d7829880950ac"},
{"name":"octokit","version":"9.2.0","platform":"ruby","checksum":"4fa47ff35ce654127edf2c836ab9269bcc8829f5542dc1e86871f697ce7f4316"},
{"name":"ohai","version":"18.1.18","platform":"ruby","checksum":"42ee8196945cb935fdeec93ba7aaee757d1d552f7b933912a1f25863c3cc1ff0"},
{"name":"oj","version":"3.16.10","platform":"ruby","checksum":"7f26bed974e331e16d579b470b0865010757f6fe6ee30ea9b67df653fbe13d7c"},
{"name":"oj","version":"3.16.11","platform":"ruby","checksum":"2aab609d2bc896529bd3c70d737f591c13932a640ba6164a0f7e414efdb052b1"},
{"name":"oj-introspect","version":"0.8.0","platform":"ruby","checksum":"5cbb15309d60294881e5c2f65ceb22e3b5798f26d0a1e65ae47a6342b87d9264"},
{"name":"omniauth","version":"2.1.2","platform":"ruby","checksum":"def03277298b8f8a5d3ff16cdb2eb5edb9bffed60ee7dda24cc0c89b3ae6a0ce"},
{"name":"omniauth-alicloud","version":"3.0.0","platform":"ruby","checksum":"9c5c4f3abb40d774b946015f177d503fbde99b2b57c0858284c25cc39369013e"},

View File

@ -1258,7 +1258,7 @@ GEM
plist (~> 3.1)
train-core
wmi-lite (~> 1.0)
oj (3.16.10)
oj (3.16.11)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
oj-introspect (0.8.0)
@ -2094,7 +2094,6 @@ DEPENDENCIES
circuitbox (= 2.0.0)
click_house-client!
cloud_profiler_agent (~> 0.0.0)!
commonmarker (~> 0.23.10)
concurrent-ruby (~> 1.1)
connection_pool (~> 2.5.3)
countries (~> 4.0.0)

View File

@ -86,7 +86,7 @@ export default {
</script>
<template>
<div>
<gl-button v-gl-modal="$options.modal.id" category="secondary">{{
<gl-button v-gl-modal="$options.modal.id" category="secondary" size="small">{{
$options.i18n.title
}}</gl-button>
<gl-modal

View File

@ -52,7 +52,7 @@ export default {
CollapsibleSection,
MergeRequest,
},
inject: ['mergeRequestsSearchDashboardPath', 'listTypeToggleEnabled'],
inject: ['mergeRequestsSearchDashboardPath'],
props: {
tabs: {
type: Array,
@ -263,13 +263,7 @@ export default {
</template>
</gl-tabs>
<div class="gl-mt-6 gl-text-center">
<gl-link
:href="
listTypeToggleEnabled
? 'https://gitlab.com/gitlab-org/gitlab/-/issues/542823'
: 'https://gitlab.com/gitlab-org/gitlab/-/issues/515912'
"
>
<gl-link href="https://gitlab.com/gitlab-org/gitlab/-/issues/542823">
{{ __('Leave feedback') }}
</gl-link>
<span class="gl-mx-2">|</span>

View File

@ -26,9 +26,6 @@ export default {
preferences: {
query: currentUserPreferencesQuery,
update: (data) => data.currentUser.userPreferences,
skip() {
return !this.listTypeToggleEnabled;
},
},
},
components: {
@ -43,7 +40,6 @@ export default {
GlTooltip: GlTooltipDirective,
},
mixins: [InternalEvents.mixin()],
inject: { listTypeToggleEnabled: { default: false } },
data() {
return {
isShowingLabels: null,
@ -53,8 +49,6 @@ export default {
},
computed: {
listTypeItems() {
if (!this.listTypeToggleEnabled) return [];
return [
{
text: __('Group by'),
@ -147,7 +141,7 @@ export default {
:title="__('Change display preferences')"
no-caret
text-sr-only
:header-text="listTypeToggleEnabled ? __('Change display preferences') : null"
:header-text="__('Change display preferences')"
:toggle-text="__('Change display preferences')"
placement="bottom-end"
:loading="savingPreferences"
@ -161,11 +155,7 @@ export default {
</template>
<template #footer>
<div
class="gl-flex gl-flex-col gl-px-4 gl-py-3"
:class="{
'gl-border-t-1 gl-border-t-dropdown-divider gl-border-t-solid': listTypeToggleEnabled,
'toggle-labels-footer': !listTypeToggleEnabled,
}"
class="gl-flex gl-flex-col gl-border-t-1 gl-border-t-dropdown-divider gl-px-4 gl-py-3 gl-border-t-solid"
>
<local-storage-sync
:value="isShowingLabels"
@ -181,10 +171,7 @@ export default {
</div>
</template>
</gl-collapsible-listbox>
<user-callout-dismisser
v-if="listTypeToggleEnabled"
feature-name="merge_request_dashboard_display_preferences_popover"
>
<user-callout-dismisser feature-name="merge_request_dashboard_display_preferences_popover">
<template #default="{ shouldShowCallout, dismiss }">
<gl-popover
v-if="shouldShowCallout"
@ -212,9 +199,3 @@ export default {
</user-callout-dismisser>
</div>
</template>
<style>
div:has(+ .toggle-labels-footer) {
display: none;
}
</style>

View File

@ -2,7 +2,6 @@ import { concatPagination } from '@apollo/client/utilities';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import VueRouter from 'vue-router';
import { parseBoolean } from '~/lib/utils/common_utils';
import { TYPENAME_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import createDefaultClient from '~/lib/graphql';
@ -104,9 +103,6 @@ export function initMergeRequestDashboard(el) {
new Vue({
el: document.getElementById('js-merge-request-dashboard-config'),
apolloProvider,
provide: {
listTypeToggleEnabled: parseBoolean(el.dataset.listTypeToggleEnabled),
},
render(h) {
return h(ConfigDropdown);
},
@ -118,7 +114,6 @@ export function initMergeRequestDashboard(el) {
apolloProvider,
provide: {
mergeRequestsSearchDashboardPath: el.dataset.mergeRequestsSearchDashboardPath,
listTypeToggleEnabled: parseBoolean(el.dataset.listTypeToggleEnabled),
},
render(createElement) {
return createElement(App, {

View File

@ -114,6 +114,12 @@
@include str-highlighted;
}
// the z-index of the mark is set to -1, so it's below the table cells
// unless they have their own stacking context
td:has(mark), th:has(mark) {
isolation: isolate;
}
// Fixed headings are default for markdown
h1 {
@apply gl-heading-1-fixed gl-mt-7 gl-pb-2 gl-border-b;

View File

@ -364,7 +364,7 @@ class GroupsController < Groups::ApplicationController
end
def check_export_rate_limit!
prefixed_action = "group_#{params[:action]}".to_sym
prefixed_action = :"group_#{params[:action]}"
scope = params[:action] == :download_export ? @group : nil

View File

@ -438,7 +438,7 @@ class Projects::IssuesController < Projects::ApplicationController
errors: result.errors,
http_status: result.http_status
)
error_method_name = "render_#{result.http_status}".to_sym
error_method_name = :"render_#{result.http_status}"
if respond_to?(error_method_name, true)
send(error_method_name) # rubocop:disable GitlabSecurity/PublicSend

View File

@ -636,7 +636,7 @@ class ProjectsController < Projects::ApplicationController
end
def check_export_rate_limit!
prefixed_action = "project_#{params[:action]}".to_sym
prefixed_action = :"project_#{params[:action]}"
project_scope = params[:action] == 'download_export' ? @project : nil

View File

@ -69,7 +69,7 @@ class UploadsController < ApplicationController
when Organizations::OrganizationDetail
can?(current_user, :read_organization, model.organization)
else
can?(current_user, "read_#{model.class.underscore}".to_sym, model)
can?(current_user, :"read_#{model.class.underscore}", model)
end
end

View File

@ -68,11 +68,11 @@ module Mutations
end
def source_id_param_name
"#{source_name}_id".to_sym
:"#{source_name}_id"
end
def source_members_key
"#{source_name}_members".to_sym
:"#{source_name}_members"
end
def source_name

View File

@ -17,7 +17,7 @@ module Mutations
end
def ability_for(snippet)
"#{ability_name}_#{snippet.to_ability_name}".to_sym
:"#{ability_name}_#{snippet.to_ability_name}"
end
def ability_name

View File

@ -10,7 +10,7 @@ module Resolvers
private
def authorized_resource?(object)
Ability.allowed?(current_user, "read_#{object.to_ability_name}".to_sym, object)
Ability.allowed?(current_user, :"read_#{object.to_ability_name}", object)
end
def votes_batch_loader

View File

@ -22,7 +22,7 @@ module Resolvers
def find_last_deployment(status)
BatchLoader::GraphQL.for(object).batch(key: status) do |environments, loader, args|
association_name = "last_#{args[:key]}_deployment".to_sym
association_name = :"last_#{args[:key]}_deployment"
Preloaders::Environments::DeploymentPreloader.new(environments)
.execute_with_union(association_name, {})

View File

@ -13,7 +13,7 @@ module Resolvers
end
def authorized_resource?(object)
ability = "read_#{object.class.name.underscore}".to_sym
ability = :"read_#{object.class.name.underscore}"
Ability.allowed?(context[:current_user], ability, object)
end

View File

@ -566,10 +566,7 @@ module MergeRequestsHelper
is_author_or_assignee = ::Feature.enabled?(:merge_request_dashboard_author_or_assignee, current_user,
type: :gitlab_com_derisk)
if Feature.enabled?(:mr_dashboard_list_type_toggle, current_user, type: :beta) &&
current_user.merge_request_dashboard_list_type == 'role_based'
return merge_request_dashboard_role_based_data
end
return merge_request_dashboard_role_based_data if current_user.user_preference.role_based?
{
tabs: [

View File

@ -36,7 +36,7 @@ module NotificationsHelper
end
def show_unsubscribe_title?(noteable)
can?(current_user, "read_#{noteable.to_ability_name}".to_sym, noteable)
can?(current_user, :"read_#{noteable.to_ability_name}", noteable)
end
def can_read_project?(project)

View File

@ -87,6 +87,54 @@
},
"additionalProperties": false
},
"^aws_secrets_manager$": {
"type": "object",
"required": [
"secret_id"
],
"properties": {
"secret_id": {
"type": "string"
},
"version_id": {
"type": [
"string",
"null"
]
},
"version_stage": {
"type": [
"string",
"null"
]
},
"region": {
"type": [
"string",
"null"
]
},
"role_arn": {
"type": [
"string",
"null"
]
},
"role_session_name": {
"type": [
"string",
"null"
]
},
"field": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
},
"^akeyless$": {
"type": "object",
"properties": {
@ -215,6 +263,11 @@
"required": [
"gitlab_secrets_manager"
]
},
{
"required": [
"aws_secrets_manager"
]
}
],
"additionalProperties": false

View File

@ -1,7 +1,7 @@
- topic = local_assigns.fetch(:topic)
- title = topic.title || topic.name
%li.topic-row.gl-py-3.gl-items-center{ class: '!gl-flex !gl-px-5' }
%li.gl-items-center{ class: '!gl-flex' }
= render Pajamas::AvatarComponent.new(topic, size: 32, alt: '')
.gl-min-w-0.gl-grow.gl-ml-3
@ -17,5 +17,5 @@
= number_with_delimiter(topic.total_projects_count)
.gl-shrink-0.gl-ml-5.gl-flex.gl-gap-3
= link_button_to _('Edit'), edit_admin_topic_path(topic), id: "edit_#{dom_id(topic)}"
= link_button_to _('Remove'), admin_topic_path(topic), aria: { label: _('Remove') }, data: { confirm: _("Are you sure you want to remove %{topic_name}?") % { topic_name: title }, confirm_btn_variant: 'danger' }, method: :delete, variant: :danger
= render Pajamas::ButtonComponent.new(category: :tertiary, href: edit_admin_topic_path(topic), icon: 'pencil', button_options: { id: "edit_#{dom_id(topic)}", class: 'has-tooltip', 'title': _('Edit'), 'aria-label': _('Edit') })
= render Pajamas::ButtonComponent.new(category: :tertiary, href: admin_topic_path(topic), method: :delete, icon: 'remove', button_options: { class: 'has-tooltip', 'title': _('Remove'), 'aria-label': _('Remove'), data: { confirm: _("Are you sure you want to remove %{topic_name}?") % { topic_name: title }, confirm_btn_variant: 'danger' } })

View File

@ -7,13 +7,9 @@
- if show_empty_state
= render 'shared/empty_states/topics', button_text: _('New topic'), button_path: new_admin_topic_path
- else
= render ::Layouts::PageHeadingComponent.new(_('Topics'), options: { data: { event_tracking_load: 'true', event_tracking: 'view_admin_topics_pageload' } }) do |c|
- c.with_actions do
.js-merge-topics{ data: { path: merge_admin_topics_path } }
= render Pajamas::ButtonComponent.new(href: new_admin_topic_path, variant: 'confirm') do
= _('New topic')
= render ::Layouts::PageHeadingComponent.new(_('Topics'), options: { data: { event_tracking_load: 'true', event_tracking: 'view_admin_topics_pageload' } })
.gl-flex.gl-min-w-0.gl-grow.row-content-block
.gl-flex.gl-min-w-0.gl-grow
= form_tag admin_topics_path, method: :get, class: 'gl-w-full' do |f|
- search = params.fetch(:search, nil)
.search-field-holder
@ -23,6 +19,15 @@
- if show_empty_search
= render ::Layouts::EmptyResultComponent.new(type: :search)
- else
%ul.content-list
= render partial: 'topic', collection: @topics
= paginate_collection @topics
= render ::Layouts::CrudComponent.new(_('Topics'),
icon: 'overview',
count: @topics.count,
options: { class: 'gl-mt-5' }) do |c|
- c.with_actions do
.js-merge-topics{ data: { path: merge_admin_topics_path } }
= render Pajamas::ButtonComponent.new(href: new_admin_topic_path, variant: 'confirm', size: 'small') do
= _('New topic')
- c.with_body do
%ul.content-list
= render partial: 'topic', collection: @topics
= paginate_collection @topics

View File

@ -34,8 +34,7 @@
base_path: merge_requests_dashboard_path,
merge_requests_search_dashboard_path: merge_requests_search_dashboard_path(assignee_username: current_user.username),
initial_data: merge_request_dashboard_data.to_json,
list_type: current_user.merge_request_dashboard_list_type,
list_type_toggle_enabled: Feature.enabled?(:mr_dashboard_list_type_toggle, current_user, type: :beta).to_s
list_type: current_user.merge_request_dashboard_list_type
} }
- if !merge_request_dashboard_enabled?(current_user) || current_page?(merge_requests_search_dashboard_path)

View File

@ -1,4 +1,4 @@
= render ::Layouts::PageHeadingComponent.new(page_title)
.gl-flex.gl-min-w-0.gl-grow.row-content-block
.gl-flex.gl-min-w-0.gl-grow
= render 'shared/topics/search_form'

View File

@ -5,6 +5,11 @@
- if show_empty_search
= render ::Layouts::EmptyResultComponent.new(type: :search)
- else
%ul.content-list
= render partial: 'shared/topics/topic', collection: @topics
= paginate_collection @topics, remote: remote
= render ::Layouts::CrudComponent.new(_('Topics'),
icon: 'overview',
count: @topics.count,
options: { class: 'gl-mt-5' }) do |c|
- c.with_body do
%ul.content-list
= render partial: 'shared/topics/topic', collection: @topics
= paginate_collection @topics, remote: remote

View File

@ -1,7 +1,7 @@
- max_topic_title_length = 30
- detail_page_link = topic_explore_projects_cleaned_path(topic_name: topic.name)
%li.topic-row.gl-py-3.gl-items-center{ class: '!gl-flex !gl-px-5' }
%li.gl-items-center{ class: '!gl-flex' }
= render Pajamas::AvatarComponent.new(topic, size: 32, alt: '')
.gl-min-w-0.gl-grow.gl-ml-3

View File

@ -1,9 +0,0 @@
---
name: mr_dashboard_list_type_toggle
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/519717
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183805
rollout_issue_url:
milestone: '17.11'
group: group::code review
type: beta
default_enabled: false

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
class AddOidToLfsObjectsProjects < Gitlab::Database::Migration[2.3]
disable_ddl_transaction!
milestone '18.1'
SOURCE_TABLE = :lfs_objects_projects
def up
with_lock_retries do
add_column SOURCE_TABLE, :oid, :text, if_not_exists: true
end
add_text_limit SOURCE_TABLE, :oid, 255
end
def down
with_lock_retries do
remove_column SOURCE_TABLE, :oid, if_exists: true
end
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class AsyncAddIndexCiBuildReportResultsOnBuildIdPartitionId < Gitlab::Database::Migration[2.3]
milestone '18.1'
TABLE_NAME = :ci_build_report_results
INDEX_NAME = :index_ci_build_report_results_on_build_id_partition_id
COLUMNS = [:build_id, :partition_id]
def up
prepare_async_index TABLE_NAME, COLUMNS, unique: true, name: INDEX_NAME
end
def down
unprepare_async_index TABLE_NAME, COLUMNS, name: INDEX_NAME
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class AsyncRemoveIndexCiBuildReportResultsOnPartitionIdBuildId < Gitlab::Database::Migration[2.3]
milestone '18.1'
TABLE_NAME = :ci_build_report_results
INDEX_NAME = :index_ci_build_report_results_on_partition_id_build_id
COLUMNS = [:partition_id, :build_id]
def up
prepare_async_index_removal TABLE_NAME, COLUMNS, name: INDEX_NAME
end
def down
unprepare_async_index TABLE_NAME, COLUMNS, name: INDEX_NAME
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class AddIndexOfOidToLfsObjectsProjects < Gitlab::Database::Migration[2.3]
disable_ddl_transaction!
milestone '18.1'
INDEX_NAME = 'index_lfs_objects_projects_on_oid'
def up
add_concurrent_index :lfs_objects_projects, :oid, name: INDEX_NAME
end
def down
remove_concurrent_index :lfs_objects_projects, :oid, name: INDEX_NAME
end
end

View File

@ -0,0 +1 @@
dc035d87698c43babf8f8093c49edbc684c6f840a5457d0405c9498b5f174e70

View File

@ -0,0 +1 @@
07392d9229e61122a4aa4264811246740a40c0d5039d7c99018829bd34f69329

View File

@ -0,0 +1 @@
ffbd42a63d4a4c08b8e74257d865e3ddcc2f40e43cbf4a898e069be90fff2462

View File

@ -0,0 +1 @@
e94d4888d721b88a874b095c08aac988e3ac1f501586417379cba65ad9bb984b

View File

@ -16723,7 +16723,9 @@ CREATE TABLE lfs_objects_projects (
project_id bigint NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone,
repository_type smallint
repository_type smallint,
oid text,
CONSTRAINT check_76ef4585ad CHECK ((char_length(oid) <= 255))
);
CREATE SEQUENCE lfs_objects_projects_id_seq
@ -35814,6 +35816,8 @@ CREATE UNIQUE INDEX index_lfs_objects_on_oid ON lfs_objects USING btree (oid);
CREATE INDEX index_lfs_objects_projects_on_lfs_object_id ON lfs_objects_projects USING btree (lfs_object_id);
CREATE INDEX index_lfs_objects_projects_on_oid ON lfs_objects_projects USING btree (oid);
CREATE INDEX index_lfs_objects_projects_on_project_id_and_lfs_object_id ON lfs_objects_projects USING btree (project_id, lfs_object_id);
CREATE INDEX index_list_user_preferences_on_list_id ON list_user_preferences USING btree (list_id);

View File

@ -41,9 +41,7 @@ This pipeline contains the filters for transforming raw Markdown into HTML, hand
#### `Filter::MarkdownFilter`
This filter interfaces with the actual Markdown parser. The primary parser uses our [`gitlab-glfm-markdown`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-glfm-markdown) Ruby gem that uses the [`comrak`](https://github.com/kivikakk/comrak) Rust crate.
A secondary deprecated parser engine uses the [`commonmarker`](https://github.com/gjtorikian/commonmarker/releases/tag/v0.23.11) Ruby gem to interact with the [`cmark-gfm`](https://github.com/github/cmark-gfm) library.
This filter interfaces with the actual Markdown parser. The parser uses our [`gitlab-glfm-markdown`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-glfm-markdown) Ruby gem that uses the [`comrak`](https://github.com/kivikakk/comrak) Rust crate.
Text is passed into this filter, and by calling the specified parser engine, generates the corresponding basic HTML.

View File

@ -401,7 +401,7 @@ This ensures your policy always reflects the most current Blue Oak Council licen
### Policy not applying
Ensure the security policy project you modified is correctly linked to your group. See [Link to a security policy project](../../user/application_security/policies/_index.md#link-to-a-security-policy-project) for more.
Ensure the security policy project you modified is correctly linked to your group. See [Link to a security policy project](../../user/application_security/policies/security_policy_projects.md#link-to-a-security-policy-project) for more.
### Dependency scan not running

View File

@ -161,4 +161,4 @@ An example password in clear is shown below:
### Policy not applying
Ensure the security policy project you modified is correctly linked to your group. See [Link to a security policy project](../../user/application_security/policies/_index.md#link-to-a-security-policy-project) for more.
Ensure the security policy project you modified is correctly linked to your group. See [Link to a security policy project](../../user/application_security/policies/security_policy_projects.md#link-to-a-security-policy-project) for more.

View File

@ -41,42 +41,7 @@ The following policy types are available:
- [Vulnerability management policy](vulnerability_management_policy.md). Automatically resolve
vulnerabilities that are no longer detected in the default branch.
## Security policy project
A security policy project is a special type of project used only to contain policies. The
policies are stored in the `.gitlab/security-policies/policy.yml` YAML file.
To enforce the policies contained in a security policy project, link the security policy
project to the projects, subgroups, or groups you want to enforce the policies on.
A security policy project can contain multiple policies but they are
enforced together. A security policy project enforced on a group or subgroup applies to everything
below in the hierarchy, including all subgroups and their projects.
Policy changes made in a merge request take effect as soon as the merge request is merged. Those
that do not go through a merge request, but instead are committed directly to the default branch,
may require up to 10 minutes before the policy changes take effect.
## Deleting security policy projects
{{< history >}}
- The deletion protection for security policy projects was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/482967) in GitLab 17.8 [with a flag](../../../administration/feature_flags.md) named `reject_security_policy_project_deletion`. Enabled by default.
- The deletion protection for groups that contain security policy projects was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/512043) in GitLab 17.9 [with a flag](../../../administration/feature_flags.md) named `reject_security_policy_project_deletion_groups`. Enabled by default.
- The deletion protection for security policy projects is generally available in GitLab 17.10. Feature flag `reject_security_policy_project_deletion` removed.
- The deletion protection for groups that contain security policy projects is generally available in GitLab 17.10. Feature flag `reject_security_policy_project_deletion_groups` removed.
{{< /history >}}
{{< alert type="flag" >}}
The availability of this feature is controlled by a feature flag.
For more information, see the history.
{{< /alert >}}
To delete a security policy project or one of its parent groups, you must remove the link to it
from all other projects or groups. Otherwise, an error message is displayed when you attempt
to delete a linked security policy project or a parent group.
To enforce policies across multiple projects, use [security policy projects](security_policy_projects.md). A security policy project is a special type of project used only to contain policies. To enforce the policies from a security policy project in other groups and projects, link to the security policy project from groups or other projects.
## Policy design guidelines
@ -280,147 +245,6 @@ If you're not a group member, you may face limitations in adding or editing poli
{{< /alert >}}
## Policy implementation
Implementation options for security policy projects differ slightly between GitLab.com, GitLab
Dedicated, and GitLab Self-Managed. The main difference is that on GitLab.com it's only possible to
create subgroups. Ensuring separation of duties requires more granular permission configuration.
### Enforce policies globally in your GitLab.com namespace
{{< details >}}
- Tier: Ultimate
- Offering: GitLab.com
{{< /details >}}
Prerequisites:
- You must have the Owner role or [custom role](../../custom_roles/_index.md) with the
`manage_security_policy_link` permission to link to the security policy project. For more
information, see [separation of duties](#separation-of-duties).
The high-level workflow for enforcing policies globally across all subgroups and projects in your GitLab.com namespace:
1. Visit the **Policies** tab from your top-level group.
1. In the subgroup, go to the **Policies** tab and create a test policy.
(Tip: You can create a policy as disabled for testing.) Creating the policy automatically creates
a new security policy project under your top-level group. This project is used to store your
`policy.yml` or policy-as-code.
1. Check and set permissions in the newly created project as desired.
By default, Owners and Maintainers are able to create, edit, and delete policies. Developers can
propose policy changes but cannot merge them.
1. In the security policy project created within your subgroup, create the policies required.
You can use the policy editor in the `Security Policy Management` project you created, under the
**Policies** tab. Or you can directly update the policies in the `policy.yml` file stored in the
newly-created security policy project `Security Policy Management - security policy project`.
1. Link up groups, subgroups, or projects to the security policy project.
As a subgroup owner, or project owner with proper permissions, you can visit the **Policies**
page and create a link to the security policy project. Include the full path and the project's
name should end with "- security policy project". All linked groups, subgroups, and projects
become "enforceable" by any policies created in the security policy project. For details, see
[Link to a security policy project](#link-to-a-security-policy-project).
1. By default, when a policy is enabled, it is enforced on all projects in linked groups,
subgroups, and projects.
For more granular enforcement, add a "policy scope". Policy scopes allow you to enforce policies
against a specific set of projects or against projects containing a given set of compliance
framework labels.
1. If you need additional restrictions, for example to block inherited permissions or require
additional review or approval of policy changes, you can create an additional policy scoped only
to your security policy project and enforce additional approvals.
### Enforce policies globally in GitLab Dedicated or GitLab Self-Managed
{{< details >}}
- Tier: Ultimate
- Offering: GitLab Self-Managed, GitLab Dedicated
{{< /details >}}
Prerequisites:
- You must have the Owner role or [custom role](../../custom_roles/_index.md) with the
`manage_security_policy_link` permission to link to the security policy project. For more
information, see [separation of duties](#separation-of-duties).
- To support approval groups globally across your instance, enable
`security_policy_global_group_approvers_enabled` in your
[GitLab instance application settings](../../../api/settings.md).
The high-level workflow for enforcing policies across multiple groups:
1. Create a separate group to contain your policies and ensure separation of duties.
By creating a separate standalone group, you can minimize the number of users who inherit
permissions.
1. In the new group, visit the **Policies** tab.
This serves as the primary location of the policy editor, allowing you to
create and manage policies in the UI.
1. Create a test policy (you can create a policy as disabled for testing).
Creating the policy automatically creates a new security policy project under your group. This
project is used to store your `policy.yml` or policy-as-code.
1. Check and set permissions in the newly created project as desired.
By default, Owners and Maintainers are able to create, edit, and delete policies. Developers can
propose policy changes but cannot merge them.
1. In the security policy project created in your subgroup, create the policies required.
You can use the policy editor in the `Security Policy Management` project you created, under the
Policies tab. Or you can directly update the policies in the `policy.yml` file stored in the
newly-created security policy project `Security Policy Management - security policy project`.
1. Link up groups, subgroups, or projects to the security policy project.
As a subgroup owner, or project owner with proper permissions, you can visit the **Policies**
page and create a link to the security policy project. Include the full path and the project's
name should end with "-security policy project". All linked groups, subgroups, and projects
become "enforceable" by any policies created in the security policy project. For more information, see
[link to a security policy project](#link-to-a-security-policy-project).
1. By default, when a policy is enabled, it is enforced on all projects in linked groups, subgroups,
and projects. For more granular enforcement, add a policy scope. Policy scopes allow you to
enforce policies against a specific set of projects or against projects containing a given set of
compliance framework labels.
1. If you need additional restrictions, for example to block inherited permissions or require
additional review or approval of policy changes, you can create an additional policy scoped only
to your security policy project and enforce additional approvals.
## Link to a security policy project
To enforce the policies contained in a security policy project against a group, subgroup, or
project, you link them. By default, all linked entities are enforced. To enforce policies
granularly per policy, you can set a "policy scope" in each policy.
Prerequisites:
- You must have the Owner role or [custom role](../../custom_roles/_index.md) with the`manage_security_policy_link` permission to link to the security policy project. For more information, see [separation of duties](#separation-of-duties).
- You must have at least the Reporter role or [custom role](../../custom_roles/_index.md) with the `manage_security_policy_link` permission to the project you want to assign as the security policy project. For more information, see [separation of duties](#separation-of-duties).
To link a group, subgroup, or project to a security policy project:
1. On the left sidebar, select **Search or go to** and find your project, subgroup, or group.
1. Select **Secure > Policies**.
1. Select **Edit Policy Project**, then search for and select the project you would like to link
from the dropdown list.
1. Select **Save**.
To unlink a security policy project, follow the same steps but instead select the trash can icon in
the dialog.
You can link to a security policy project from a different subgroup in the same top-level group, or from an entirely different top-level group.
However, when you enforce a
[pipeline execution policy](pipeline_execution_policies.md#pipeline-execution-policy-schema), users must have at least read-only access to the project that contains the CI/CD configuration referenced in the policy to trigger the pipeline.
### Viewing the linked security policy project
All users who have access to the project policy page and are not project owners instead view a
button linking out to the associated security policy project.
## Policy recommendations
When implementing policies, consider the following recommendations.

View File

@ -450,7 +450,7 @@ The availability of support for pipeline execution policies is controlled by a f
#### Example of `policy_tuning` with a scan execution policy
You can use this example in a `.gitlab/security-policies/policy.yml` file stored in a
[security policy project](_index.md#security-policy-project):
[security policy project](security_policy_projects.md):
```yaml
scan_execution_policy:
@ -504,7 +504,7 @@ For more information, see [Recreate pipeline execution policies created before G
{{< /alert >}}
You can use this example in a `.gitlab/security-policies/policy.yml` file stored in a
[security policy project](_index.md#security-policy-project):
[security policy project](security_policy_projects.md):
```yaml
---
@ -559,7 +559,7 @@ specified projects, groups, or compliance framework labels. For more details, se
## Example `policy.yml` in a security policy project
You can use this example in a `.gitlab/security-policies/policy.yml` file stored in a
[security policy project](_index.md#security-policy-project):
[security policy project](security_policy_projects.md):
```yaml
---

View File

@ -815,7 +815,7 @@ These examples demonstrate what you can achieve with pipeline execution policies
### Pipeline execution policy
You can use the following example in a `.gitlab/security-policies/policy.yml` file stored in a
[security policy project](_index.md#security-policy-project):
[security policy project](security_policy_projects.md):
```yaml
---

View File

@ -469,7 +469,7 @@ specified projects, groups, or compliance framework labels. For more details, se
## Example security policy project
You can use this example in a `.gitlab/security-policies/policy.yml` file stored in a
[security policy project](_index.md#security-policy-project):
[security policy project](security_policy_projects.md):
```yaml
---

View File

@ -0,0 +1,182 @@
---
stage: Security Risk Management
group: Security Policies
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Learn how to enforce security rules in GitLab using merge request approval policies to automate scans, approvals, and compliance across your projects.
title: Security policy projects
---
{{< details >}}
- Tier: Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
{{< /details >}}
Security policy projects enforce policies across multiple projects. A security policy project is a
special type of project used only to contain policies. To enforce the policies contained in a
security policy project, link the security policy project to the projects, subgroups, or groups
you want to enforce the policies on. A security policy project can contain multiple policies but they are
enforced together. A security policy project enforced on a group or subgroup applies to everything
below in the hierarchy, including all subgroups and their projects.
Policy changes made in a merge request take effect as soon as the merge request is merged. Those
that do not go through a merge request, but instead are committed directly to the default branch,
may require up to 10 minutes before the policy changes take effect.
Policies are stored in the `.gitlab/security-policies/policy.yml` YAML file.
## Security policy project implementation
Implementation options for security policy projects differ slightly between GitLab.com, GitLab
Dedicated, and GitLab Self-Managed. The main difference is that on GitLab.com it's only possible to
create subgroups. Ensuring separation of duties requires more granular permission configuration.
### Enforce policies globally in your GitLab.com namespace
{{< details >}}
- Tier: Ultimate
- Offering: GitLab.com
{{< /details >}}
Prerequisites:
- You must have the Owner role or a [custom role](../../custom_roles/_index.md) with the
`manage_security_policy_link` permission to link to the security policy project. For more
information, see [separation of duties](_index.md#separation-of-duties).
The high-level workflow for enforcing policies globally across all subgroups and projects in your GitLab.com namespace:
1. Visit the **Policies** tab from your top-level group.
1. In the subgroup, go to the **Policies** tab and create a test policy.
You can create a policy as disabled for testing. Creating the policy automatically creates
a new security policy project under your top-level group. This project is used to store your
`policy.yml` or policy-as-code.
1. Check and set permissions in the newly created project as desired.
By default, Owners and Maintainers are able to create, edit, and delete policies. Developers can
propose policy changes but cannot merge them.
1. In the security policy project created within your subgroup, create the policies required.
You can use the policy editor in the `Security Policy Management` project you created, under the
**Policies** tab. Or you can directly update the policies in the `policy.yml` file stored in the
newly-created security policy project `Security Policy Management - security policy project`.
1. Link up groups, subgroups, or projects to the security policy project.
As a subgroup owner, or project owner with proper permissions, you can visit the **Policies**
page and create a link to the security policy project. Include the full path and the project's
name should end with "- security policy project". All linked groups, subgroups, and projects
become "enforceable" by any policies created in the security policy project. For details, see
[Link to a security policy project](#link-to-a-security-policy-project).
1. By default, when a policy is enabled, it is enforced on all projects in linked groups,
subgroups, and projects.
For more granular enforcement, add a policy scope. A policy scope allow you to enforce policies
against a specific set of projects or against projects containing a set of compliance
framework labels.
1. If you need additional restrictions, for example to block inherited permissions or require
additional review or approval of policy changes, you can create an additional policy scoped only
to your security policy project and enforce additional approvals.
### Enforce policies globally in GitLab Dedicated or GitLab Self-Managed
{{< details >}}
- Tier: Ultimate
- Offering: GitLab Self-Managed, GitLab Dedicated
{{< /details >}}
Prerequisites:
- You must have the Owner role or a [custom role](../../custom_roles/_index.md) with the
`manage_security_policy_link` permission to link to the security policy project. For more
information, see [separation of duties](_index.md#separation-of-duties).
- To support approval groups globally across your instance, enable
`security_policy_global_group_approvers_enabled` in your
[GitLab instance application settings](../../../api/settings.md).
The high-level workflow for enforcing policies across multiple groups:
1. Create a separate group to contain your policies and ensure separation of duties.
By creating a separate standalone group, you can minimize the number of users who inherit
permissions.
1. In the new group, visit the **Policies** tab.
This serves as the primary location of the policy editor, allowing you to
create and manage policies in the UI.
1. Create a test policy (you can create a policy as disabled for testing).
Creating the policy automatically creates a new security policy project under your group. This
project is used to store your `policy.yml` or policy-as-code.
1. Check and set permissions in the newly created project as desired.
By default, Owners and Maintainers are able to create, edit, and delete policies. Developers can
propose policy changes but cannot merge them.
1. In the security policy project created in your subgroup, create the policies required.
You can use the policy editor in the `Security Policy Management` project you created, under the
Policies tab. Or you can directly update the policies in the `policy.yml` file stored in the
newly-created security policy project `Security Policy Management - security policy project`.
1. Link up groups, subgroups, or projects to the security policy project.
As a subgroup owner, or project owner with proper permissions, you can visit the **Policies**
page and create a link to the security policy project. Include the full path and the project's
name should end with "- security policy project". All linked groups, subgroups, and projects
become "enforceable" by any policies created in the security policy project. For more information, see
[link to a security policy project](#link-to-a-security-policy-project).
1. By default, when a policy is enabled, it is enforced on all projects in linked groups, subgroups,
and projects. For more granular enforcement, add a policy scope. A policy scope allows you to
enforce policies against a specific set of projects or against projects that contain a set of
compliance framework labels.
1. If you need additional restrictions, for example to block inherited permissions or require
additional review or approval of policy changes, you can create an additional policy scoped only
to your security policy project and enforce additional approvals.
## Link to a security policy project
To enforce the policies contained in a security policy project against a group, subgroup, or
project, you link them. By default, all linked entities are enforced. To enforce policies
granularly per policy, you can set a policy scope in each policy.
Prerequisites:
- You must have the Owner role or [custom role](../../custom_roles/_index.md) with the`manage_security_policy_link` permission to link to the security policy project. For more information, see [separation of duties](_index.md#separation-of-duties).
- You must have at least the Reporter role or [custom role](../../custom_roles/_index.md) with the `manage_security_policy_link` permission to the project you want to assign as the security policy project. For more information, see [separation of duties](_index.md#separation-of-duties).
To link a group, subgroup, or project to a security policy project:
1. On the left sidebar, select **Search or go to** and find your project, subgroup, or group.
1. Select **Secure > Policies**.
1. Select **Edit Policy Project**, then search for and select the project you would like to link
from the dropdown list.
1. Select **Save**.
To unlink a security policy project, follow the same steps but instead select the trash can icon in
the dialog.
You can link to a security policy project from a different subgroup in the same top-level group, or from an entirely different top-level group.
However, when you enforce a
[pipeline execution policy](pipeline_execution_policies.md#pipeline-execution-policy-schema), users must have at least read-only access to the project that contains the CI/CD configuration referenced in the policy to trigger the pipeline.
### Viewing the linked security policy project
All users who have access to the project policy page and are not project owners instead view a
button linking out to the associated security policy project.
## Deleting a security policy project
{{< history >}}
- Deletion protection for security policy projects was introduced in GitLab 17.8 with a flag named `reject_security_policy_project_deletion`. Enabled by default.
- Deletion protection for groups that contain security policy projects was introduced in GitLab 17.9 with a flag named `reject_security_policy_project_deletion_groups`. Enabled by default.
- Deletion protection for security policy projects and groups that contain security policy projects is generally available in GitLab 17.10. Feature flags `reject_security_policy_project_deletion` and `reject_security_policy_project_deletion_groups` removed.
{{< /history >}}
To delete a security policy project or one of its parent groups, you must remove the link to it
from all other projects or groups. Otherwise, an error message is displayed when you attempt
to delete a linked security policy project or a parent group.

View File

@ -70,7 +70,7 @@ To migrate an existing compliance framework to use the pipeline execution policy
1. In the banner than appears, select **Migrate pipeline to a policy** to create a new policy in the security policies.
1. Edit the compliance framework again to remove the compliance pipeline.
For more information, see [Security policy project](../application_security/policies/_index.md#security-policy-project).
For more information, see [Security policy project](../application_security/policies/security_policy_projects.md).
If you receive a `Pipeline execution policy error: Job names must be unique` error during the migration, see the
[relevant troubleshooting information](#error-job-names-must-be-unique).

View File

@ -53,7 +53,7 @@ Create a license approval policy to enforce license compliance.
To create a license approval policy:
1. [Link a security policy project](../application_security/policies/_index.md#policy-implementation) to your development group, subgroup, or project (the Owner role is required).
1. [Link a security policy project](../application_security/policies/security_policy_projects.md#link-to-a-security-policy-project) to your development group, subgroup, or project (the Owner role is required).
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Secure > Policies**.
1. Create a new [Merge request approval Policy](../application_security/policies/merge_request_approval_policies.md).

View File

@ -124,7 +124,7 @@ module Banzai
end
# Since this came from a Text node, make sure the new href is encoded.
# `commonmarker` percent encodes the domains of links it handles, so
# Markdown renderer percent encodes the domains of links it handles, so
# do the same (instead of using `normalized_encode`).
begin
href_safe = Addressable::URI.encode(match).html_safe

View File

@ -41,14 +41,14 @@ module Banzai
pre_node.set_attribute(LANG_ATTR, escape_once(lang)) if lang.present?
pre_node.set_attribute(LANG_PARAMS_ATTR, escape_once(lang_params)) if lang_params.present?
# cmark-gfm added this, it's now in data-lang-params
# markdown rendered added this, it's now in data-lang-params
pre_node.remove_attribute('data-meta')
code_node.remove_attribute('data-meta')
end
private
# cmark-gfm's FULL_INFO_STRING render option works with the space delimiter.
# the `full_info_string` render option works with the space delimiter.
# Which means the language specified on a code block is parsed with spaces. Anything
# after the first space is placed in the `data-meta` attribute.
# However GitLab recognizes `:` as an additional delimiter on the lang attribute.
@ -67,7 +67,7 @@ module Banzai
language, language_params = language.split(LANG_PARAMS_DELIMITER, 2)
# cmark-gfm places extra lang parameters into data-meta
# markdown renderer places extra lang parameters into data-meta
language_params = [pre_node.attr('data-meta'), code_node.attr('data-meta'), language_params].compact.join(' ')
[language, language_params]

View File

@ -3,7 +3,7 @@
module Banzai
module Filter
# HTML Filter for parsing Gollum's tags in HTML.
# Only used for the ascii_doc pipeline or the older cmark parser.
# Only used for the ascii_doc pipeline.
#
# It's only parses the following tags:
#
@ -35,7 +35,7 @@ module Banzai
IGNORED_ANCESTOR_TAGS = %w[pre code tt].to_set
def call
return doc if MarkdownFilter.glfm_markdown?(context) && context[:pipeline] != :ascii_doc
return doc if context[:pipeline] != :ascii_doc
doc.xpath('descendant-or-self::text()').each do |node|
next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)

View File

@ -1,51 +0,0 @@
# frozen_string_literal: true
# `CommonMark` markdown engine for GitLab's Banzai markdown filter.
# This module is used in Banzai::Filter::MarkdownFilter.
# Used gem is `commonmarker` which is a ruby wrapper for cmark-gfm (CommonMark parser)
# including GitHub's GFM extensions.
# We now utilize the renderer built in `C`, rather than the ruby based renderer.
# Homepage: https://github.com/gjtorikian/commonmarker
#
# Although this engine is currently not actively used, let's keep it here
# for performance testing and as a backup.
module Banzai
module Filter
module MarkdownEngines
class Cmark < Base
EXTENSIONS = [
:autolink, # provides support for automatically converting URLs to anchor tags.
:strikethrough, # provides support for strikethroughs.
:table # provides support for tables.
].freeze
PARSE_OPTIONS = [
:FOOTNOTES, # parse footnotes.
:STRIKETHROUGH_DOUBLE_TILDE, # parse strikethroughs by double tildes (as redcarpet does).
:VALIDATE_UTF8 # replace illegal sequences with the replacement character U+FFFD.
].freeze
RENDER_OPTIONS = [
:GITHUB_PRE_LANG, # use GitHub-style <pre lang> for fenced code blocks.
:FOOTNOTES, # render footnotes.
:FULL_INFO_STRING, # include full info strings of code blocks in separate attribute.
:UNSAFE # allow raw/custom HTML and unsafe links.
].freeze
RENDER_OPTIONS_SOURCEPOS = RENDER_OPTIONS + [:SOURCEPOS].freeze
def render(text)
CommonMarker.render_html(text, render_options, EXTENSIONS)
end
private
def render_options
sourcepos_disabled? ? RENDER_OPTIONS : RENDER_OPTIONS_SOURCEPOS
end
end
end
end
end
Banzai::Filter::MarkdownEngines::Cmark.prepend_mod

View File

@ -4,7 +4,6 @@ module Banzai
module Filter
class MarkdownFilter < HTML::Pipeline::TextFilter
GLFM_ENGINE = :glfm_markdown # glfm_markdown/comrak
CMARK_ENGINE = :cmark # original commonmarker/cmark-gfm
DEFAULT_ENGINE = GLFM_ENGINE
def initialize(text, context = nil, result = nil)

View File

@ -43,6 +43,7 @@
- i_ci_secrets_management_id_tokens_build_created
- i_ci_secrets_management_vault_build_created
- i_ci_secrets_management_gitlab_secrets_manager_build_created
- i_ci_secrets_management_aws_secrets_manager_build_created
- i_code_review_click_diff_view_setting
- i_code_review_click_file_browser_setting
- i_code_review_click_single_file_mode_setting

View File

@ -34,7 +34,6 @@ RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures, feature_categor
let_it_be(:wiki_page) { feature.wiki_page }
let_it_be(:markdown_text) { feature.raw_markdown }
let_it_be(:glfm_engine) { Banzai::Filter::MarkdownFilter::GLFM_ENGINE }
let_it_be(:cmark_engine) { Banzai::Filter::MarkdownFilter::CMARK_ENGINE }
let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
let_it_be(:default_context) do
{
@ -85,33 +84,31 @@ RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures, feature_categor
context 'markdown engines' do
it 'benchmarks full pipeline using different markdown engines' do
puts "\n--> Benchmarking FullPipeline with Cmark and Glfm engines\n"
puts "\n--> Benchmarking FullPipeline with Glfm engine\n"
Benchmark.ips do |x|
x.config(time: 10, warmup: 2)
x.report('glfm') { Banzai::Pipeline::FullPipeline.call(markdown_text, context.merge(markdown_engine: glfm_engine)) }
x.report('cmark') { Banzai::Pipeline::FullPipeline.call(markdown_text, context.merge(markdown_engine: cmark_engine)) }
x.compare!
end
end
it 'benchmarks plain markdown pipeline using different markdown engines' do
puts "\n--> Benchmarking PlainMarkdownPipeline with Cmark and Glfm engines\n"
puts "\n--> Benchmarking PlainMarkdownPipeline with Glfm engine\n"
Benchmark.ips do |x|
x.config(time: 10, warmup: 2)
x.report('glfm') { Banzai::Pipeline::PlainMarkdownPipeline.call(markdown_text, context.merge(markdown_engine: glfm_engine)) }
x.report('cmark') { Banzai::Pipeline::PlainMarkdownPipeline.call(markdown_text, context.merge(markdown_engine: cmark_engine)) }
x.compare!
end
end
it 'benchmarks MarkdownFilter using different markdown engines' do
puts "\n--> Benchmarking MarkdownFilter with Cmark and Glfm engines\n"
puts "\n--> Benchmarking MarkdownFilter with Glfm engine\n"
pipeline = Banzai::Pipeline[:plain_markdown]
filter_klass = Banzai::Filter::MarkdownFilter
@ -127,13 +124,6 @@ RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures, feature_categor
filter.call
end
x.report('Markdown-cmark') do
filter = filter_klass.new(filter_source[filter_klass][:input_text],
context.merge(markdown_engine: cmark_engine),
filter_source[filter_klass][:input_result])
filter.call
end
x.compare!
end
end

View File

@ -25,13 +25,12 @@ describe('Merge requests app component', () => {
const findMergeRequests = () => wrapper.findAllComponents(MergeRequest);
const findLoadMoreButton = () => wrapper.findByTestId('load-more');
const findCountExplanation = () => wrapper.findByTestId('merge-request-count-explanation');
const findFeedbackLink = () => wrapper.findAllComponents(GlLink).at(0);
const $router = {
push: jest.fn(),
};
function createComponent(lists = null, listTypeToggleEnabled = false) {
function createComponent(lists = null) {
subscriptionHandler = createMockSubscription();
assigneeQueryMock = jest.fn().mockResolvedValue({
data: {
@ -106,7 +105,6 @@ describe('Merge requests app component', () => {
},
provide: {
mergeRequestsSearchDashboardPath: '/search',
listTypeToggleEnabled,
},
stubs: {
MergeRequestsQuery,
@ -260,22 +258,4 @@ describe('Merge requests app component', () => {
);
});
});
describe('feedback link', () => {
it('shows the default feedback link when feature flag is off', async () => {
createComponent();
await waitForPromises();
expect(findFeedbackLink().attributes('href')).toBe(
'https://gitlab.com/gitlab-org/gitlab/-/issues/515912',
);
});
it('shows the new feedback link when feature flag is on', async () => {
createComponent(null, { listTypeToggleEnabled: true });
await waitForPromises();
expect(findFeedbackLink().attributes('href')).toBe(
'https://gitlab.com/gitlab-org/gitlab/-/issues/542823',
);
});
});
});

View File

@ -24,11 +24,7 @@ describe('Merge request dashboard config dropdown component', () => {
const findPopover = () => wrapper.findComponent(GlPopover);
const { bindInternalEventDocument } = useMockInternalEventsTracking();
function createComponent({
isShowingLabels = false,
listTypeToggleEnabled = false,
shouldShowCallout = true,
} = {}) {
function createComponent({ isShowingLabels = false, shouldShowCallout = true } = {}) {
setIsShowingLabelsMutationMock = jest.fn();
updatePreferencesMutationMock = jest.fn().mockResolvedValue({
data: {
@ -70,7 +66,6 @@ describe('Merge request dashboard config dropdown component', () => {
wrapper = shallowMountExtended(ConfigDropdown, {
apolloProvider,
provide: { listTypeToggleEnabled },
stubs: {
UserCalloutDismisser: makeMockUserCalloutDismisser({
dismiss: userCalloutDismissSpy,
@ -207,25 +202,23 @@ describe('Merge request dashboard config dropdown component', () => {
},
);
describe('when listTypeToggleEnabled is true', () => {
it('displays explanation popover when shouldShowCallout is true', () => {
createComponent({ listTypeToggleEnabled: true, shouldShowCallout: true });
it('displays explanation popover when shouldShowCallout is true', () => {
createComponent({ shouldShowCallout: true });
expect(findPopover().exists()).toBe(true);
});
expect(findPopover().exists()).toBe(true);
});
it('does not display explanation popover when shouldShowCallout is false', () => {
createComponent({ listTypeToggleEnabled: true, shouldShowCallout: false });
it('does not display explanation popover when shouldShowCallout is false', () => {
createComponent({ shouldShowCallout: false });
expect(findPopover().exists()).toBe(false);
});
expect(findPopover().exists()).toBe(false);
});
it('calls dismiss method createComponent({ listTypeToggleEnabled: true, shouldShowCallout: true });when hiding popover', () => {
createComponent({ listTypeToggleEnabled: true, shouldShowCallout: true });
it('calls dismiss method when hiding popover', () => {
createComponent({ shouldShowCallout: true });
findPopover().vm.$emit('hidden');
findPopover().vm.$emit('hidden');
expect(userCalloutDismissSpy).toHaveBeenCalled();
});
expect(userCalloutDismissSpy).toHaveBeenCalled();
});
});

View File

@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::AutolinkFilter, feature_category: :markdown do
include FilterSpecHelper
let_it_be(:context) { { markdown_engine: Banzai::Filter::MarkdownFilter::CMARK_ENGINE } }
let_it_be(:context) { { pipeline: :single_line } }
let(:link) { 'http://about.gitlab.com/' }
let(:quotes) { ['"', "'"] }

View File

@ -83,10 +83,6 @@ RSpec.describe Banzai::Filter::GollumTagsFilter, feature_category: :wiki do
end
end
it_behaves_like 'gollum tag parsing' do
let_it_be(:context) { { markdown_engine: Banzai::Filter::MarkdownFilter::CMARK_ENGINE } }
end
it_behaves_like 'gollum tag parsing' do
let_it_be(:context) { { pipeline: :ascii_doc } }
end

View File

@ -1,17 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Banzai::Filter::MarkdownEngines::Cmark, feature_category: :markdown do
it 'defaults to generating sourcepos' do
engine = described_class.new({})
expect(engine.render('# hi')).to eq %(<h1 data-sourcepos="1:1-1:4">hi</h1>\n)
end
it 'turns off sourcepos' do
engine = described_class.new({ no_sourcepos: true })
expect(engine.render('# hi')).to eq %(<h1>hi</h1>\n)
end
end

View File

@ -8,8 +8,8 @@ RSpec.describe Banzai::Filter::MarkdownFilter, feature_category: :markdown do
describe 'markdown engine from context' do
it 'finds the correct engine' do
expect(described_class.new('foo', { markdown_engine: :cmark }).render_engine)
.to eq Banzai::Filter::MarkdownEngines::Cmark
expect(described_class.new('foo', { markdown_engine: :glfm_markdown }).render_engine)
.to eq Banzai::Filter::MarkdownEngines::GlfmMarkdown
end
it 'defaults to the GLFM_ENGINE' do

View File

@ -72,43 +72,49 @@ module Gitlab
items = {
'link with extra attribute' => {
input: 'link:mylink"onmouseover="alert(1)[Click Here]',
output: "<div>\n<p><a href=\"mylink\">Click Here</a></p>\n</div>"
output: <<~HTML
<div>
<p><a href="mylink">Click Here</a></p>
</div>
HTML
},
'link with unsafe scheme' => {
input: 'link:data://danger[Click Here]',
output: "<div>\n<p><a>Click Here</a></p>\n</div>"
output: <<~HTML
<div>
<p><a>Click Here</a></p>
</div>
HTML
},
'image with onerror' => {
input: 'image:https://localhost.com/image.png[Alt text" onerror="alert(7)]',
output: "<div>\n<p><span><a class=\"no-attachment-icon\" href=\"https://localhost.com/image.png\" target=\"_blank\" rel=\"noopener noreferrer\"><img src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt='Alt text\" onerror=\"alert(7)' decoding=\"async\" class=\"lazy\" data-src=\"https://localhost.com/image.png\"></a></span></p>\n</div>"
output: <<~HTML
<div>
<p><span><a class="no-attachment-icon" href="https://localhost.com/image.png" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt='Alt text" onerror="alert(7)' decoding="async" class="lazy" data-src="https://localhost.com/image.png"></a></span></p>
</div>
HTML
},
'fenced code with inline script' => {
input: '```mypre"><script>alert(3)</script>',
output: <<~HTML
<div>
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-canonical-lang="mypre" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code><insert-code-snippet></insert-code-snippet>
</div>
</div>
</div>
HTML
}
}
items.each do |name, data|
it "does not convert dangerous #{name} into HTML" do
expect(render(data[:input], context)).to include(data[:output])
expect(render(data[:input], context)).to include(data[:output].strip)
end
end
# `stub_feature_flags method` runs AFTER declaration of `items` above.
# So the spec in its current implementation won't pass.
# Move this test back to the items hash when removing `use_cmark_renderer` feature flag.
it "does not convert dangerous fenced code with inline script into HTML" do
input = '```mypre"><script>alert(3)</script>'
output = <<~HTML
<div>
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-canonical-lang="mypre" class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code></code></pre>
<copy-code></copy-code><insert-code-snippet></insert-code-snippet>
</div>
</div>
</div>
HTML
expect(render(input, context)).to include(output.strip)
end
it 'does not allow locked attributes to be overridden' do
input = <<~ADOC
{counter:max-include-depth:1234}