summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile.lock2
-rw-r--r--app/assets/stylesheets/framework/files.scss18
-rw-r--r--app/assets/stylesheets/pages/commits.scss29
-rw-r--r--app/helpers/blob_helper.rb14
-rw-r--r--app/services/merge_requests/merge_service.rb6
-rw-r--r--app/views/projects/blob/_header.html.haml6
-rw-r--r--app/views/projects/blob/_viewer_switcher.html.haml6
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--changelogs/unreleased/273288-update-blob-page-buttons.yml5
-rw-r--r--changelogs/unreleased/30141-merge-error-msg-update.yml5
-rw-r--r--changelogs/unreleased/asciidoctor-2-0-12.yml5
-rw-r--r--changelogs/unreleased/sh-prepend-marginalia-comments.yml5
-rw-r--r--config/initializers/0_marginalia.rb5
-rw-r--r--doc/administration/auth/oidc.md41
-rw-r--r--doc/integration/azure.md4
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md6
-rw-r--r--lib/banzai/filter/plantuml_filter.rb2
-rw-r--r--spec/benchmarks/banzai_benchmark.rb182
-rw-r--r--spec/features/markdown/markdown_spec.rb27
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/fixtures/markdown.md.erb14
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb12
-rw-r--r--spec/support/matchers/markdown_matchers.rb27
23 files changed, 267 insertions, 158 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index d7d91a92015..3962fe27073 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -81,7 +81,7 @@ GEM
faraday_middleware (~> 1.0)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.4)
- asciidoctor (2.0.10)
+ asciidoctor (2.0.12)
asciidoctor-include-ext (0.3.1)
asciidoctor (>= 1.5.6, < 3.0.0)
asciidoctor-kroki (0.2.2)
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 103d59382b4..bda123fa7ea 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -353,23 +353,17 @@ span.idiff {
color: $gl-text-color;
}
- .file-actions .btn:not(.btn-icon) {
- padding: 0 10px;
- font-size: 13px;
- line-height: 28px;
- display: inline-block;
- float: none;
- }
-
.file-actions .ide-edit-button {
z-index: 2;
}
- @include media-breakpoint-down(sm) {
- display: block;
-
+ @include media-breakpoint-down(md) {
.file-actions {
- margin-top: 5px;
+ margin-top: $gl-padding-8;
+
+ .btn {
+ margin-bottom: $gl-padding-8;
+ }
}
}
}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 9b17da80023..226c7867eca 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -108,30 +108,6 @@
}
}
-.text-expander {
- display: inline-flex;
- background: $white;
- color: $gl-text-color-secondary;
- padding: 1px $gl-padding-4;
- cursor: pointer;
- border: 1px solid $border-white-normal;
- border-radius: $border-radius-default;
- margin-left: 5px;
- font-size: 12px;
- line-height: $gl-font-size;
- outline: none;
-
- &.open {
- background-color: darken($gray-light, 10%);
- box-shadow: inset 0 0 2px rgba($black, 0.2);
- }
-
- &:hover {
- background-color: darken($gray-light, 10%);
- text-decoration: none;
- }
-}
-
.commit.flex-list {
display: flex;
}
@@ -240,11 +216,6 @@
.commit,
.generic-commit-status {
- a,
- button {
- vertical-align: baseline;
- }
-
a {
color: $gl-text-color;
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 3435dfcf317..28a947a6ca1 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -64,7 +64,7 @@ module BlobHelper
def edit_blob_button(project = @project, ref = @ref, path = @path, options = {})
return unless blob = readable_blob(options, path, project, ref)
- common_classes = "btn gl-button btn-confirm js-edit-blob gl-mr-3 #{options[:extra_class]}"
+ common_classes = "btn gl-button btn-confirm js-edit-blob gl-ml-3 #{options[:extra_class]}"
data = { track_event: 'click_edit', track_label: 'Edit' }
if Feature.enabled?(:web_ide_primary_edit, project.group)
@@ -84,7 +84,7 @@ module BlobHelper
def ide_edit_button(project = @project, ref = @ref, path = @path, blob:)
return unless blob
- common_classes = 'btn gl-button btn-confirm ide-edit-button gl-mr-3'
+ common_classes = 'btn gl-button btn-confirm ide-edit-button gl-ml-3'
data = { track_event: 'click_edit_ide', track_label: 'Web IDE' }
unless Feature.enabled?(:web_ide_primary_edit, project.group)
@@ -229,13 +229,13 @@ module BlobHelper
end
def copy_file_path_button(file_path)
- clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'btn-clipboard btn-transparent', title: _('Copy file path'))
+ clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'gl-button btn btn-default-tertiary btn-icon btn-sm', title: _('Copy file path'))
end
def copy_blob_source_button(blob)
return unless blob.rendered_as_text?(ignore_errors: false)
- clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}'] > pre", class: "btn gl-button btn-default btn-sm js-copy-blob-source-btn", title: _("Copy file contents"))
+ clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}'] > pre", class: "btn gl-button btn-default btn-icon js-copy-blob-source-btn", title: _("Copy file contents"))
end
def open_raw_blob_button(blob)
@@ -245,7 +245,7 @@ module BlobHelper
title = _('Open raw')
link_to sprite_icon('doc-code'),
external_storage_url_or_path(blob_raw_path),
- class: 'btn gl-button btn-default btn-sm has-tooltip',
+ class: 'btn gl-button btn-default btn-icon has-tooltip',
target: '_blank',
rel: 'noopener noreferrer',
aria: { label: title },
@@ -260,7 +260,7 @@ module BlobHelper
link_to sprite_icon('download'),
external_storage_url_or_path(blob_raw_path(inline: false)),
download: @path,
- class: 'btn gl-button btn-default btn-sm has-tooltip',
+ class: 'btn gl-button btn-default btn-icon has-tooltip',
target: '_blank',
rel: 'noopener noreferrer',
aria: { label: title },
@@ -361,7 +361,7 @@ module BlobHelper
end
def edit_link_tag(link_text, edit_path, common_classes, data)
- link_to link_text, edit_path, class: "#{common_classes} btn-sm", data: data
+ link_to link_text, edit_path, class: "#{common_classes}", data: data
end
def edit_button_tag(blob, common_classes, text, edit_path, project, ref, data)
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index f4454db0af8..fc4405ef704 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -8,6 +8,8 @@ module MergeRequests
# Executed when you do merge via GitLab UI
#
class MergeService < MergeRequests::MergeBaseService
+ GENERIC_ERROR_MESSAGE = 'An error occurred while merging'
+
delegate :merge_jid, :state, to: :@merge_request
def execute(merge_request, options = {})
@@ -79,7 +81,7 @@ module MergeRequests
if commit_id
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
else
- raise_error('Conflicts detected during merge')
+ raise_error(GENERIC_ERROR_MESSAGE)
end
merge_request.update!(merge_commit_sha: commit_id)
@@ -96,7 +98,7 @@ module MergeRequests
"Something went wrong during merge pre-receive hook. #{e.message}".strip
rescue => e
handle_merge_error(log_message: e.message)
- raise_error('Something went wrong during merge')
+ raise_error(GENERIC_ERROR_MESSAGE)
end
def after_merge
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index 6d01206a128..7adb91f1fe6 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -2,19 +2,19 @@
.js-file-title.file-title-flex-parent
= render 'projects/blob/header_content', blob: blob
- .file-actions.gl-display-flex.gl-flex-fill-1.gl-align-self-start.gl-md-justify-content-end<
+ .file-actions.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-md-justify-content-end<
= render 'projects/blob/viewer_switcher', blob: blob unless blame
- if Feature.enabled?(:consolidated_edit_button, @project)
= render 'shared/web_ide_button', blob: blob
- else
= edit_blob_button(@project, @ref, @path, blob: blob)
= ide_edit_button(@project, @ref, @path, blob: blob)
- .btn-group.ml-2{ role: "group" }>
+ .btn-group{ role: "group", class: ("gl-ml-3" if current_user) }>
= render_if_exists 'projects/blob/header_file_locks_link'
- if current_user
= replace_blob_link(@project, @ref, @path, blob: blob)
= delete_blob_link(@project, @ref, @path, blob: blob)
- .btn-group.ml-2{ role: "group" }
+ .btn-group.gl-ml-3{ role: "group" }
= copy_blob_source_button(blob) unless blame
= open_raw_blob_button(blob)
= download_blob_button(blob)
diff --git a/app/views/projects/blob/_viewer_switcher.html.haml b/app/views/projects/blob/_viewer_switcher.html.haml
index c6b13deaece..043b8629289 100644
--- a/app/views/projects/blob/_viewer_switcher.html.haml
+++ b/app/views/projects/blob/_viewer_switcher.html.haml
@@ -2,11 +2,11 @@
- simple_viewer = blob.simple_viewer
- rich_viewer = blob.rich_viewer
- .btn-group.js-blob-viewer-switcher.ml-2{ role: "group" }>
+ .btn-group.js-blob-viewer-switcher.gl-ml-3{ role: "group" }>
- simple_label = "Display #{simple_viewer.switcher_title}"
- %button.btn.gl-button.btn-default.btn-sm.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => simple_label, title: simple_label, data: { viewer: 'simple', container: 'body' } }>
+ %button.btn.gl-button.btn-default.btn-icon.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => simple_label, title: simple_label, data: { viewer: 'simple', container: 'body' } }>
= sprite_icon(simple_viewer.switcher_icon)
- rich_label = "Display #{rich_viewer.switcher_title}"
- %button.btn.gl-button.btn-default.btn-sm.js-blob-viewer-switch-btn.gl-mr-3.has-tooltip{ 'aria-label' => rich_label, title: rich_label, data: { viewer: 'rich', container: 'body' } }>
+ %button.btn.gl-button.btn-default.btn-icon.js-blob-viewer-switch-btn.has-tooltip{ 'aria-label' => rich_label, title: rich_label, data: { viewer: 'rich', container: 'body' } }>
= sprite_icon(rich_viewer.switcher_icon)
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 179b0c5efbd..c708efe7c7b 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -32,7 +32,7 @@
&middot;
= commit.short_id
- if commit.description? && collapsible
- %button.text-expander.js-toggle-button
+ %button.gl-button.btn.btn-default.button-ellipsis-horizontal.btn-sm.gl-ml-2.text-expander.js-toggle-button
= sprite_icon('ellipsis_h', size: 12)
.committer
diff --git a/changelogs/unreleased/273288-update-blob-page-buttons.yml b/changelogs/unreleased/273288-update-blob-page-buttons.yml
new file mode 100644
index 00000000000..6e1b7bcc1b0
--- /dev/null
+++ b/changelogs/unreleased/273288-update-blob-page-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Update blob page buttons to gitlab-ui pajamas styles
+merge_request: 53775
+author:
+type: changed
diff --git a/changelogs/unreleased/30141-merge-error-msg-update.yml b/changelogs/unreleased/30141-merge-error-msg-update.yml
new file mode 100644
index 00000000000..4abe2c6ebf6
--- /dev/null
+++ b/changelogs/unreleased/30141-merge-error-msg-update.yml
@@ -0,0 +1,5 @@
+---
+title: Show more appropriate error message when merging fails
+merge_request: 52671
+author:
+type: fixed
diff --git a/changelogs/unreleased/asciidoctor-2-0-12.yml b/changelogs/unreleased/asciidoctor-2-0-12.yml
new file mode 100644
index 00000000000..0ee92803fc5
--- /dev/null
+++ b/changelogs/unreleased/asciidoctor-2-0-12.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Asciidoctor to 2.0.12
+merge_request: 54121
+author: Guillaume Grossetie
+type: changed
diff --git a/changelogs/unreleased/sh-prepend-marginalia-comments.yml b/changelogs/unreleased/sh-prepend-marginalia-comments.yml
new file mode 100644
index 00000000000..3ebdd0527ec
--- /dev/null
+++ b/changelogs/unreleased/sh-prepend-marginalia-comments.yml
@@ -0,0 +1,5 @@
+---
+title: Prepend the Marginalia comment in SQL query
+merge_request: 54015
+author:
+type: changed
diff --git a/config/initializers/0_marginalia.rb b/config/initializers/0_marginalia.rb
index 5c6cf7752c4..952dd75886d 100644
--- a/config/initializers/0_marginalia.rb
+++ b/config/initializers/0_marginalia.rb
@@ -9,6 +9,11 @@ require 'marginalia'
# Refer: https://github.com/basecamp/marginalia/blob/v1.8.0/lib/marginalia/railtie.rb#L67
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Marginalia::ActiveRecordInstrumentation)
+# By default, PostgreSQL only tracks the first 1024 bytes of a SQL
+# query. Prepending the comment allows us to trace the source of the
+# query without having to increase the `track_activity_query_size`
+# parameter.
+Marginalia::Comment.prepend_comment = true unless Rails.env.test? # Some tests do string matching against raw SQL
Marginalia::Comment.components = [:application, :controller, :action, :correlation_id, :jid, :job_class]
# As mentioned in https://github.com/basecamp/marginalia/pull/93/files,
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 1ddf75e7c1b..cde8944fadc 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -130,8 +130,7 @@ different providers with Omnibus GitLab.
### Google
-See the [Google
-documentation](https://developers.google.com/identity/protocols/oauth2/openid-connect)
+See the [Google documentation](https://developers.google.com/identity/protocols/oauth2/openid-connect)
for more details:
```ruby
@@ -156,6 +155,44 @@ for more details:
}
```
+### Microsoft Azure
+
+The OpenID Connect (OIDC) protocol for Microsoft Azure uses the [Microsoft identity platform (v2) endpoints](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/azure-ad-endpoint-comparison).
+To get started, sign in to the [Azure Portal](https://portal.azure.com). For your app, you'll need the
+following information:
+
+- A tenant ID. You may already have one. For more information, review the
+ [Microsoft Azure Tenant](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant) documentation.
+- A client ID and a client secret. Follow the instructions in the
+ [Microsoft Quickstart Register an Application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) documentation.
+to obtain the tenant ID, client ID, and client secret for your app.
+
+Example Omnibus configuration block:
+
+```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ 'name' => 'openid_connect',
+ 'label' => 'Azure OIDC',
+ 'args' => {
+ 'name' => 'openid_connect',
+ 'scope' => ['openid', 'profile', 'email'],
+ 'response_type' => 'code',
+ 'issuer' => 'https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0',
+ 'client_auth_method' => 'query',
+ 'discovery' => true,
+ 'uid_field' => 'preferred_username',
+ 'client_options' => {
+ 'identifier' => '<YOUR APP CLIENT ID>',
+ 'secret' => '<YOUR APP CLIENT SECRET>',
+ 'redirect_uri' => 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ }
+ }
+ }
+```
+
+Microsoft has documented how its platform works with [the OIDC protocol](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc).
+
## Troubleshooting
If you're having trouble, here are some tips:
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index f22a94a01c7..c83ef650f54 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -6,6 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Microsoft Azure OAuth2 OmniAuth Provider
+NOTE:
+Per Microsoft, this provider uses the [older Azure Active Directory v1.0 endpoint](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/v1-protocols-oauth-code).
+Microsoft documentation suggests that you should use the [OpenID Connect protocol to use the v2 endpoints](../administration/auth/oidc.md#microsoft-azure) for new projects.
+
To enable the Microsoft Azure OAuth2 OmniAuth provider, you must register your application with Azure. Azure generates a client ID and secret key for you to use.
Sign in to the [Azure Portal](https://portal.azure.com), and follow the instructions in
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index f8e9be9b628..0fcdbf3ca90 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -124,10 +124,10 @@ For more details on group visibility, see [Public access](../../../public_access
## Restricted visibility levels
-To set the available visibility levels for projects, snippets, and selected pages:
+To set the restricted visibility levels for projects, snippets, and selected pages:
-1. Check the desired visibility levels.
-1. Click **Save changes**.
+1. Select the desired visibility levels to restrict.
+1. Select **Save changes**.
For more details on project visibility, see [Public access](../../../public_access/public_access.md).
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index 1a75cd14b11..37d4126c1ba 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -9,7 +9,7 @@ module Banzai
#
class PlantumlFilter < HTML::Pipeline::Filter
def call
- return doc unless doc.at('pre > code[lang="plantuml"]') && settings.plantuml_enabled
+ return doc unless settings.plantuml_enabled? && doc.at('pre > code[lang="plantuml"]')
plantuml_setup
diff --git a/spec/benchmarks/banzai_benchmark.rb b/spec/benchmarks/banzai_benchmark.rb
index e489237a2f2..a87414ba512 100644
--- a/spec/benchmarks/banzai_benchmark.rb
+++ b/spec/benchmarks/banzai_benchmark.rb
@@ -1,114 +1,124 @@
# frozen_string_literal: true
-if ENV.key?('BENCHMARK')
- require 'spec_helper'
- require 'erb'
- require 'benchmark/ips'
-
- # This benchmarks some of the Banzai pipelines and filters.
- # They are not definitive, but can be used by a developer to
- # get a rough idea how the changing or addition of a new filter
- # will effect performance.
- #
- # Run by:
- # BENCHMARK=1 rspec spec/benchmarks/banzai_benchmark.rb
- # or
- # rake benchmark:banzai
- #
- RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures do
- include MarkupHelper
-
- let_it_be(:feature) { MarkdownFeature.new }
- let_it_be(:project) { feature.project }
- let_it_be(:group) { feature.group }
- let_it_be(:wiki) { feature.wiki }
- let_it_be(:wiki_page) { feature.wiki_page }
- let_it_be(:markdown_text) { feature.raw_markdown }
-
- let!(:render_context) { Banzai::RenderContext.new(project, current_user) }
-
- before do
- stub_application_setting(asset_proxy_enabled: true)
- stub_application_setting(asset_proxy_secret_key: 'shared-secret')
- stub_application_setting(asset_proxy_url: 'https://assets.example.com')
- stub_application_setting(asset_proxy_whitelist: %w(gitlab.com *.mydomain.com))
-
- Banzai::Filter::AssetProxyFilter.initialize_settings
- end
+return unless ENV.key?('BENCHMARK')
+
+require 'spec_helper'
+require 'erb'
+require 'benchmark/ips'
+
+# This benchmarks some of the Banzai pipelines and filters.
+# They are not definitive, but can be used by a developer to
+# get a rough idea how the changing or addition of a new filter
+# will effect performance.
+#
+# Run by:
+# BENCHMARK=1 rspec spec/benchmarks/banzai_benchmark.rb
+# or
+# rake benchmark:banzai
+#
+# rubocop: disable RSpec/TopLevelDescribePath
+RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures do
+ include MarkupHelper
+
+ let_it_be(:feature) { MarkdownFeature.new }
+ let_it_be(:project) { feature.project }
+ let_it_be(:group) { feature.group }
+ let_it_be(:wiki) { feature.wiki }
+ let_it_be(:wiki_page) { feature.wiki_page }
+ let_it_be(:markdown_text) { feature.raw_markdown }
+ let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
+ let_it_be(:default_context) do
+ {
+ project: project,
+ current_user: current_user,
+ suggestions_filter_enabled: true
+ }
+ end
- context 'pipelines' do
- it 'benchmarks several pipelines' do
- path = 'images/example.jpg'
- gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
- allow(wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
- allow(wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
+ let(:context) do
+ Banzai::Filter::AssetProxyFilter.transform_context(default_context)
+ end
- puts "\n--> Benchmarking Full, Wiki, and Plain pipelines\n"
+ let!(:render_context) { Banzai::RenderContext.new(project, current_user) }
- Benchmark.ips do |x|
- x.config(time: 10, warmup: 2)
+ before do
+ stub_application_setting(asset_proxy_enabled: true)
+ stub_application_setting(asset_proxy_secret_key: 'shared-secret')
+ stub_application_setting(asset_proxy_url: 'https://assets.example.com')
+ stub_application_setting(asset_proxy_whitelist: %w(gitlab.com *.mydomain.com))
+ stub_application_setting(plantuml_enabled: true, plantuml_url: 'http://localhost:8080')
+ stub_application_setting(kroki_enabled: true, kroki_url: 'http://localhost:8000')
- x.report('Full pipeline') { markdown(markdown_text, { pipeline: :full }) }
- x.report('Wiki pipeline') { markdown(markdown_text, { pipeline: :wiki, wiki: wiki, page_slug: wiki_page.slug }) }
- x.report('Plain pipeline') { markdown(markdown_text, { pipeline: :plain_markdown }) }
+ Banzai::Filter::AssetProxyFilter.initialize_settings
+ end
- x.compare!
- end
- end
- end
+ context 'pipelines' do
+ it 'benchmarks several pipelines' do
+ path = 'images/example.jpg'
+ gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
+ allow(wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
+ allow(wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
- context 'filters' do
- let(:context) do
- tmp = { project: project, current_user: current_user, render_context: render_context }
- Banzai::Filter::AssetProxyFilter.transform_context(tmp)
- end
+ puts "\n--> Benchmarking Full, Wiki, and Plain pipelines\n"
- it 'benchmarks all filters in the FullPipeline' do
- benchmark_pipeline_filters(:full)
- end
+ Benchmark.ips do |x|
+ x.config(time: 10, warmup: 2)
+
+ x.report('Full pipeline') { Banzai::Pipeline::FullPipeline.call(markdown_text, context) }
+ x.report('Wiki pipeline') { Banzai::Pipeline::WikiPipeline.call(markdown_text, context.merge(wiki: wiki, page_slug: wiki_page.slug)) }
+ x.report('Plain pipeline') { Banzai::Pipeline::PlainMarkdownPipeline.call(markdown_text, context) }
- it 'benchmarks all filters in the PlainMarkdownPipeline' do
- benchmark_pipeline_filters(:plain_markdown)
+ x.compare!
end
end
+ end
- # build up the source text for each filter
- def build_filter_text(pipeline, initial_text)
- filter_source = {}
- input_text = initial_text
+ context 'filters' do
+ it 'benchmarks all filters in the FullPipeline' do
+ benchmark_pipeline_filters(:full)
+ end
- pipeline.filters.each do |filter_klass|
- filter_source[filter_klass] = input_text
+ it 'benchmarks all filters in the PlainMarkdownPipeline' do
+ benchmark_pipeline_filters(:plain_markdown)
+ end
+ end
- output = filter_klass.call(input_text, context)
- input_text = output
- end
+ # build up the source text for each filter
+ def build_filter_text(pipeline, initial_text)
+ filter_source = {}
+ input_text = initial_text
- filter_source
+ pipeline.filters.each do |filter_klass|
+ filter_source[filter_klass] = input_text
+
+ output = filter_klass.call(input_text, context)
+ input_text = output
end
- def benchmark_pipeline_filters(pipeline_type)
- pipeline = Banzai::Pipeline[pipeline_type]
- filter_source = build_filter_text(pipeline, markdown_text)
+ filter_source
+ end
- puts "\n--> Benchmarking #{pipeline.name.demodulize} filters\n"
+ def benchmark_pipeline_filters(pipeline_type)
+ pipeline = Banzai::Pipeline[pipeline_type]
+ filter_source = build_filter_text(pipeline, markdown_text)
- Benchmark.ips do |x|
- x.config(time: 10, warmup: 2)
+ puts "\n--> Benchmarking #{pipeline.name.demodulize} filters\n"
- pipeline.filters.each do |filter_klass|
- label = filter_klass.name.demodulize.delete_suffix('Filter').truncate(20)
+ Benchmark.ips do |x|
+ x.config(time: 10, warmup: 2)
- x.report(label) { filter_klass.call(filter_source[filter_klass], context) }
- end
+ pipeline.filters.each do |filter_klass|
+ label = filter_klass.name.demodulize.delete_suffix('Filter').truncate(20)
- x.compare!
+ x.report(label) { filter_klass.call(filter_source[filter_klass], context) }
end
- end
- # Fake a `current_user` helper
- def current_user
- feature.user
+ x.compare!
end
end
+
+ # Fake a `current_user` helper
+ def current_user
+ feature.user
+ end
end
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index 151ef76e884..8e28f89f49e 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -206,6 +206,9 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
# `markdown` helper expects a `@project` and `@group` variable
@project = @feat.project
@group = @feat.group
+
+ stub_application_setting(plantuml_enabled: true, plantuml_url: 'http://localhost:8080')
+ stub_application_setting(kroki_enabled: true, kroki_url: 'http://localhost:8000')
end
let(:project) { @feat.project } # Shadow this so matchers can use it
@@ -265,6 +268,18 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
aggregate_failures 'ColorFilter' do
expect(doc).to parse_colors
end
+
+ aggregate_failures 'MermaidFilter' do
+ expect(doc).to parse_mermaid
+ end
+
+ aggregate_failures 'PlantumlFilter' do
+ expect(doc).to parse_plantuml
+ end
+
+ aggregate_failures 'KrokiFilter' do
+ expect(doc).to parse_kroki
+ end
end
end
@@ -338,6 +353,18 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
aggregate_failures 'ColorFilter' do
expect(doc).to parse_colors
end
+
+ aggregate_failures 'MermaidFilter' do
+ expect(doc).to parse_mermaid
+ end
+
+ aggregate_failures 'PlantumlFilter' do
+ expect(doc).to parse_plantuml
+ end
+
+ aggregate_failures 'KrokiFilter' do
+ expect(doc).to parse_kroki
+ end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 34689c084f2..0854a8b9fb7 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -388,7 +388,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
click_button 'Merge'
page.within('.mr-widget-body') do
- expect(page).to have_content('Conflicts detected during merge')
+ expect(page).to have_content('An error occurred while merging')
end
end
end
diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
index 30ae58dbf9e..100d17cc16e 100644
--- a/spec/fixtures/markdown.md.erb
+++ b/spec/fixtures/markdown.md.erb
@@ -358,3 +358,17 @@ For details see the [Mermaid official page][mermaid].
[mermaid]: https://mermaidjs.github.io/ "Mermaid website"
+### PLantUML
+
+```plantuml
+Bob -> Sara : Hello
+```
+
+### Kroki
+
+```nomnoml
+[Pirate|eyeCount: Int|raid();pillage()|
+ [beard]--[parrot]
+ [beard]-:>[foul mouth]
+]
+```
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index a4c70ac0266..611f12c8146 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -310,12 +310,12 @@ RSpec.describe MergeRequests::MergeService do
it 'logs and saves error if there is an exception' do
error_message = 'error message'
- allow(service).to receive(:repository).and_raise('error message')
+ allow(service).to receive(:repository).and_raise(error_message)
allow(service).to receive(:execute_hooks)
service.execute(merge_request)
- expect(merge_request.merge_error).to include('Something went wrong during merge')
+ expect(merge_request.merge_error).to eq(described_class::GENERIC_ERROR_MESSAGE)
expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
end
@@ -343,9 +343,7 @@ RSpec.describe MergeRequests::MergeService do
expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
end
- it 'logs and saves error if there is a merge conflict' do
- error_message = 'Conflicts detected during merge'
-
+ it 'logs and saves error if commit is not created' do
allow_any_instance_of(Repository).to receive(:merge).and_return(false)
allow(service).to receive(:execute_hooks)
@@ -353,8 +351,8 @@ RSpec.describe MergeRequests::MergeService do
expect(merge_request).to be_open
expect(merge_request.merge_commit_sha).to be_nil
- expect(merge_request.merge_error).to include(error_message)
- expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ expect(merge_request.merge_error).to include(described_class::GENERIC_ERROR_MESSAGE)
+ expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(described_class::GENERIC_ERROR_MESSAGE))
end
context 'when squashing is required' do
diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb
index 6e75fa58700..47cffad8c41 100644
--- a/spec/support/matchers/markdown_matchers.rb
+++ b/spec/support/matchers/markdown_matchers.rb
@@ -246,6 +246,33 @@ module MarkdownMatchers
end
end
end
+
+ # MermaidFilter
+ matcher :parse_mermaid do
+ set_default_markdown_messages
+
+ match do |actual|
+ expect(actual).to have_selector('code.js-render-mermaid')
+ end
+ end
+
+ # PLantumlFilter
+ matcher :parse_plantuml do
+ set_default_markdown_messages
+
+ match do |actual|
+ expect(actual).to have_link(href: 'http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd9vm80EtS5lW00')
+ end
+ end
+
+ # KrokiFilter
+ matcher :parse_kroki do
+ set_default_markdown_messages
+
+ match do |actual|
+ expect(actual).to have_link(href: 'http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KzhUlCITkpNLEqJ1dWNLkgsKsoviUUSs7KLTssvzVHIzS8tyYjligUAMhEd0g==')
+ end
+ end
end
# Monkeypatch the matcher DSL so that we can reduce some noisy duplication for